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

View File

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

View File

@ -793,7 +793,7 @@ class ASN1
return $values;
}
case self::TYPE_OCTET_STRING:
return Base64::encode($decoded['content']);
return $decoded['content'];
case self::TYPE_NULL:
return '';
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.
-- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=16 */
$value = Base64::decode($source);
$value = $source;
break;
case self::TYPE_OBJECT_IDENTIFIER:
if (!preg_match('#(?:\d+\.)+#', $source)) {

View File

@ -583,7 +583,6 @@ class X509
for ($i = 0; $i < count($extensions); $i++) {
$id = $extensions[$i]['extnId'];
$value = &$extensions[$i]['extnValue'];
$value = Base64::decode($value);
$decoded = ASN1::decodeBER($value);
/* [extnValue] contains the DER encoding of an ASN.1 value
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]);
}
} else {
$temp = ASN1::encodeDER($value, $map, array('iPAddress' => array($this, '_encodeIP')));
$value = Base64::encode($temp);
$value = ASN1::encodeDER($value, $map, array('iPAddress' => array($this, '_encodeIP')));
}
}
}
@ -713,7 +709,7 @@ class X509
$this->_mapInExtensions($values, $j);
}
} elseif ($map) {
$values[$j] = Base64::encode($value);
$values[$j] = $value;
}
}
}
@ -1149,7 +1145,7 @@ class X509
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'],
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'],
$this->currentCert['signatureAlgorithm']['algorithm'],
substr(Base64::decode($this->currentCert['signature']), 1),
substr($this->currentCert['signature'], 1),
$this->signatureSubject
);
case isset($this->currentCert['certificationRequestInfo']):
@ -1157,7 +1153,7 @@ class X509
$this->currentCert['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'],
$this->currentCert['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'],
$this->currentCert['signatureAlgorithm']['algorithm'],
substr(Base64::decode($this->currentCert['signature']), 1),
substr($this->currentCert['signature'], 1),
$this->signatureSubject
);
case isset($this->currentCert['publicKeyAndChallenge']):
@ -1165,7 +1161,7 @@ class X509
$this->currentCert['publicKeyAndChallenge']['spki']['algorithm']['algorithm'],
$this->currentCert['publicKeyAndChallenge']['spki']['subjectPublicKey'],
$this->currentCert['signatureAlgorithm']['algorithm'],
substr(Base64::decode($this->currentCert['signature']), 1),
substr($this->currentCert['signature'], 1),
$this->signatureSubject
);
case isset($this->currentCert['tbsCertList']):
@ -1193,7 +1189,7 @@ class X509
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'],
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'],
$this->currentCert['signatureAlgorithm']['algorithm'],
substr(Base64::decode($this->currentCert['signature']), 1),
substr($this->currentCert['signature'], 1),
$this->signatureSubject
);
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
// 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.
chunk_split(Base64::encode(substr(Base64::decode($key), 1)), 64) .
chunk_split(Base64::encode(substr($key, 1)), 64) .
'-----END RSA PUBLIC KEY-----';
default:
return $key;
@ -1284,7 +1280,7 @@ class X509
*/
function _decodeIP($ip)
{
return inet_ntop(Base64::decode($ip));
return inet_ntop($ip);
}
/**
@ -1298,7 +1294,7 @@ class X509
*/
function _encodeIP($ip)
{
return Base64::encode(inet_pton($ip));
return inet_pton($ip);
}
/**
@ -2464,7 +2460,7 @@ class X509
);
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':
$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;
default:
throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
@ -3339,7 +3335,7 @@ class X509
if (empty($value)) {
unset($this->currentKeyIdentifier);
} else {
$this->currentKeyIdentifier = Base64::encode($value);
$this->currentKeyIdentifier = $value;
}
}
@ -3386,7 +3382,6 @@ class X509
if (empty($raw)) {
return false;
}
$raw = Base64::decode($raw);
// If the key is private, compute identifier from its corresponding public key.
$key = new RSA();
if (!$key->load($raw)) {
@ -3439,7 +3434,7 @@ class X509
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 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(
'algorithm' => array('algorithm' => 'rsaEncryption'),
'subjectPublicKey' => $this->publicKey->getPublicKey('PKCS1')

View File

@ -107,7 +107,7 @@ k6m17mi63YW/+iPCGOWZ2qXmY5HPEyyF2L4L4IDryFJ+8xLyw3pH9/yp5aHZDtp6
$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()