2 /** @package php-gpg */
\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
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
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
23 * require_once 'libs/GPG.php';
\r
25 * $pub_key = new GPG_Public_Key($public_key_ascii);
\r
26 * $encrypted = $gpg->encrypt($pub_key,$plain_text_string);
\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
35 private function gpg_encrypt($key, $text) {
\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
47 if($len % $this->width) {
\r
48 for($i = ($len % $this->width); $i < $this->width; $i++) $text .= "\0";
\r
51 $ekey = new Expanded_Key($key);
\r
53 for($i = 0; $i < $this->width; $i++) {
\r
55 $rblock[$i] = GPG_Utility::c_random();
\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
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
68 for($i = 0; $i < $this->width + 2; $i++) $cipher .= chr($ct[$i]);
\r
70 $iblock = array_slice($ct, 2, $this->width + 2);
\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
80 return substr($cipher, 0, $len + $this->width + 2);
\r
83 private function gpg_header($tag, $len)
\r
85 if ($len > 0xff) $tag += 1;
\r
87 if ($len > 0xff) $h .= chr($len / 0x100);
\r
88 $h .= chr($len % 0x100);
\r
93 private function gpg_session($key_id, $key_type, $session_key, $public_key)
\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
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
116 $exp = mpi2b(substr($s, $l + 2));
\r
120 $lsk = strlen($session_key);
\r
121 for($i = 0; $i < $lsk; $i++) $c += ord($session_key[$i]);
\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
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
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
141 private function gpg_literal($text)
\r
143 if (strpos($text, "\r\n") === false)
\r
144 $text = str_replace("\n", "\r\n", $text);
\r
147 $this->gpg_header(0xac, strlen($text) + 10) . "t" .
\r
148 chr(4) . "file\0\0\0\0" . $text;
\r
151 private function gpg_data($key, $text)
\r
153 $enc = $this->gpg_encrypt($key, $this->gpg_literal($text));
\r
154 return $this->gpg_header(0xa4, strlen($enc)) . $enc;
\r
158 * GPG Encypts a message to the provided public key
\r
160 * @param GPG_Public_Key $pk
\r
161 * @param string $plaintext
\r
162 * @return string encrypted text
\r
164 function encrypt($pk, $plaintext)
\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
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
176 $code = base64_encode($cp);
\r
177 $code = wordwrap($code, 60, "\n", 1);
\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