From a56799955faa9e3c346fe476e945050b336a188b Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Sat, 26 Jan 2013 14:55:51 -0500 Subject: [PATCH] Decrypt secret key --- lib/openpgp.php | 8 +++--- lib/openpgp_crypt_aes_tripledes.php | 38 ++++++++++++++++++++++++++++ tests/data/encryptedSecretKey.gpg | Bin 0 -> 1291 bytes tests/phpseclib_suite.php | 6 +++++ 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 tests/data/encryptedSecretKey.gpg diff --git a/lib/openpgp.php b/lib/openpgp.php index 06e354f..3fdd9d9 100644 --- a/lib/openpgp.php +++ b/lib/openpgp.php @@ -1454,15 +1454,15 @@ class OpenPGP_PublicSubkeyPacket extends OpenPGP_PublicKeyPacket { * @see http://tools.ietf.org/html/rfc4880#section-12 */ class OpenPGP_SecretKeyPacket extends OpenPGP_PublicKeyPacket { - public $s2k_useage, $s2k, $symmetric_type, $private_hash, $encrypted_data; + public $s2k_useage, $s2k, $symmetric_algorithm, $private_hash, $encrypted_data; function read() { parent::read(); // All the fields from PublicKey $this->s2k_useage = ord($this->read_byte()); if($this->s2k_useage == 255 || $this->s2k_useage == 254) { - $this->symmetric_type = ord($this->read_byte()); + $this->symmetric_algorithm = ord($this->read_byte()); $this->s2k = OpenPGP_S2k::parse($this->input); } else if($this->s2k_useage > 0) { - $this->symmetric_type = $this->s2k_useage; + $this->symmetric_algorithm = $this->s2k_useage; } if($this->s2k_useage > 0) { // TODO: IV of the same length as cipher's block size @@ -1503,7 +1503,7 @@ class OpenPGP_SecretKeyPacket extends OpenPGP_PublicKeyPacket { $bytes = parent::body() . chr($this->s2k_useage); $secret_material = NULL; if($this->s2k_useage == 255 || $this->s2k_useage == 254) { - $bytes .= chr($this->symmetric_type); + $bytes .= chr($this->symmetric_algorithm); $bytes .= $this->s2k->to_bytes(); } if($this->s2k_useage > 0) { diff --git a/lib/openpgp_crypt_aes_tripledes.php b/lib/openpgp_crypt_aes_tripledes.php index d0cf24c..8309819 100644 --- a/lib/openpgp_crypt_aes_tripledes.php +++ b/lib/openpgp_crypt_aes_tripledes.php @@ -30,6 +30,44 @@ class OpenPGP_Crypt_AES_TripleDES { return NULL; /* If we get here, we failed */ } + public static function decryptSecretKey($pass, $packet) { + $packet = clone $packet; // Do not mutate orinigal + + list($cipher, $key_bytes, $key_block_bytes) = self::getCipher($packet->symmetric_algorithm); + $cipher->setKey($packet->s2k->make_key($pass, $key_bytes)); + $cipher->setIV(substr($packet->encrypted_data, 0, $key_block_bytes)); + $material = $cipher->decrypt(substr($packet->encrypted_data, $key_block_bytes)); + + if($packet->s2k_useage == 254) { + $chk = substr($material, -20); + $material = substr($material, 0, -20); + if($chk != hash('sha1', $material)) return NULL; + } else { + $chk = unpack('n', substr($material, -2)); + $chk = reset($chk); + $material = substr($material, 0, -2); + + $mkChk = 0; + for($i = 0; $i < strlen($material); $i++) { + $mkChk = ($mkChk + ord($material{$i})) % 65536; + } + if($chk != $mkChk) return NULL; + } + + $packet->s2k_useage = 0; + $packet->symmetric_algorithm = 0; + $packet->encrypted_data = NULL; + + foreach($packet::$secret_key_fields[$packet->algorithm] as $f) { + $length = unpack('n', substr($material, 0, 2)); // in bits + $length = (int)floor((reset($length) + 7) / 8); // in bytes + $packet->key[$f] = substr($material, 2, $length); + $material = substr($material, 2 + $length); + } + + return $packet; + } + public static function decryptPacket($epacket, $symmetric_algorithm, $key) { list($cipher, $key_bytes, $key_block_bytes) = self::getCipher($symmetric_algorithm); if(!$cipher) return NULL; diff --git a/tests/data/encryptedSecretKey.gpg b/tests/data/encryptedSecretKey.gpg new file mode 100644 index 0000000000000000000000000000000000000000..af700e80f0f870ff7299efb853cd1a9743a7c6c4 GIT binary patch literal 1291 zcmV+m1@!ur1GEH8D4nwb2mt8zmLTMxZZR6QeaEPxI`X|7A=lc$*O_tFz zRQ#e|nyFIAVC9~Hj&3G~*twvINgr9O9_~)F>)5P^is#RP^8Ru}+rrXr6IxFLHK#mG*CFifSd4)g z$lks*!iCeN>6`e#w>JP00RRF22Ll2UC-!hQ;*^14KD=IJ`XCgaX;tgU(2$+=teKJd zpBrX^z@1Q#T%jk}xC#T6PMV+9cXAV{%B``A;POQ^>r56V%w)K6 zLK5gAwFZQ{r^@^`FsVcJ63rR+FkH}GT~+w9L1p{b>%A-aYEmNs%brq@sJOnm;tN&jYTG7d)M zrM52^7@1JBoaOPDG67yzzX2s}5E&2G^BO3*I@K!xdYy92U3F1)s$1(eJ1oIIUUsxt z3GJM;Z%5BL<`*`=GVOpRFZzumq62>LIA|=T_-v#&MH?ZfP6BoKhZfwc8)SsL{k!4# z!vY|YgDe4J#7EN7#P;Md{o8K5TM_8*>_PPxr_HP;VzUJGiM!}T7vb+O^E6J(Vq8WN zMp8SYvxMvX7P2_>k>t_fwYrTSNo-LI;$LW0=4zQtNS|G9Ig0yZw9MNC$K;$}dQ;p(Z`InWz}&+dl+uBr}7&0Ga>7 zV08vg0K7Z5pF+I9K2IDw(F{=^TV(8E*%s%?lMwf2?-_u6cC_GDBU%CHG265szBX0H zhL#}H1#-}TCmRsxH&4p_%bC~3LQ1q4R7F!%AWu$ASs*-QZ$NHubS`vqb#rt+i2*kR z69EVSAq4_VD4nwc8v_Lk2?z%R1r-Vj2nz)k0s{d60v-VZ7k~f?2@nQrON|Tc2S5CJ z2msFO0s@S#bBF{aY8-uWkN&f33rMFZ6e0UaDQbmweUC*za0FMy^AHOu$nSfmEa)5P z&+6LdLY7d*ycS5vz0VhIDjrGdX_d>j^TfRo5vpdbMMDF-6HX^EZR{JZ;T`nU9=INs z_g>nbQ!c(S)JdV+VYZrQZm-qZbi;8a=LGA6A-k=qWy(oYYRte>(5BrRFow&vh{N8B zk=ZZb%pD+ck8}jVN}O$a4b+^0Sx~D5wyT^l)W<4K%Nb9=UxTSLgmG_#O#WTG3|6Nu z)163l%r~(`Po~assertSame(!!$skey, true); + } }