1
0
mirror of https://github.com/danog/phpseclib.git synced 2025-01-22 04:51:19 +01:00

ASN1: don't require octet / bit strings be base64-encoded

This commit is contained in:
terrafrost 2016-11-28 18:50:21 -06:00
parent 874ada8d93
commit 370fbec300
5 changed files with 31 additions and 37 deletions

View File

@ -368,8 +368,8 @@ class PKCS8 extends PKCS
$temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']); $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']);
extract(ASN1::asn1map($temp[0], Maps\PBEParameter::MAP)); extract(ASN1::asn1map($temp[0], Maps\PBEParameter::MAP));
$iterationCount = (int) $iterationCount->toString(); $iterationCount = (int) $iterationCount->toString();
$cipher->setPassword($password, $kdf, $hash, Base64::decode($salt), $iterationCount); $cipher->setPassword($password, $kdf, $hash, $salt, $iterationCount);
$key = $cipher->decrypt(Base64::decode($decrypted['encryptedData'])); $key = $cipher->decrypt($decrypted['encryptedData']);
$decoded = ASN1::decodeBER($key); $decoded = ASN1::decodeBER($key);
if (empty($decoded)) { if (empty($decoded)) {
return false; return false;
@ -391,7 +391,7 @@ class PKCS8 extends PKCS
extract($temp); extract($temp);
if (!$cipher instanceof RC2) { if (!$cipher instanceof RC2) {
$cipher->setIV(Base64::decode($encryptionScheme['parameters']['octetString'])); $cipher->setIV($encryptionScheme['parameters']['octetString']);
} else { } else {
$temp = ASN1::decodeBER($encryptionScheme['parameters']); $temp = ASN1::decodeBER($encryptionScheme['parameters']);
extract(ASN1::asn1map($temp[0], Maps\RC2CBCParameter::MAP)); extract(ASN1::asn1map($temp[0], Maps\RC2CBCParameter::MAP));
@ -408,7 +408,7 @@ class PKCS8 extends PKCS
break; break;
//default: // should be >= 256 //default: // should be >= 256
} }
$cipher->setIV(Base64::decode($iv)); $cipher->setIV($iv);
$cipher->setKeyLength($effectiveKeyLength); $cipher->setKeyLength($effectiveKeyLength);
} }
@ -425,14 +425,14 @@ class PKCS8 extends PKCS
$password, $password,
'pbkdf2', 'pbkdf2',
$hash, $hash,
Base64::decode($salt), $salt,
(int) $iterationCount->toString() (int) $iterationCount->toString()
]; ];
if (isset($keyLength)) { if (isset($keyLength)) {
$params[] = (int) $keyLength->toString(); $params[] = (int) $keyLength->toString();
} }
call_user_func_array([$cipher, 'setPassword'], $params); call_user_func_array([$cipher, 'setPassword'], $params);
$key = $cipher->decrypt(Base64::decode($decrypted['encryptedData'])); $key = $cipher->decrypt($decrypted['encryptedData']);
$decoded = ASN1::decodeBER($key); $decoded = ASN1::decodeBER($key);
if (empty($decoded)) { if (empty($decoded)) {
return false; return false;
@ -462,11 +462,10 @@ class PKCS8 extends PKCS
// bit strings wanting a non-zero amount of bits trimmed are not supported // bit strings wanting a non-zero amount of bits trimmed are not supported
$public = ASN1::asn1map($decoded[0], Maps\PublicKeyInfo::MAP); $public = ASN1::asn1map($decoded[0], Maps\PublicKeyInfo::MAP);
if (is_array($public)) { if (is_array($public)) {
$public['publicKey'] = base64_decode($public['publicKey']);
if ($public['publicKey'][0] != "\0") { if ($public['publicKey'][0] != "\0") {
return false; return false;
} }
$public['publicKey'] = base64_encode(substr($public['publicKey'], 1)); $public['publicKey'] = substr($public['publicKey'], 1);
return $public; return $public;
} }
@ -490,7 +489,7 @@ class PKCS8 extends PKCS
$key = [ $key = [
'version' => 'v1', 'version' => 'v1',
'privateKeyAlgorithm' => ['algorithm' => $algorithm], // parameters are not currently supported 'privateKeyAlgorithm' => ['algorithm' => $algorithm], // parameters are not currently supported
'privateKey' => Base64::encode($key) 'privateKey' => $key
]; ];
if (!empty($attr)) { if (!empty($attr)) {
$key['attributes'] = $attr; $key['attributes'] = $attr;
@ -507,18 +506,18 @@ class PKCS8 extends PKCS
$iv = Random::string($crypto->getBlockLength() >> 3); $iv = Random::string($crypto->getBlockLength() >> 3);
$PBKDF2params = [ $PBKDF2params = [
'salt' => Base64::encode($salt), 'salt' => $salt,
'iterationCount' => $iterationCount, 'iterationCount' => $iterationCount,
'prf' => ['algorithm' => self::$defaultPRF, 'parameters' => null] 'prf' => ['algorithm' => self::$defaultPRF, 'parameters' => null]
]; ];
$PBKDF2params = ASN1::encodeDER($PBKDF2params, Maps\PBKDF2params::MAP); $PBKDF2params = ASN1::encodeDER($PBKDF2params, Maps\PBKDF2params::MAP);
if (!$crypto instanceof RC2) { if (!$crypto instanceof RC2) {
$params = ['octetString' => Base64::encode($iv)]; $params = ['octetString' => $iv];
} else { } else {
$params = [ $params = [
'rc2ParametersVersion' => 58, 'rc2ParametersVersion' => 58,
'iv' => Base64::encode($iv) 'iv' => $iv
]; ];
$params = ASN1::encodeDER($params, Maps\RC2CBCParameter::MAP); $params = ASN1::encodeDER($params, Maps\RC2CBCParameter::MAP);
$params = new ASN1\Element($params); $params = new ASN1\Element($params);
@ -543,7 +542,7 @@ class PKCS8 extends PKCS
$kdf = self::getPBES1KDF(self::$defaultEncryptionAlgorithm); $kdf = self::getPBES1KDF(self::$defaultEncryptionAlgorithm);
$params = [ $params = [
'salt' => Base64::encode($salt), 'salt' => $salt,
'iterationCount' => $iterationCount 'iterationCount' => $iterationCount
]; ];
$params = ASN1::encodeDER($params, Maps\PBEParameter::MAP); $params = ASN1::encodeDER($params, Maps\PBEParameter::MAP);
@ -556,7 +555,7 @@ class PKCS8 extends PKCS
'algorithm' => self::$defaultEncryptionAlgorithm, 'algorithm' => self::$defaultEncryptionAlgorithm,
'parameters' => new ASN1\Element($params) 'parameters' => new ASN1\Element($params)
], ],
'encryptedData' => Base64::encode($key) 'encryptedData' => $key
]; ];
$key = ASN1::encodeDER($key, Maps\EncryptedPrivateKeyInfo::MAP); $key = ASN1::encodeDER($key, Maps\EncryptedPrivateKeyInfo::MAP);
@ -587,7 +586,7 @@ class PKCS8 extends PKCS
'algorithm' => $algorithm, 'algorithm' => $algorithm,
'parameters' => null // parameters are not currently supported 'parameters' => null // parameters are not currently supported
], ],
'publicKey' => Base64::encode("\0" . $key) 'publicKey' => "\0" . $key
]; ];
$key = ASN1::encodeDER($key, Maps\PublicKeyInfo::MAP); $key = ASN1::encodeDER($key, Maps\PublicKeyInfo::MAP);

