Decrypt secret key

This commit is contained in:
Stephen Paul Weber 2013-01-26 14:55:51 -05:00
parent ae062433b7
commit a56799955f
4 changed files with 48 additions and 4 deletions

View File

@ -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) {

View File

@ -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;

Binary file not shown.

View File

@ -104,4 +104,10 @@ class Decryption extends PHPUnit_Framework_TestCase {
}
}
}
public function testDecryptSecretKey() {
$key = OpenPGP_Message::parse(file_get_contents(dirname(__FILE__) . '/data/encryptedSecretKey.gpg'));
$skey = OpenPGP_Crypt_AES_TripleDES::decryptSecretKey("hello", $key[0]);
$this->assertSame(!!$skey, true);
}
}