RSA: add support for loading PKCS8 encrypted private keys

This commit is contained in:
terrafrost 2014-06-13 08:56:00 -05:00
parent 21c6a15df3
commit abae026264

View File

@ -145,6 +145,10 @@ define('CRYPT_RSA_ASN1_INTEGER', 2);
* ASN1 Bit String * ASN1 Bit String
*/ */
define('CRYPT_RSA_ASN1_BITSTRING', 3); define('CRYPT_RSA_ASN1_BITSTRING', 3);
/**
* ASN1 Object Identifier
*/
define('CRYPT_RSA_ASN1_OBJECT', 6);
/** /**
* ASN1 Sequence (with the constucted bit set) * ASN1 Sequence (with the constucted bit set)
*/ */
@ -1109,6 +1113,52 @@ class Crypt_RSA
} }
if ($tag == CRYPT_RSA_ASN1_SEQUENCE) { if ($tag == CRYPT_RSA_ASN1_SEQUENCE) {
$temp = $this->_string_shift($key, $this->_decodeLength($key));
if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_OBJECT) {
return false;
}
$length = $this->_decodeLength($temp);
switch ($this->_string_shift($temp, $length)) {
case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption
break;
case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC
/*
PBEParameter ::= SEQUENCE {
salt OCTET STRING (SIZE(8)),
iterationCount INTEGER }
*/
if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_SEQUENCE) {
return false;
}
if ($this->_decodeLength($temp) != strlen($temp)) {
return false;
}
$this->_string_shift($temp); // assume it's an octet string
$salt = $this->_string_shift($temp, $this->_decodeLength($temp));
if (ord($this->_string_shift($temp)) != CRYPT_RSA_ASN1_INTEGER) {
return false;
}
$this->_decodeLength($temp);
list(, $iterationCount) = unpack('N', str_pad($temp, 4, chr(0), STR_PAD_LEFT));
$this->_string_shift($key); // assume it's an octet string
$length = $this->_decodeLength($key);
if (strlen($key) != $length) {
return false;
}
if (!class_exists('Crypt_DES')) {
include_once 'Crypt/DES.php';
}
$crypto = new Crypt_DES();
$crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount, 16);
$key = $crypto->decrypt($key);
if ($key === false) {
return false;
}
return $this->_parseKey($key, CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
default:
return false;
}
/* intended for keys for which OpenSSL's asn1parse returns the following: /* intended for keys for which OpenSSL's asn1parse returns the following:
0:d=0 hl=4 l= 290 cons: SEQUENCE 0:d=0 hl=4 l= 290 cons: SEQUENCE
@ -1116,7 +1166,6 @@ class Crypt_RSA
6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption
17:d=2 hl=2 l= 0 prim: NULL 17:d=2 hl=2 l= 0 prim: NULL
19:d=1 hl=4 l= 271 prim: BIT STRING */ 19:d=1 hl=4 l= 271 prim: BIT STRING */
$this->_string_shift($key, $this->_decodeLength($key));
$tag = ord($this->_string_shift($key)); // skip over the BIT STRING / OCTET STRING tag $tag = ord($this->_string_shift($key)); // skip over the BIT STRING / OCTET STRING tag
$this->_decodeLength($key); // skip over the BIT STRING / OCTET STRING length $this->_decodeLength($key); // skip over the BIT STRING / OCTET STRING length
// "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of // "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of