]> git.mxchange.org Git - friendica-addons.git/blob - securemail/php-gpg/libs/GPG.php
New experimental plugin 'secure mail'
[friendica-addons.git] / securemail / php-gpg / libs / GPG.php
1 <?php\r
2 /** @package    php-gpg */\r
3 \r
4 /** require supporting files */\r
5 require_once("GPG/Expanded_Key.php");\r
6 require_once("GPG/Public_Key.php");\r
7 require_once("GPG/AES.php");\r
8 require_once("GPG/globals.php");\r
9 \r
10 /**\r
11  * Pure PHP implementation of PHP/GPG encryption.  \r
12  * Supports RSA, DSA public key length of 2,4,8,16,512,1024,2048 or 4096\r
13  * Currently supports only encrypt\r
14  *\r
15  * @package php-gpg::Encryption\r
16  * @link http://www.verysimple.com/\r
17  * @copyright 1997-2012 VerySimple, Inc.\r
18  * @license http://www.gnu.org/licenses/gpl.html  GPL\r
19  * @todo implement decryption\r
20  * @version 1.1\r
21  * \r
22  * @example \r
23  *              require_once 'libs/GPG.php';\r
24  *              $gpg = new GPG();\r
25  *              $pub_key = new GPG_Public_Key($public_key_ascii);\r
26  *              $encrypted = $gpg->encrypt($pub_key,$plain_text_string);\r
27  */\r
28 class GPG \r
29 {\r
30 \r
31         private $width = 16;\r
32         private $el = array(3, 5, 9, 17, 513, 1025, 2049, 4097);\r
33         private $version = "1.4.7";\r
34 \r
35         private function gpg_encrypt($key, $text) {\r
36 \r
37                 $i = 0;\r
38                 $i = 0;\r
39                 $len = strlen($text);\r
40                 $len = strlen($text);\r
41                 $iblock = array_fill(0, $this->width, 0);\r
42                 $rblock = array_fill(0, $this->width, 0);\r
43                 $ct = array_fill(0, $this->width + 2, 0);\r
44          \r
45                 $cipher = "";\r
46 \r
47                 if($len % $this->width) {\r
48                         for($i = ($len % $this->width); $i < $this->width; $i++) $text .= "\0";\r
49                 }\r
50          \r
51                 $ekey = new Expanded_Key($key);\r
52 \r
53                 for($i = 0; $i < $this->width; $i++) {\r
54                         $iblock[$i] = 0;\r
55                         $rblock[$i] = GPG_Utility::c_random();\r
56                 }\r
57 \r
58 \r
59                 $iblock = GPG_AES::encrypt($iblock, $ekey);\r
60                 for($i = 0; $i < $this->width; $i++) {\r
61                         $ct[$i] = ($iblock[$i] ^= $rblock[$i]);\r
62                 }\r
63 \r
64                 $iblock = GPG_AES::encrypt($iblock, $ekey);\r
65                 $ct[$this->width]   = ($iblock[0] ^ $rblock[$this->width - 2]);\r
66                 $ct[$this->width + 1] = ($iblock[1] ^ $rblock[$this->width - 1]);\r
67          \r
68                 for($i = 0; $i < $this->width + 2; $i++) $cipher .= chr($ct[$i]);\r
69 \r
70                 $iblock = array_slice($ct, 2, $this->width + 2);\r
71 \r
72                 for($n = 0; $n < strlen($text); $n += $this->width) {\r
73                         $iblock = GPG_AES::encrypt($iblock, $ekey);\r
74                         for($i = 0; $i < $this->width; $i++) {\r
75                                 $iblock[$i] ^= ord($text[$n + $i]);\r
76                                 $cipher .= chr($iblock[$i]);\r
77                         }\r
78                 }\r
79          \r
80                 return substr($cipher, 0, $len + $this->width + 2);\r
81         }\r
82 \r
83         private function gpg_header($tag, $len)\r
84         {\r
85                 if ($len > 0xff) $tag += 1;\r
86                 $h = chr($tag);\r
87                 if ($len > 0xff) $h .= chr($len / 0x100);\r
88                 $h .= chr($len % 0x100);\r
89 \r
90                 return $h;\r
91         }\r
92 \r
93         private function gpg_session($key_id, $key_type, $session_key, $public_key)\r
94         { \r
95 \r
96                 $mod = array();\r
97                 $exp = array();\r
98                 $enc = "";\r
99          \r
100                 $s = base64_decode($public_key);\r
101                 $l = floor((ord($s[0]) * 256 + ord($s[1]) + 7) / 8);\r
102                 $mod = mpi2b(substr($s, 0, $l + 2));\r
103                 if($key_type) {\r
104                         $grp = array();\r
105                         $y = array();\r
106                         $B = array();\r
107                         $C = array();\r
108 \r
109                         $l2 = floor((ord($s[$l + 2]) * 256 + ord($s[$l + 3]) + 7) / 8) + 2;\r
110                         $grp = mpi2b(substr($s, $l + 2, $l2));\r
111                         $y = mpi2b(substr($s, $l + 2 + $l2));\r
112                         $exp[0] = $this->el[GPG_Utility::c_random() & 7];\r
113                         $B = bmodexp($grp, $exp, $mod);\r
114                         $C = bmodexp($y, $exp, $mod);\r
115                 } else {\r
116                         $exp = mpi2b(substr($s, $l + 2));\r
117                 }\r
118 \r
119                 $c = 0;\r
120                 $lsk = strlen($session_key);\r
121                 for($i = 0; $i < $lsk; $i++) $c += ord($session_key[$i]);\r
122                 $c &= 0xffff;\r
123 \r
124                 $lm = ($l - 2) * 8 + 2;\r
125                 $m = chr($lm / 256) . chr($lm % 256) .\r
126                         chr(2) . GPG_Utility::s_random($l - $lsk - 6, 1) . "\0" .\r
127                         chr(7) . $session_key .\r
128                         chr($c / 256) . chr($c & 0xff);\r
129 \r
130                 if($key_type) {\r
131                         $enc = b2mpi($B) . b2mpi(bmod(bmul(mpi2b($m), $C), $mod));\r
132                         return $this->gpg_header(0x84,strlen($enc) + 10) .\r
133                                 chr(3) . $key_id . chr(16) . $enc;\r
134                 } else {\r
135                         $enc = b2mpi(bmodexp(mpi2b($m), $exp, $mod));\r
136                         return $this->gpg_header(0x84, strlen($enc) + 10) .\r
137                                 chr(3) . $key_id . chr(1) . $enc;\r
138                 }\r
139         }\r
140 \r
141         private function gpg_literal($text)\r
142         {\r
143                 if (strpos($text, "\r\n") === false)\r
144                         $text = str_replace("\n", "\r\n", $text);\r
145 \r
146                 return\r
147                 $this->gpg_header(0xac, strlen($text) + 10) . "t" .\r
148                         chr(4) . "file\0\0\0\0" . $text;\r
149         }\r
150 \r
151         private function gpg_data($key, $text)\r
152         {\r
153                 $enc = $this->gpg_encrypt($key, $this->gpg_literal($text));\r
154                 return $this->gpg_header(0xa4, strlen($enc)) . $enc;\r
155         }\r
156 \r
157         /**\r
158          * GPG Encypts a message to the provided public key\r
159          *\r
160          * @param GPG_Public_Key $pk\r
161          * @param string $plaintext\r
162          * @return string encrypted text\r
163          */\r
164         function encrypt($pk, $plaintext)\r
165         {\r
166                 // normalize the public key\r
167                 $key_id = $pk->GetKeyId();\r
168                 $key_type = $pk->GetKeyType();\r
169                 $public_key = $pk->GetPublicKey();\r
170 \r
171                 $session_key = GPG_Utility::s_random($this->width, 0);\r
172                 $key_id = GPG_Utility::hex2bin($key_id);\r
173                 $cp = $this->gpg_session($key_id, $key_type, $session_key, $public_key) .\r
174                         $this->gpg_data($session_key, $plaintext);\r
175 \r
176                 $code = base64_encode($cp);\r
177                 $code = wordwrap($code, 60, "\n", 1);\r
178 \r
179                 return\r
180                         "-----BEGIN PGP MESSAGE-----\nVersion: VerySimple PHP-GPG v".$this->version."\n\n" .\r
181                         $code . "\n=" . base64_encode(GPG_Utility::crc24($cp)) .\r
182                         "\n-----END PGP MESSAGE-----\n";\r
183         }\r
184 }\r
185 \r
186 ?>