RSA: slight adjustment to CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW format

CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW and CRYPT_RSA_PUBLIC_FORMAT_PKCS1
produce two very similar looking keys but they are not the same.
As dissection OpenSSL's asn1parse would reveal CRYPT_RSA_PUBLIC_FORMAT_PKCS1
has the fact that it is an RSA key embedded within it whereas
CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW does not. phpseclib now resolves
this ambiguity in the same way that OpenSSH's ssh-keygen does.

Despite this change CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW is still incompatible
with OpenSSL's rsautl (CRYPT_RSA_PUBLIC_FORMAT_PKCS1 is compatible). I guess
this incompatibility isn't just due to the headers but is also due to the
overall structure of the format.
This commit is contained in:
terrafrost 2014-06-10 22:16:59 -05:00
parent 6e796d091a
commit 72a0913d39
2 changed files with 25 additions and 7 deletions

View File

@ -216,6 +216,12 @@ define('CRYPT_RSA_PUBLIC_FORMAT_RAW', 3);
* PKCS#1 formatted public key (raw) * PKCS#1 formatted public key (raw)
* *
* Used by File/X509.php * Used by File/X509.php
*
* Has the following header:
*
* -----BEGIN RSA PUBLIC KEY-----
*
* Analogous to ssh-keygen's pem format (as specified by -m)
*/ */
define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW', 4); define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW', 4);
/** /**
@ -232,6 +238,14 @@ define('CRYPT_RSA_PUBLIC_FORMAT_OPENSSH', 6);
* PKCS#1 formatted public key (encapsulated) * PKCS#1 formatted public key (encapsulated)
* *
* Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set) * Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
*
* Has the following header:
*
* -----BEGIN PUBLIC KEY-----
*
* Analogous to ssh-keygen's pkcs8 format (as specified by -m)
* (the applicability of PKCS8 is dubious since PKCS8 is talking about
* private keys but whatever)
*/ */
define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1', 7); define('CRYPT_RSA_PUBLIC_FORMAT_PKCS1', 7);
/**#@-*/ /**#@-*/
@ -906,7 +920,11 @@ class Crypt_RSA
$components['modulus'], $components['publicExponent'] $components['modulus'], $components['publicExponent']
); );
if ($this->publicKeyFormat == CRYPT_RSA_PUBLIC_FORMAT_PKCS1) { if ($this->publicKeyFormat == CRYPT_RSA_PUBLIC_FORMAT_PKCS1_RAW) {
$RSAPublicKey = "-----BEGIN RSA PUBLIC KEY-----\r\n" .
chunk_split(base64_encode($RSAPublicKey), 64) .
'-----END RSA PUBLIC KEY-----';
} else {
// sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption. // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
$rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
$RSAPublicKey = chr(0) . $RSAPublicKey; $RSAPublicKey = chr(0) . $RSAPublicKey;
@ -915,11 +933,11 @@ class Crypt_RSA
$RSAPublicKey = pack('Ca*a*', $RSAPublicKey = pack('Ca*a*',
CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey CRYPT_RSA_ASN1_SEQUENCE, $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey
); );
}
$RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
chunk_split(base64_encode($RSAPublicKey), 64) . chunk_split(base64_encode($RSAPublicKey), 64) .
'-----END PUBLIC KEY-----'; '-----END PUBLIC KEY-----';
}
return $RSAPublicKey; return $RSAPublicKey;
} }

View File

@ -2173,12 +2173,12 @@ class File_X509
switch ($algorithm) { switch ($algorithm) {
case 'rsaEncryption': case 'rsaEncryption':
return return
"-----BEGIN PUBLIC KEY-----\r\n" . "-----BEGIN RSA PUBLIC KEY-----\r\n" .
// subjectPublicKey is stored as a bit string in X.509 certs. the first byte of a bit string represents how many bits // subjectPublicKey is stored as a bit string in X.509 certs. the first byte of a bit string represents how many bits
// in the last byte should be ignored. the following only supports non-zero stuff but as none of the X.509 certs Firefox // in the last byte should be ignored. the following only supports non-zero stuff but as none of the X.509 certs Firefox
// uses as a cert authority actually use a non-zero bit I think it's safe to assume that none do. // uses as a cert authority actually use a non-zero bit I think it's safe to assume that none do.
chunk_split(base64_encode(substr(base64_decode($key), 1)), 64) . chunk_split(base64_encode(substr(base64_decode($key), 1)), 64) .
'-----END PUBLIC KEY-----'; '-----END RSA PUBLIC KEY-----';
default: default:
return $key; return $key;
} }