View File

@ -2051,7 +2051,7 @@ class RSA
$hash; $hash;
$hash = new Hash($hash); $hash = new Hash($hash);
$em = $hash->hash($m); $em = $hash->hash($m);
$em2 = Base64::decode($decoded['digest']); $em2 = $decoded['digest'];
return self::_equals($em, $em2); return self::_equals($em, $em2);
} }

View File

@ -793,7 +793,7 @@ class ASN1
return $values; return $values;
} }
case self::TYPE_OCTET_STRING: case self::TYPE_OCTET_STRING:
return Base64::encode($decoded['content']); return $decoded['content'];
case self::TYPE_NULL: case self::TYPE_NULL:
return ''; return '';
case self::TYPE_BOOLEAN: case self::TYPE_BOOLEAN:
@ -1051,7 +1051,7 @@ class ASN1
the number of unused bits in the final subsequent octet. The number shall be in the range zero to seven. the number of unused bits in the final subsequent octet. The number shall be in the range zero to seven.
-- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=16 */ -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=16 */
$value = Base64::decode($source); $value = $source;
break; break;
case self::TYPE_OBJECT_IDENTIFIER: case self::TYPE_OBJECT_IDENTIFIER:
if (!preg_match('#(?:\d+\.)+#', $source)) { if (!preg_match('#(?:\d+\.)+#', $source)) {

View File

@ -583,7 +583,6 @@ class X509
for ($i = 0; $i < count($extensions); $i++) { for ($i = 0; $i < count($extensions); $i++) {
$id = $extensions[$i]['extnId']; $id = $extensions[$i]['extnId'];
$value = &$extensions[$i]['extnValue']; $value = &$extensions[$i]['extnValue'];
$value = Base64::decode($value);
$decoded = ASN1::decodeBER($value); $decoded = ASN1::decodeBER($value);
/* [extnValue] contains the DER encoding of an ASN.1 value /* [extnValue] contains the DER encoding of an ASN.1 value
corresponding to the extension type identified by extnID */ corresponding to the extension type identified by extnID */
@ -609,8 +608,6 @@ class X509
} }
} }
} }
} else {
$value = Base64::encode($value);
} }
} }
} }
@ -674,8 +671,7 @@ class X509
unset($extensions[$i]); unset($extensions[$i]);
} }
} else { } else {
$temp = ASN1::encodeDER($value, $map, array('iPAddress' => array($this, '_encodeIP'))); $value = ASN1::encodeDER($value, $map, array('iPAddress' => array($this, '_encodeIP')));
$value = Base64::encode($temp);
} }
} }
} }
@ -713,7 +709,7 @@ class X509
$this->_mapInExtensions($values, $j); $this->_mapInExtensions($values, $j);
} }
} elseif ($map) { } elseif ($map) {
$values[$j] = Base64::encode($value); $values[$j] = $value;
} }
} }
} }
@ -1149,7 +1145,7 @@ class X509
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'],
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'],
$this->currentCert['signatureAlgorithm']['algorithm'], $this->currentCert['signatureAlgorithm']['algorithm'],
substr(Base64::decode($this->currentCert['signature']), 1), substr($this->currentCert['signature'], 1),
$this->signatureSubject $this->signatureSubject
); );
case isset($this->currentCert['certificationRequestInfo']): case isset($this->currentCert['certificationRequestInfo']):
@ -1157,7 +1153,7 @@ class X509
$this->currentCert['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'], $this->currentCert['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'],
$this->currentCert['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], $this->currentCert['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'],
$this->currentCert['signatureAlgorithm']['algorithm'], $this->currentCert['signatureAlgorithm']['algorithm'],
substr(Base64::decode($this->currentCert['signature']), 1), substr($this->currentCert['signature'], 1),
$this->signatureSubject $this->signatureSubject
); );
case isset($this->currentCert['publicKeyAndChallenge']): case isset($this->currentCert['publicKeyAndChallenge']):
@ -1165,7 +1161,7 @@ class X509
$this->currentCert['publicKeyAndChallenge']['spki']['algorithm']['algorithm'], $this->currentCert['publicKeyAndChallenge']['spki']['algorithm']['algorithm'],
$this->currentCert['publicKeyAndChallenge']['spki']['subjectPublicKey'], $this->currentCert['publicKeyAndChallenge']['spki']['subjectPublicKey'],
$this->currentCert['signatureAlgorithm']['algorithm'], $this->currentCert['signatureAlgorithm']['algorithm'],
substr(Base64::decode($this->currentCert['signature']), 1), substr($this->currentCert['signature'], 1),
$this->signatureSubject $this->signatureSubject
); );
case isset($this->currentCert['tbsCertList']): case isset($this->currentCert['tbsCertList']):
@ -1193,7 +1189,7 @@ class X509
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'],
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'],
$this->currentCert['signatureAlgorithm']['algorithm'], $this->currentCert['signatureAlgorithm']['algorithm'],
substr(Base64::decode($this->currentCert['signature']), 1), substr($this->currentCert['signature'], 1),
$this->signatureSubject $this->signatureSubject
); );
default: default:
@ -1266,7 +1262,7 @@ class X509
// 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($key, 1)), 64) .
'-----END RSA PUBLIC KEY-----'; '-----END RSA PUBLIC KEY-----';
default: default:
return $key; return $key;
@ -1284,7 +1280,7 @@ class X509
*/ */
function _decodeIP($ip) function _decodeIP($ip)
{ {
return inet_ntop(Base64::decode($ip)); return inet_ntop($ip);
} }
/** /**
@ -1298,7 +1294,7 @@ class X509
*/ */
function _encodeIP($ip) function _encodeIP($ip)
{ {
return Base64::encode(inet_pton($ip)); return inet_pton($ip);
} }
/** /**
@ -2464,7 +2460,7 @@ class X509
); );
if (!isset($subject->currentKeyIdentifier)) { if (!isset($subject->currentKeyIdentifier)) {
$this->setExtension('id-ce-subjectKeyIdentifier', Base64::encode($this->computeKeyIdentifier($this->currentCert)), false, false); $this->setExtension('id-ce-subjectKeyIdentifier', $this->computeKeyIdentifier($this->currentCert), false, false);
} }
} }
@ -2759,7 +2755,7 @@ class X509
case 'sha512WithRSAEncryption': case 'sha512WithRSAEncryption':
$key->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm)); $key->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
$this->currentCert['signature'] = Base64::encode("\0" . $key->sign($this->signatureSubject, RSA::PADDING_PKCS1)); $this->currentCert['signature'] = "\0" . $key->sign($this->signatureSubject, RSA::PADDING_PKCS1);
return $this->currentCert; return $this->currentCert;
default: default:
throw new UnsupportedAlgorithmException('Signature algorithm unsupported'); throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
@ -3339,7 +3335,7 @@ class X509
if (empty($value)) { if (empty($value)) {
unset($this->currentKeyIdentifier); unset($this->currentKeyIdentifier);
} else { } else {
$this->currentKeyIdentifier = Base64::encode($value); $this->currentKeyIdentifier = $value;
} }
} }
@ -3386,7 +3382,6 @@ class X509
if (empty($raw)) { if (empty($raw)) {
return false; return false;
} }
$raw = Base64::decode($raw);
// If the key is private, compute identifier from its corresponding public key. // If the key is private, compute identifier from its corresponding public key.
$key = new RSA(); $key = new RSA();
if (!$key->load($raw)) { if (!$key->load($raw)) {
@ -3439,7 +3434,7 @@ class X509
if ($this->publicKey instanceof RSA) { if ($this->publicKey instanceof RSA) {
// the following two return statements do the same thing. i dunno.. i just prefer the later for some reason. // the following two return statements do the same thing. i dunno.. i just prefer the later for some reason.
// the former is a good example of how to do fuzzing on the public key // the former is a good example of how to do fuzzing on the public key
//return new Element(Base64::decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey()))); //return new Element(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey()));
return array( return array(
'algorithm' => array('algorithm' => 'rsaEncryption'), 'algorithm' => array('algorithm' => 'rsaEncryption'),
'subjectPublicKey' => $this->publicKey->getPublicKey('PKCS1') 'subjectPublicKey' => $this->publicKey->getPublicKey('PKCS1')

View File

@ -107,7 +107,7 @@ k6m17mi63YW/+iPCGOWZ2qXmY5HPEyyF2L4L4IDryFJ+8xLyw3pH9/yp5aHZDtp6
$cert = $x509->loadX509($test); $cert = $x509->loadX509($test);
$this->assertEquals('MDUwDgYIKoZIhvcNAwICAgCAMA4GCCqGSIb3DQMEAgIAgDAHBgUrDgMCBzAKBggqhkiG9w0DBw==', $cert['tbsCertificate']['extensions'][8]['extnValue']); $this->assertEquals(base64_decode('MDUwDgYIKoZIhvcNAwICAgCAMA4GCCqGSIb3DQMEAgIAgDAHBgUrDgMCBzAKBggqhkiG9w0DBw=='), $cert['tbsCertificate']['extensions'][8]['extnValue']);
} }
public function testSaveUnsupportedExtension() public function testSaveUnsupportedExtension()