Merge branch '2.0'

This commit is contained in:
terrafrost 2016-06-12 14:19:56 -05:00
commit f815e43077
2 changed files with 389 additions and 69 deletions

View File

@ -147,6 +147,7 @@ class X509
var $CertificatePolicies; var $CertificatePolicies;
var $AuthorityInfoAccessSyntax; var $AuthorityInfoAccessSyntax;
var $SubjectAltName; var $SubjectAltName;
var $SubjectDirectoryAttributes;
var $PrivateKeyUsagePeriod; var $PrivateKeyUsagePeriod;
var $IssuerAltName; var $IssuerAltName;
var $PolicyMappings; var $PolicyMappings;
@ -170,6 +171,14 @@ class X509
var $SignedPublicKeyAndChallenge; var $SignedPublicKeyAndChallenge;
/**#@-*/ /**#@-*/
/**#@+
* ASN.1 syntax for various DN attributes
*
* @access private
*/
var $PostalAddress;
/**#@-*/
/** /**
* ASN.1 syntax for Certificate Signing Requests (RFC2986) * ASN.1 syntax for Certificate Signing Requests (RFC2986)
* *
@ -1072,6 +1081,13 @@ class X509
) )
); );
$this->SubjectDirectoryAttributes = array(
'type' => ASN1::TYPE_SEQUENCE,
'min' => 1,
'max' => -1,
'children' => $Attribute
);
// adapted from <http://tools.ietf.org/html/rfc2986> // adapted from <http://tools.ietf.org/html/rfc2986>
$Attributes = array( $Attributes = array(
@ -1239,6 +1255,14 @@ class X509
) )
); );
$this->PostalAddress = array(
'type' => ASN1::TYPE_SEQUENCE,
'optional' => true,
'min' => 1,
'max' => -1,
'children' => $this->DirectoryString
);
// OIDs from RFC5280 and those RFCs mentioned in RFC5280#section-4.1.1.2 // OIDs from RFC5280 and those RFCs mentioned in RFC5280#section-4.1.1.2
$this->oids = array( $this->oids = array(
'1.3.6.1.5.5.7' => 'id-pkix', '1.3.6.1.5.5.7' => 'id-pkix',
@ -1273,6 +1297,7 @@ class X509
'2.5.4.9' => 'id-at-streetAddress', '2.5.4.9' => 'id-at-streetAddress',
'2.5.4.45' => 'id-at-uniqueIdentifier', '2.5.4.45' => 'id-at-uniqueIdentifier',
'2.5.4.72' => 'id-at-role', '2.5.4.72' => 'id-at-role',
'2.5.4.16' => 'id-at-postalAddress',
'0.9.2342.19200300.100.1.25' => 'id-domainComponent', '0.9.2342.19200300.100.1.25' => 'id-domainComponent',
'1.2.840.113549.1.9' => 'pkcs-9', '1.2.840.113549.1.9' => 'pkcs-9',
@ -1463,6 +1488,8 @@ class X509
$this->signatureSubject = substr($cert, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); $this->signatureSubject = substr($cert, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
$this->_mapInExtensions($x509, 'tbsCertificate/extensions', $asn1); $this->_mapInExtensions($x509, 'tbsCertificate/extensions', $asn1);
$this->_mapInDNs($x509, 'tbsCertificate/issuer/rdnSequence', $asn1);
$this->_mapInDNs($x509, 'tbsCertificate/subject/rdnSequence', $asn1);
$key = &$x509['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']; $key = &$x509['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'];
$key = $this->_reformatKey($x509['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $key); $key = $this->_reformatKey($x509['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $key);
@ -1539,6 +1566,8 @@ class X509
$asn1->loadFilters($filters); $asn1->loadFilters($filters);
$this->_mapOutExtensions($cert, 'tbsCertificate/extensions', $asn1); $this->_mapOutExtensions($cert, 'tbsCertificate/extensions', $asn1);
$this->_mapOutDNs($cert, 'tbsCertificate/issuer/rdnSequence', $asn1);
$this->_mapOutDNs($cert, 'tbsCertificate/subject/rdnSequence', $asn1);
$cert = $asn1->encodeDER($cert, $this->Certificate); $cert = $asn1->encodeDER($cert, $this->Certificate);
@ -1751,6 +1780,68 @@ class X509
} }
} }
/**
* Map DN values from ANY type to DN-specific internal
* format.
*
* @param array ref $root
* @param string $path
* @param object $asn1
* @access private
*/
function _mapInDNs(&$root, $path, $asn1)
{
$dns = &$this->_subArray($root, $path);
if (is_array($dns)) {
for ($i = 0; $i < count($dns); $i++) {
for ($j = 0; $j < count($dns[$i]); $j++) {
$type = $dns[$i][$j]['type'];
$value = &$dns[$i][$j]['value'];
if (is_object($value) && $value instanceof Element) {
$map = $this->_getMapping($type);
if (!is_bool($map)) {
$decoded = $asn1->decodeBER($value);
$value = $asn1->asn1map($decoded[0], $map);
}
}
}
}
}
}
/**
* Map DN values from DN-specific internal format to
* ANY type.
*
* @param array ref $root
* @param string $path
* @param object $asn1
* @access private
*/
function _mapOutDNs(&$root, $path, $asn1)
{
$dns = &$this->_subArray($root, $path);
if (is_array($dns)) {
$size = count($dns);
for ($i = 0; $i < $size; $i++) {
for ($j = 0; $j < count($dns[$i]); $j++) {
$type = $dns[$i][$j]['type'];
$value = &$dns[$i][$j]['value'];
if (is_object($value) && $value instanceof Element) {
continue;
}
$map = $this->_getMapping($type);
if (!is_bool($map)) {
$value = new Element($asn1->encodeDER($value, $map));
}
}
}
}
}
/** /**
* Associate an extension ID to an extension mapping * Associate an extension ID to an extension mapping
* *
@ -1783,6 +1874,8 @@ class X509
return $this->AuthorityInfoAccessSyntax; return $this->AuthorityInfoAccessSyntax;
case 'id-ce-subjectAltName': case 'id-ce-subjectAltName':
return $this->SubjectAltName; return $this->SubjectAltName;
case 'id-ce-subjectDirectoryAttributes':
return $this->SubjectDirectoryAttributes;
case 'id-ce-privateKeyUsagePeriod': case 'id-ce-privateKeyUsagePeriod':
return $this->PrivateKeyUsagePeriod; return $this->PrivateKeyUsagePeriod;
case 'id-ce-issuerAltName': case 'id-ce-issuerAltName':
@ -1842,6 +1935,8 @@ class X509
return $this->CertificateIssuer; return $this->CertificateIssuer;
case 'id-ce-holdInstructionCode': case 'id-ce-holdInstructionCode':
return $this->HoldInstructionCode; return $this->HoldInstructionCode;
case 'id-at-postalAddress':
return $this->PostalAddress;
} }
return false; return false;
@ -2033,14 +2128,16 @@ class X509
switch (true) { switch (true) {
case isset($this->currentCert['tbsCertificate']): case isset($this->currentCert['tbsCertificate']):
// self-signed cert // self-signed cert
if ($this->currentCert['tbsCertificate']['issuer'] === $this->currentCert['tbsCertificate']['subject']) { switch (true) {
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier'); case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $this->currentCert['tbsCertificate']['subject']:
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier'); case defined('FILE_X509_IGNORE_TYPE') && $this->getIssuerDN(self::DN_STRING) === $this->getDN(self::DN_STRING):
switch (true) { $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
case !is_array($authorityKey): $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier');
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: switch (true) {
$signingCert = $this->currentCert; // working cert case !is_array($authorityKey):
} case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
$signingCert = $this->currentCert; // working cert
}
} }
if (!empty($this->CAs)) { if (!empty($this->CAs)) {
@ -2048,15 +2145,17 @@ class X509
// even if the cert is a self-signed one we still want to see if it's a CA; // even if the cert is a self-signed one we still want to see if it's a CA;
// if not, we'll conditionally return an error // if not, we'll conditionally return an error
$ca = $this->CAs[$i]; $ca = $this->CAs[$i];
if ($this->currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']) { switch (true) {
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier'); case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']:
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca); case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertificate']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']):
switch (true) { $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
case !is_array($authorityKey): $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: switch (true) {
$signingCert = $ca; // working cert case !is_array($authorityKey):
break 2; case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
} $signingCert = $ca; // working cert
break 3;
}
} }
} }
if (count($this->CAs) == $i && $caonly) { if (count($this->CAs) == $i && $caonly) {
@ -2092,15 +2191,17 @@ class X509
if (!empty($this->CAs)) { if (!empty($this->CAs)) {
for ($i = 0; $i < count($this->CAs); $i++) { for ($i = 0; $i < count($this->CAs); $i++) {
$ca = $this->CAs[$i]; $ca = $this->CAs[$i];
if ($this->currentCert['tbsCertList']['issuer'] === $ca['tbsCertificate']['subject']) { switch (true) {
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier'); case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertList']['issuer'] === $ca['tbsCertificate']['subject']:
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca); case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertList']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']):
switch (true) { $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
case !is_array($authorityKey): $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID: switch (true) {
$signingCert = $ca; // working cert case !is_array($authorityKey):
break 2; case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
} $signingCert = $ca; // working cert
break 3;
}
} }
} }
} }
@ -2303,6 +2404,9 @@ class X509
case 'uniqueidentifier': case 'uniqueidentifier':
case 'x500uniqueidentifier': case 'x500uniqueidentifier':
return 'id-at-uniqueIdentifier'; return 'id-at-uniqueIdentifier';
case 'postaladdress':
case 'id-at-postaladdress':
return 'id-at-postalAddress';
default: default:
return false; return false;
} }
@ -2392,25 +2496,38 @@ class X509
return false; return false;
} }
$asn1 = new ASN1();
$asn1->loadOIDs($this->oids);
$filters = array();
$filters['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
$asn1->loadFilters($filters);
$this->_mapOutDNs($dn, 'rdnSequence', $asn1);
$dn = $dn['rdnSequence']; $dn = $dn['rdnSequence'];
$result = array(); $result = array();
$asn1 = new ASN1();
for ($i = 0; $i < count($dn); $i++) { for ($i = 0; $i < count($dn); $i++) {
if ($dn[$i][0]['type'] == $propName) { if ($dn[$i][0]['type'] == $propName) {
$v = $dn[$i][0]['value']; $v = $dn[$i][0]['value'];
if (!$withType && is_array($v)) { if (!$withType) {
foreach ($v as $type => $s) { if (is_array($v)) {
$type = array_search($type, $asn1->ANYmap, true); foreach ($v as $type => $s) {
if ($type !== false && isset($asn1->stringTypeSize[$type])) { $type = array_search($type, $asn1->ANYmap, true);
$s = $asn1->convert($s, $type); if ($type !== false && isset($asn1->stringTypeSize[$type])) {
if ($s !== false) { $s = $asn1->convert($s, $type);
$v = $s; if ($s !== false) {
break; $v = $s;
break;
}
} }
} }
} if (is_array($v)) {
if (is_array($v)) { $v = array_pop($v); // Always strip data type.
$v = array_pop($v); // Always strip data type. }
} elseif (is_object($v) && $v instanceof Element) {
$map = $this->_getMapping($propName);
if (!is_bool($map)) {
$decoded = $asn1->decodeBER($v);
$v = $asn1->asn1map($decoded[0], $map);
}
} }
} }
$result[] = $v; $result[] = $v;
@ -2451,7 +2568,7 @@ class X509
} }
// handles everything else // handles everything else
$results = preg_split('#((?:^|, *|/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE); $results = preg_split('#((?:^|, *|/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=|postalAddress=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
for ($i = 1; $i < count($results); $i+=2) { for ($i = 1; $i < count($results); $i+=2) {
$prop = trim($results[$i], ', =/'); $prop = trim($results[$i], ', =/');
$value = $results[$i + 1]; $value = $results[$i + 1];
@ -2486,33 +2603,19 @@ class X509
$filters = array(); $filters = array();
$filters['rdnSequence']['value'] = array('type' => ASN1::TYPE_UTF8_STRING); $filters['rdnSequence']['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
$asn1->loadFilters($filters); $asn1->loadFilters($filters);
$this->_mapOutDNs($dn, 'rdnSequence', $asn1);
return $asn1->encodeDER($dn, $this->Name); return $asn1->encodeDER($dn, $this->Name);
case self::DN_OPENSSL:
$dn = $this->getDN(self::DN_STRING, $dn);
if ($dn === false) {
return false;
}
$attrs = preg_split('#((?:^|, *|/)[a-z][a-z0-9]*=)#i', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
$dn = array();
for ($i = 1; $i < count($attrs); $i += 2) {
$prop = trim($attrs[$i], ', =/');
$value = $attrs[$i + 1];
if (!isset($dn[$prop])) {
$dn[$prop] = $value;
} else {
$dn[$prop] = array_merge((array) $dn[$prop], array($value));
}
}
return $dn;
case self::DN_CANON: case self::DN_CANON:
// No SEQUENCE around RDNs and all string values normalized as // No SEQUENCE around RDNs and all string values normalized as
// trimmed lowercase UTF-8 with all spacing as one blank. // trimmed lowercase UTF-8 with all spacing as one blank.
// constructed RDNs will not be canonicalized
$asn1 = new ASN1(); $asn1 = new ASN1();
$asn1->loadOIDs($this->oids); $asn1->loadOIDs($this->oids);
$filters = array(); $filters = array();
$filters['value'] = array('type' => ASN1::TYPE_UTF8_STRING); $filters['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
$asn1->loadFilters($filters); $asn1->loadFilters($filters);
$result = ''; $result = '';
$this->_mapOutDNs($dn, 'rdnSequence', $asn1);
foreach ($dn['rdnSequence'] as $rdn) { foreach ($dn['rdnSequence'] as $rdn) {
foreach ($rdn as $i => $attr) { foreach ($rdn as $i => $attr) {
$attr = &$rdn[$i]; $attr = &$rdn[$i];
@ -2544,7 +2647,15 @@ class X509
// Default is to return a string. // Default is to return a string.
$start = true; $start = true;
$output = ''; $output = '';
$result = array();
$asn1 = new ASN1(); $asn1 = new ASN1();
$asn1->loadOIDs($this->oids);
$filters = array();
$filters['rdnSequence']['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
$asn1->loadFilters($filters);
$this->_mapOutDNs($dn, 'rdnSequence', $asn1);
foreach ($dn['rdnSequence'] as $field) { foreach ($dn['rdnSequence'] as $field) {
$prop = $field[0]['type']; $prop = $field[0]['type'];
$value = $field[0]['value']; $value = $field[0]['value'];
@ -2552,33 +2663,37 @@ class X509
$delim = ', '; $delim = ', ';
switch ($prop) { switch ($prop) {
case 'id-at-countryName': case 'id-at-countryName':
$desc = 'C='; $desc = 'C';
break; break;
case 'id-at-stateOrProvinceName': case 'id-at-stateOrProvinceName':
$desc = 'ST='; $desc = 'ST';
break; break;
case 'id-at-organizationName': case 'id-at-organizationName':
$desc = 'O='; $desc = 'O';
break; break;
case 'id-at-organizationalUnitName': case 'id-at-organizationalUnitName':
$desc = 'OU='; $desc = 'OU';
break; break;
case 'id-at-commonName': case 'id-at-commonName':
$desc = 'CN='; $desc = 'CN';
break; break;
case 'id-at-localityName': case 'id-at-localityName':
$desc = 'L='; $desc = 'L';
break; break;
case 'id-at-surname': case 'id-at-surname':
$desc = 'SN='; $desc = 'SN';
break; break;
case 'id-at-uniqueIdentifier': case 'id-at-uniqueIdentifier':
$delim = '/'; $delim = '/';
$desc = 'x500UniqueIdentifier='; $desc = 'x500UniqueIdentifier';
break;
case 'id-at-postalAddress':
$delim = '/';
$desc = 'postalAddress';
break; break;
default: default:
$delim = '/'; $delim = '/';
$desc = preg_replace('#.+-([^-]+)$#', '$1', $prop) . '='; $desc = preg_replace('#.+-([^-]+)$#', '$1', $prop);
} }
if (!$start) { if (!$start) {
@ -2598,12 +2713,18 @@ class X509
if (is_array($value)) { if (is_array($value)) {
$value = array_pop($value); // Always strip data type. $value = array_pop($value); // Always strip data type.
} }
} elseif (is_object($value) && $value instanceof Element) {
$callback = create_function('$x', 'return "\x" . bin2hex($x[0]);');
$value = strtoupper(preg_replace_callback('#[^\x20-\x7E]#', $callback, $value->element));
} }
$output.= $desc . $value; $output.= $desc . '=' . $value;
$result[$desc] = isset($result[$desc]) ?
array_merge((array) $dn[$prop], array($value)) :
$value;
$start = false; $start = false;
} }
return $output; return $format == self::DN_OPENSSL ? $result : $output;
} }
/** /**
@ -2878,8 +2999,10 @@ class X509
return false; return false;
} }
$this->dn = $csr['certificationRequestInfo']['subject'];
$this->_mapInAttributes($csr, 'certificationRequestInfo/attributes', $asn1); $this->_mapInAttributes($csr, 'certificationRequestInfo/attributes', $asn1);
$this->_mapInDNs($csr, 'certificationRequestInfo/subject/rdnSequence', $asn1);
$this->dn = $csr['certificationRequestInfo']['subject'];
$this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
@ -2939,6 +3062,7 @@ class X509
$asn1->loadFilters($filters); $asn1->loadFilters($filters);
$this->_mapOutDNs($csr, 'certificationRequestInfo/subject/rdnSequence', $asn1);
$this->_mapOutAttributes($csr, 'certificationRequestInfo/attributes', $asn1); $this->_mapOutAttributes($csr, 'certificationRequestInfo/attributes', $asn1);
$csr = $asn1->encodeDER($csr, $this->CertificationRequest); $csr = $asn1->encodeDER($csr, $this->CertificationRequest);
@ -3116,6 +3240,7 @@ class X509
$this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']); $this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
$this->_mapInDNs($crl, 'tbsCertList/issuer/rdnSequence', $asn1);
$this->_mapInExtensions($crl, 'tbsCertList/crlExtensions', $asn1); $this->_mapInExtensions($crl, 'tbsCertList/crlExtensions', $asn1);
$rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates'); $rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates');
if (is_array($rclist)) { if (is_array($rclist)) {
@ -3168,6 +3293,7 @@ class X509
$asn1->loadFilters($filters); $asn1->loadFilters($filters);
$this->_mapOutDNs($crl, 'tbsCertList/issuer/rdnSequence', $asn1);
$this->_mapOutExtensions($crl, 'tbsCertList/crlExtensions', $asn1); $this->_mapOutExtensions($crl, 'tbsCertList/crlExtensions', $asn1);
$rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates'); $rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates');
if (is_array($rclist)) { if (is_array($rclist)) {

View File

@ -260,4 +260,198 @@ NDEuGt30Vl2de7G1glnhaceB6Q9KfH7p2gAwNP9JMTtx3PtEcA==
$this->assertEquals($cert['tbsCertificate']['extensions'][3]['extnValue'][0]['iPAddress'], '204.152.200.250'); $this->assertEquals($cert['tbsCertificate']['extensions'][3]['extnValue'][0]['iPAddress'], '204.152.200.250');
$this->assertEquals($cert['tbsCertificate']['extensions'][3]['extnValue'][1]['iPAddress'], '2001:470:f309:9::3'); $this->assertEquals($cert['tbsCertificate']['extensions'][3]['extnValue'][1]['iPAddress'], '2001:470:f309:9::3');
} }
public function testPostalAddress()
{
$x509 = new X509();
$decoded = $x509->loadX509('-----BEGIN CERTIFICATE-----
MIIFzzCCBLegAwIBAgIDAfdlMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNVBAYTAlBM
MSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYD
VQQDDBtDT1BFIFNaQUZJUiAtIEt3YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdw
aXN1OiA2MB4XDTExMTEwOTA2MDAwMFoXDTEzMTEwOTA2MDAwMFowgdkxCzAJBgNV
BAYTAlBMMRwwGgYDVQQKDBNVcnrEhWQgTWlhc3RhIEdkeW5pMRswGQYDVQQFExJQ
RVNFTDogNjEwNjA2MDMxMTgxGTAXBgNVBAMMEEplcnp5IFByemV3b3Jza2kxTzBN
BgNVBBAwRgwiQWwuIE1hcnN6YcWCa2EgUGnFgnN1ZHNraWVnbyA1Mi81NAwNODEt
MzgyIEdkeW5pYQwGUG9sc2thDAlwb21vcnNraWUxDjAMBgNVBCoMBUplcnp5MRMw
EQYDVQQEDApQcnpld29yc2tpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCM
m5vjGqHPthJCMqKpqssSISRos0PYDTcEQzyyurfX67EJWKtZj6HNwuDMEGJ02iBN
ZfjUl7r8dIi28bSKhNlsfycXZKYRcIjp0+r5RqtR2auo9GQ6veKb61DEAGIqaR+u
LLcJVTHCu0w9oXLGbRlGth5eNoj03CxXVAH2IfhbNwIDAQABo4IChzCCAoMwDAYD
VR0TAQH/BAIwADCCAUgGA1UdIAEB/wSCATwwggE4MIIBNAYJKoRoAYb3IwEBMIIB
JTCB3QYIKwYBBQUHAgIwgdAMgc1EZWtsYXJhY2phIHRhIGplc3Qgb8Wbd2lhZGN6
ZW5pZW0gd3lkYXdjeSwgxbxlIHRlbiBjZXJ0eWZpa2F0IHpvc3RhxYIgd3lkYW55
IGpha28gY2VydHlmaWthdCBrd2FsaWZpa293YW55IHpnb2RuaWUgeiB3eW1hZ2Fu
aWFtaSB1c3Rhd3kgbyBwb2RwaXNpZSBlbGVrdHJvbmljem55bSBvcmF6IHRvd2Fy
enlzesSFY3ltaSBqZWogcm96cG9yesSFZHplbmlhbWkuMEMGCCsGAQUFBwIBFjdo
dHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN6eS9wb2xpdHlr
YS5odG1sMAkGA1UdCQQCMAAwIQYDVR0RBBowGIEWai5wcnpld29yc2tpQGdkeW5p
YS5wbDAOBgNVHQ8BAf8EBAMCBkAwgZ4GA1UdIwSBljCBk4AU3TGldJXipN4oGS3Z
YmnBDMFs8gKhd6R1MHMxCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6
YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYDVQQDDBtDT1BFIFNaQUZJUiAtIEt3
YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdwaXN1OiA2ggJb9jBIBgNVHR8EQTA/
MD2gO6A5hjdodHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN6
eS9DUkxfT1pLMzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQBYPIqnAreyeql7/opJ
jcar/qWZy9ruhB2q0lZFsJOhwgMnbQXzp/4vv93YJqcHGAXdHP6EO8FQX47mjo2Z
KQmi+cIHJHLONdX/3Im+M17V0iNAh7Z1lOSfTRT+iiwe/F8phcEaD5q2RmvYusR7
zXZq/cLL0If0hXoPZ/EHQxjN8pxzxiUx6bJAgturnIMEfRNesxwghdr1dkUjOhGL
f3kHVzgM6j3VAM7oFmMUb5y5s96Bzl10DodWitjOEH0vvnIcsppSxH1C1dCAi0o9
f/1y2XuLNhBNHMAyTqpYPX8Yvav1c+Z50OMaSXHAnTa20zv8UtiHbaAhwlifCelU
Mj93S
-----END CERTIFICATE-----');
$x509->loadX509($x509->saveX509($decoded));
$expected = array(
array(
array('utf8String' => "Al. Marsza\xC5\x82ka Pi\xC5\x82sudskiego 52/54"),
array('utf8String' => '81-382 Gdynia'),
array('utf8String' => 'Polska'),
array('utf8String' => 'pomorskie')
)
);
$this->assertEquals($x509->getDNProp('id-at-postalAddress'), $expected);
$expected = "C=PL, O=Urz\xC4\x85d Miasta Gdyni/serialNumber=PESEL: 61060603118, CN=Jerzy Przeworski/postalAddress=" . '0F\X0C"AL. MARSZA\XC5\X82KA PI\XC5\X82SUDSKIEGO 52/54\X0C\X0D81-382 GDYNIA\X0C\X06POLSKA\X0C\X09POMORSKIE/givenName=Jerzy, SN=Przeworski';
$this->assertEquals($x509->getDN(X509::DN_STRING), $expected);
}
public function testStrictComparison()
{
$x509 = new X509();
$x509->loadCA('-----BEGIN CERTIFICATE-----
MIIEbDCCA1SgAwIBAgIUJguKOMpJm/yRMDlMOW04NV0YPXowDQYJKoZIhvcNAQEF
BQAwYTELMAkGA1UEBhMCUEwxNzA1BgNVBAoTLkNaaUMgQ2VudHJhc3QgU0EgdyBp
bWllbml1IE1pbmlzdHJhIEdvc3BvZGFya2kxGTAXBgNVBAMTEENaaUMgQ2VudHJh
c3QgU0EwHhcNMDkwNDI5MTE1MzIxWhcNMTMxMjEzMjM1OTU5WjBzMQswCQYDVQQG
EwJQTDEoMCYGA1UEChMfS3Jham93YSBJemJhIFJvemxpY3plbmlvd2EgUy5BLjEk
MCIGA1UEAxMbQ09QRSBTWkFGSVIgLSBLd2FsaWZpa293YW55MRQwEgYDVQQFEwtO
ciB3cGlzdTogNjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIjNy3EL
oK0uKTqAJokiP8VIxER/0OfwhY4DBhJGW38W6Pfema8iUs4net0NgoIeDpMQ8IHj
FDSKkSaRkyL5f7PgvqBwzKe0HD1Duf9G/Lr2lu/J4QUMF3rqKaMRipXKkkEoKrub
Qe41/mPiPXeClNswNQUEyInqWpfWNncU8AIs2GKIFTfSNqK4PgWOY1kG9MYfoNVr
74dhejv7yHexEw9eAIcM1fIkEEq0vWIOjRtBXBAuWtUyD8iSeBs4nIN+614pHIjv
ncHxG7xTDbmOAVZFgGZ8Hk5CUseAtTpazQNdU66XRUuCj4km01L4wsfZ1X8tfYQA
6msMRYj+F7hLtoECAwEAAaOCAQgwggEEMA8GA1UdEwEB/wQFMAMBAf8wgY4GA1Ud
IwSBhjCBg4AU2a7r85Cp1iJNW0Ca1LR6VG3996ShZaRjMGExCzAJBgNVBAYTAlBM
MTcwNQYDVQQKEy5DWmlDIENlbnRyYXN0IFNBIHcgaW1pZW5pdSBNaW5pc3RyYSBH
b3Nwb2RhcmtpMRkwFwYDVQQDExBDWmlDIENlbnRyYXN0IFNBggQ9/0sQMDEGA1Ud
IAEB/wQnMCUwIwYEVR0gADAbMBkGCCsGAQUFBwIBFg13d3cubmNjZXJ0LnBsMA4G
A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU3TGldJXipN4oGS3ZYmnBDMFs8gIwDQYJ
KoZIhvcNAQEFBQADggEBAJrkn3XycfimT5C6D+lYvQNB4/X44KZRhxhnplMOdr/V
3O13oJA/G2SkVaRZS1Rqy01vC9H3YSFfYnjFXJTOXldzodwszHEcGLHF/3JazHI9
BTpP1F4oFyd0Un/wkp1usGU4e1riU5RAlSp8YcMX3q+nOqyCh0JsxnP7LjauHkE3
KZ1RuBDZYbsYOwkAKjHax8srKugdWtq4sMNcqpxGFUah/4uLQn6hD4jeRpP4VGDv
HZDmxaIoJdmCxfn9XeIS5PcZR+mHHkUOIhYLnfdUp/T3Yxxo+XrrTckC6AjtsL5/
OA0vBLngVqqeuzVf0tUhcrCwPKQo5rKoakbApeXrows=
-----END CERTIFICATE-----');
$x509->loadX509('-----BEGIN CERTIFICATE-----
MIIFzzCCBLegAwIBAgIDAfdlMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNVBAYTAlBM
MSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYD
VQQDDBtDT1BFIFNaQUZJUiAtIEt3YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdw
aXN1OiA2MB4XDTExMTEwOTA2MDAwMFoXDTEzMTEwOTA2MDAwMFowgdkxCzAJBgNV
BAYTAlBMMRwwGgYDVQQKDBNVcnrEhWQgTWlhc3RhIEdkeW5pMRswGQYDVQQFExJQ
RVNFTDogNjEwNjA2MDMxMTgxGTAXBgNVBAMMEEplcnp5IFByemV3b3Jza2kxTzBN
BgNVBBAwRgwiQWwuIE1hcnN6YcWCa2EgUGnFgnN1ZHNraWVnbyA1Mi81NAwNODEt
MzgyIEdkeW5pYQwGUG9sc2thDAlwb21vcnNraWUxDjAMBgNVBCoMBUplcnp5MRMw
EQYDVQQEDApQcnpld29yc2tpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCM
m5vjGqHPthJCMqKpqssSISRos0PYDTcEQzyyurfX67EJWKtZj6HNwuDMEGJ02iBN
ZfjUl7r8dIi28bSKhNlsfycXZKYRcIjp0+r5RqtR2auo9GQ6veKb61DEAGIqaR+u
LLcJVTHCu0w9oXLGbRlGth5eNoj03CxXVAH2IfhbNwIDAQABo4IChzCCAoMwDAYD
VR0TAQH/BAIwADCCAUgGA1UdIAEB/wSCATwwggE4MIIBNAYJKoRoAYb3IwEBMIIB
JTCB3QYIKwYBBQUHAgIwgdAMgc1EZWtsYXJhY2phIHRhIGplc3Qgb8Wbd2lhZGN6
ZW5pZW0gd3lkYXdjeSwgxbxlIHRlbiBjZXJ0eWZpa2F0IHpvc3RhxYIgd3lkYW55
IGpha28gY2VydHlmaWthdCBrd2FsaWZpa293YW55IHpnb2RuaWUgeiB3eW1hZ2Fu
aWFtaSB1c3Rhd3kgbyBwb2RwaXNpZSBlbGVrdHJvbmljem55bSBvcmF6IHRvd2Fy
enlzesSFY3ltaSBqZWogcm96cG9yesSFZHplbmlhbWkuMEMGCCsGAQUFBwIBFjdo
dHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN6eS9wb2xpdHlr
YS5odG1sMAkGA1UdCQQCMAAwIQYDVR0RBBowGIEWai5wcnpld29yc2tpQGdkeW5p
YS5wbDAOBgNVHQ8BAf8EBAMCBkAwgZ4GA1UdIwSBljCBk4AU3TGldJXipN4oGS3Z
YmnBDMFs8gKhd6R1MHMxCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6
YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYDVQQDDBtDT1BFIFNaQUZJUiAtIEt3
YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdwaXN1OiA2ggJb9jBIBgNVHR8EQTA/
MD2gO6A5hjdodHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN6
eS9DUkxfT1pLMzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQBYPIqnAreyeql7/opJ
jcar/qWZy9ruhB2q0lZFsJOhwgMnbQXzp/4vv93YJqcHGAXdHP6EO8FQX47mjo2Z
KQmi+cIHJHLONdX/3Im+M17V0iNAh7Z1lOSfTRT+iiwe/F8phcEaD5q2RmvYusR7
zXZq/cLL0If0hXoPZ/EHQxjN8pxzxiUx6bJAgturnIMEfRNesxwghdr1dkUjOhGL
f3kHVzgM6j3VAM7oFmMUb5y5s96Bzl10DodWitjOEH0vvnIcsppSxH1C1dCAi0o9
f/1y2XuLNhBNHMAyTqpYPX8Yvav1c+Z50OMaSXHAnTa20zv8UtiHbaAhwlifCelU
Mj93S
-----END CERTIFICATE-----');
$this->assertFalse($x509->validateSignature());
}
public function testLooseComparison()
{
if (!extension_loaded('runkit')) {
return false;
}
define('FILE_X509_IGNORE_TYPE', true);
$x509 = new X509();
$x509->loadCA('-----BEGIN CERTIFICATE-----
MIIEbDCCA1SgAwIBAgIUJguKOMpJm/yRMDlMOW04NV0YPXowDQYJKoZIhvcNAQEF
BQAwYTELMAkGA1UEBhMCUEwxNzA1BgNVBAoTLkNaaUMgQ2VudHJhc3QgU0EgdyBp
bWllbml1IE1pbmlzdHJhIEdvc3BvZGFya2kxGTAXBgNVBAMTEENaaUMgQ2VudHJh
c3QgU0EwHhcNMDkwNDI5MTE1MzIxWhcNMTMxMjEzMjM1OTU5WjBzMQswCQYDVQQG
EwJQTDEoMCYGA1UEChMfS3Jham93YSBJemJhIFJvemxpY3plbmlvd2EgUy5BLjEk
MCIGA1UEAxMbQ09QRSBTWkFGSVIgLSBLd2FsaWZpa293YW55MRQwEgYDVQQFEwtO
ciB3cGlzdTogNjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIjNy3EL
oK0uKTqAJokiP8VIxER/0OfwhY4DBhJGW38W6Pfema8iUs4net0NgoIeDpMQ8IHj
FDSKkSaRkyL5f7PgvqBwzKe0HD1Duf9G/Lr2lu/J4QUMF3rqKaMRipXKkkEoKrub
Qe41/mPiPXeClNswNQUEyInqWpfWNncU8AIs2GKIFTfSNqK4PgWOY1kG9MYfoNVr
74dhejv7yHexEw9eAIcM1fIkEEq0vWIOjRtBXBAuWtUyD8iSeBs4nIN+614pHIjv
ncHxG7xTDbmOAVZFgGZ8Hk5CUseAtTpazQNdU66XRUuCj4km01L4wsfZ1X8tfYQA
6msMRYj+F7hLtoECAwEAAaOCAQgwggEEMA8GA1UdEwEB/wQFMAMBAf8wgY4GA1Ud
IwSBhjCBg4AU2a7r85Cp1iJNW0Ca1LR6VG3996ShZaRjMGExCzAJBgNVBAYTAlBM
MTcwNQYDVQQKEy5DWmlDIENlbnRyYXN0IFNBIHcgaW1pZW5pdSBNaW5pc3RyYSBH
b3Nwb2RhcmtpMRkwFwYDVQQDExBDWmlDIENlbnRyYXN0IFNBggQ9/0sQMDEGA1Ud
IAEB/wQnMCUwIwYEVR0gADAbMBkGCCsGAQUFBwIBFg13d3cubmNjZXJ0LnBsMA4G
A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU3TGldJXipN4oGS3ZYmnBDMFs8gIwDQYJ
KoZIhvcNAQEFBQADggEBAJrkn3XycfimT5C6D+lYvQNB4/X44KZRhxhnplMOdr/V
3O13oJA/G2SkVaRZS1Rqy01vC9H3YSFfYnjFXJTOXldzodwszHEcGLHF/3JazHI9
BTpP1F4oFyd0Un/wkp1usGU4e1riU5RAlSp8YcMX3q+nOqyCh0JsxnP7LjauHkE3
KZ1RuBDZYbsYOwkAKjHax8srKugdWtq4sMNcqpxGFUah/4uLQn6hD4jeRpP4VGDv
HZDmxaIoJdmCxfn9XeIS5PcZR+mHHkUOIhYLnfdUp/T3Yxxo+XrrTckC6AjtsL5/
OA0vBLngVqqeuzVf0tUhcrCwPKQo5rKoakbApeXrows=
-----END CERTIFICATE-----');
$x509->loadX509('-----BEGIN CERTIFICATE-----
MIIFzzCCBLegAwIBAgIDAfdlMA0GCSqGSIb3DQEBBQUAMHMxCzAJBgNVBAYTAlBM
MSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYD
VQQDDBtDT1BFIFNaQUZJUiAtIEt3YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdw
aXN1OiA2MB4XDTExMTEwOTA2MDAwMFoXDTEzMTEwOTA2MDAwMFowgdkxCzAJBgNV
BAYTAlBMMRwwGgYDVQQKDBNVcnrEhWQgTWlhc3RhIEdkeW5pMRswGQYDVQQFExJQ
RVNFTDogNjEwNjA2MDMxMTgxGTAXBgNVBAMMEEplcnp5IFByemV3b3Jza2kxTzBN
BgNVBBAwRgwiQWwuIE1hcnN6YcWCa2EgUGnFgnN1ZHNraWVnbyA1Mi81NAwNODEt
MzgyIEdkeW5pYQwGUG9sc2thDAlwb21vcnNraWUxDjAMBgNVBCoMBUplcnp5MRMw
EQYDVQQEDApQcnpld29yc2tpMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCM
m5vjGqHPthJCMqKpqssSISRos0PYDTcEQzyyurfX67EJWKtZj6HNwuDMEGJ02iBN
ZfjUl7r8dIi28bSKhNlsfycXZKYRcIjp0+r5RqtR2auo9GQ6veKb61DEAGIqaR+u
LLcJVTHCu0w9oXLGbRlGth5eNoj03CxXVAH2IfhbNwIDAQABo4IChzCCAoMwDAYD
VR0TAQH/BAIwADCCAUgGA1UdIAEB/wSCATwwggE4MIIBNAYJKoRoAYb3IwEBMIIB
JTCB3QYIKwYBBQUHAgIwgdAMgc1EZWtsYXJhY2phIHRhIGplc3Qgb8Wbd2lhZGN6
ZW5pZW0gd3lkYXdjeSwgxbxlIHRlbiBjZXJ0eWZpa2F0IHpvc3RhxYIgd3lkYW55
IGpha28gY2VydHlmaWthdCBrd2FsaWZpa293YW55IHpnb2RuaWUgeiB3eW1hZ2Fu
aWFtaSB1c3Rhd3kgbyBwb2RwaXNpZSBlbGVrdHJvbmljem55bSBvcmF6IHRvd2Fy
enlzesSFY3ltaSBqZWogcm96cG9yesSFZHplbmlhbWkuMEMGCCsGAQUFBwIBFjdo
dHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN6eS9wb2xpdHlr
YS5odG1sMAkGA1UdCQQCMAAwIQYDVR0RBBowGIEWai5wcnpld29yc2tpQGdkeW5p
YS5wbDAOBgNVHQ8BAf8EBAMCBkAwgZ4GA1UdIwSBljCBk4AU3TGldJXipN4oGS3Z
YmnBDMFs8gKhd6R1MHMxCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6
YmEgUm96bGljemVuaW93YSBTLkEuMSQwIgYDVQQDDBtDT1BFIFNaQUZJUiAtIEt3
YWxpZmlrb3dhbnkxFDASBgNVBAUTC05yIHdwaXN1OiA2ggJb9jBIBgNVHR8EQTA/
MD2gO6A5hjdodHRwOi8vd3d3Lmtpci5jb20ucGwvY2VydHlmaWthY2phX2tsdWN6
eS9DUkxfT1pLMzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQBYPIqnAreyeql7/opJ
jcar/qWZy9ruhB2q0lZFsJOhwgMnbQXzp/4vv93YJqcHGAXdHP6EO8FQX47mjo2Z
KQmi+cIHJHLONdX/3Im+M17V0iNAh7Z1lOSfTRT+iiwe/F8phcEaD5q2RmvYusR7
zXZq/cLL0If0hXoPZ/EHQxjN8pxzxiUx6bJAgturnIMEfRNesxwghdr1dkUjOhGL
f3kHVzgM6j3VAM7oFmMUb5y5s96Bzl10DodWitjOEH0vvnIcsppSxH1C1dCAi0o9
f/1y2XuLNhBNHMAyTqpYPX8Yvav1c+Z50OMaSXHAnTa20zv8UtiHbaAhwlifCelU
Mj93S
-----END CERTIFICATE-----');
$this->assertTrue($x509->validateSignature());
runkit_constant_remove('FILE_X509_IGNORE_TYPE');
}
} }