diff options
author | Anton Luka Šijanec <anton@sijanec.eu> | 2022-01-11 12:35:47 +0100 |
---|---|---|
committer | Anton Luka Šijanec <anton@sijanec.eu> | 2022-01-11 12:35:47 +0100 |
commit | 19985dbb8c0aa66dc4bf7905abc1148de909097d (patch) | |
tree | 2cd5a5d20d7e80fc2a51adf60d838d8a2c40999e /vendor/fgrosse/phpasn1/lib/X509 | |
download | 1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.tar 1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.tar.gz 1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.tar.bz2 1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.tar.lz 1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.tar.xz 1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.tar.zst 1ka-19985dbb8c0aa66dc4bf7905abc1148de909097d.zip |
Diffstat (limited to 'vendor/fgrosse/phpasn1/lib/X509')
-rw-r--r-- | vendor/fgrosse/phpasn1/lib/X509/AlgorithmIdentifier.php | 22 | ||||
-rw-r--r-- | vendor/fgrosse/phpasn1/lib/X509/CSR/Attributes.php | 68 | ||||
-rw-r--r-- | vendor/fgrosse/phpasn1/lib/X509/CSR/CSR.php | 159 | ||||
-rw-r--r-- | vendor/fgrosse/phpasn1/lib/X509/CertificateExtensions.php | 100 | ||||
-rw-r--r-- | vendor/fgrosse/phpasn1/lib/X509/CertificateSubject.php | 108 | ||||
-rw-r--r-- | vendor/fgrosse/phpasn1/lib/X509/PrivateKey.php | 35 | ||||
-rw-r--r-- | vendor/fgrosse/phpasn1/lib/X509/PublicKey.php | 35 | ||||
-rw-r--r-- | vendor/fgrosse/phpasn1/lib/X509/SAN/DNSName.php | 28 | ||||
-rw-r--r-- | vendor/fgrosse/phpasn1/lib/X509/SAN/IPAddress.php | 73 | ||||
-rw-r--r-- | vendor/fgrosse/phpasn1/lib/X509/SAN/SubjectAlternativeNames.php | 96 |
10 files changed, 724 insertions, 0 deletions
diff --git a/vendor/fgrosse/phpasn1/lib/X509/AlgorithmIdentifier.php b/vendor/fgrosse/phpasn1/lib/X509/AlgorithmIdentifier.php new file mode 100644 index 0000000..a06b56f --- /dev/null +++ b/vendor/fgrosse/phpasn1/lib/X509/AlgorithmIdentifier.php @@ -0,0 +1,22 @@ +<?php +/* + * This file is part of the PHPASN1 library. + * + * Copyright © Friedrich Große <friedrich.grosse@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509; + +use FG\ASN1\Universal\NullObject; +use FG\ASN1\Composite\AttributeTypeAndValue; + +class AlgorithmIdentifier extends AttributeTypeAndValue +{ + public function __construct($objectIdentifierString) + { + parent::__construct($objectIdentifierString, new NullObject()); + } +} diff --git a/vendor/fgrosse/phpasn1/lib/X509/CSR/Attributes.php b/vendor/fgrosse/phpasn1/lib/X509/CSR/Attributes.php new file mode 100644 index 0000000..5a965e2 --- /dev/null +++ b/vendor/fgrosse/phpasn1/lib/X509/CSR/Attributes.php @@ -0,0 +1,68 @@ +<?php +/* + * This file is part of the PHPASN1 library. + * + * Copyright © Friedrich Große <friedrich.grosse@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509\CSR; + +use FG\ASN1\ASNObject; +use FG\X509\CertificateExtensions; +use FG\ASN1\OID; +use FG\ASN1\Parsable; +use FG\ASN1\Construct; +use FG\ASN1\Identifier; +use FG\ASN1\Universal\Set; +use FG\ASN1\Universal\Sequence; +use FG\ASN1\Universal\ObjectIdentifier; + +class Attributes extends Construct implements Parsable +{ + public function getType() + { + return 0xA0; + } + + public function addAttribute($objectIdentifier, Set $attribute) + { + if (is_string($objectIdentifier)) { + $objectIdentifier = new ObjectIdentifier($objectIdentifier); + } + $attributeSequence = new Sequence($objectIdentifier, $attribute); + $attributeSequence->getNumberOfLengthOctets(); // length and number of length octets is calculated + $this->addChild($attributeSequence); + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], 0xA0, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + $octetsToRead = $contentLength; + + $parsedObject = new self(); + while ($octetsToRead > 0) { + $initialOffset = $offsetIndex; // used to calculate how much bits have been read + self::parseIdentifier($binaryData[$offsetIndex], Identifier::SEQUENCE, $offsetIndex++); + self::parseContentLength($binaryData, $offsetIndex); + + $objectIdentifier = ObjectIdentifier::fromBinary($binaryData, $offsetIndex); + $oidString = $objectIdentifier->getContent(); + if ($oidString == OID::PKCS9_EXTENSION_REQUEST) { + $attribute = CertificateExtensions::fromBinary($binaryData, $offsetIndex); + } else { + $attribute = ASNObject::fromBinary($binaryData, $offsetIndex); + } + + $parsedObject->addAttribute($objectIdentifier, $attribute); + $octetsToRead -= ($offsetIndex - $initialOffset); + } + + $parsedObject->setContentLength($contentLength); + + return $parsedObject; + } +} diff --git a/vendor/fgrosse/phpasn1/lib/X509/CSR/CSR.php b/vendor/fgrosse/phpasn1/lib/X509/CSR/CSR.php new file mode 100644 index 0000000..53f9aeb --- /dev/null +++ b/vendor/fgrosse/phpasn1/lib/X509/CSR/CSR.php @@ -0,0 +1,159 @@ +<?php
+/*
+ * This file is part of the PHPASN1 library.
+ *
+ * Copyright © Friedrich Große <friedrich.grosse@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace FG\X509\CSR;
+
+use FG\ASN1\OID;
+use FG\ASN1\Universal\Integer;
+use FG\ASN1\Universal\BitString;
+use FG\ASN1\Universal\Sequence;
+use FG\X509\CertificateSubject;
+use FG\X509\AlgorithmIdentifier;
+use FG\X509\PublicKey;
+
+class CSR extends Sequence
+{
+ const CSR_VERSION_NR = 0;
+
+ protected $subject;
+ protected $publicKey;
+ protected $signature;
+ protected $signatureAlgorithm;
+
+ protected $startSequence;
+
+ /**
+ * @param string $commonName
+ * @param string $email
+ * @param string $organization
+ * @param string $locality
+ * @param string $state
+ * @param string $country
+ * @param string $organizationalUnit
+ * @param string $publicKey
+ * @param string $signature
+ * @param string $signatureAlgorithm
+ */
+ public function __construct($commonName, $email, $organization, $locality, $state, $country, $organizationalUnit, $publicKey, $signature = null, $signatureAlgorithm = OID::SHA1_WITH_RSA_SIGNATURE)
+ {
+ $this->subject = new CertificateSubject(
+ $commonName,
+ $email,
+ $organization,
+ $locality,
+ $state,
+ $country,
+ $organizationalUnit
+ );
+ $this->publicKey = $publicKey;
+ $this->signature = $signature;
+ $this->signatureAlgorithm = $signatureAlgorithm;
+
+ if (isset($signature)) {
+ $this->createCSRSequence();
+ }
+ }
+
+ protected function createCSRSequence()
+ {
+ $versionNr = new Integer(self::CSR_VERSION_NR);
+ $publicKey = new PublicKey($this->publicKey);
+ $signature = new BitString($this->signature);
+ $signatureAlgorithm = new AlgorithmIdentifier($this->signatureAlgorithm);
+
+ $certRequestInfo = new Sequence($versionNr, $this->subject, $publicKey);
+
+ // Clear the underlying Construct
+ $this->rewind();
+ $this->children = [];
+ $this->addChild($certRequestInfo);
+ $this->addChild($signatureAlgorithm);
+ $this->addChild($signature);
+ }
+
+ public function getSignatureSubject()
+ {
+ $versionNr = new Integer(self::CSR_VERSION_NR);
+ $publicKey = new PublicKey($this->publicKey);
+
+ $certRequestInfo = new Sequence($versionNr, $this->subject, $publicKey);
+ return $certRequestInfo->getBinary();
+ }
+
+ public function setSignature($signature, $signatureAlgorithm = OID::SHA1_WITH_RSA_SIGNATURE)
+ {
+ $this->signature = $signature;
+ $this->signatureAlgorithm = $signatureAlgorithm;
+
+ $this->createCSRSequence();
+ }
+
+ public function __toString()
+ {
+ $tmp = base64_encode($this->getBinary());
+
+ for ($i = 0; $i < strlen($tmp); $i++) {
+ if (($i + 2) % 65 == 0) {
+ $tmp = substr($tmp, 0, $i + 1)."\n".substr($tmp, $i + 1);
+ }
+ }
+
+ $result = '-----BEGIN CERTIFICATE REQUEST-----'.PHP_EOL;
+ $result .= $tmp.PHP_EOL;
+ $result .= '-----END CERTIFICATE REQUEST-----';
+
+ return $result;
+ }
+
+ public function getVersion()
+ {
+ return self::CSR_VERSION_NR;
+ }
+
+ public function getOrganizationName()
+ {
+ return $this->subject->getOrganization();
+ }
+
+ public function getLocalName()
+ {
+ return $this->subject->getLocality();
+ }
+
+ public function getState()
+ {
+ return $this->subject->getState();
+ }
+
+ public function getCountry()
+ {
+ return $this->subject->getCountry();
+ }
+
+ public function getOrganizationalUnit()
+ {
+ return $this->subject->getOrganizationalUnit();
+ }
+
+ public function getPublicKey()
+ {
+ return $this->publicKey;
+ }
+
+ public function getSignature()
+ {
+ return $this->signature;
+ }
+
+ public function getSignatureAlgorithm()
+ {
+ return $this->signatureAlgorithm;
+ }
+}
diff --git a/vendor/fgrosse/phpasn1/lib/X509/CertificateExtensions.php b/vendor/fgrosse/phpasn1/lib/X509/CertificateExtensions.php new file mode 100644 index 0000000..6ed1c6a --- /dev/null +++ b/vendor/fgrosse/phpasn1/lib/X509/CertificateExtensions.php @@ -0,0 +1,100 @@ +<?php +/* + * This file is part of the PHPASN1 library. + * + * Copyright © Friedrich Große <friedrich.grosse@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509; + +use FG\ASN1\Exception\ParserException; +use FG\ASN1\OID; +use FG\ASN1\ASNObject; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; +use FG\ASN1\Universal\OctetString; +use FG\ASN1\Universal\Set; +use FG\ASN1\Universal\Sequence; +use FG\ASN1\Universal\ObjectIdentifier; +use FG\X509\SAN\SubjectAlternativeNames; + +class CertificateExtensions extends Set implements Parsable +{ + private $innerSequence; + private $extensions = []; + + public function __construct() + { + $this->innerSequence = new Sequence(); + parent::__construct($this->innerSequence); + } + + public function addSubjectAlternativeNames(SubjectAlternativeNames $sans) + { + $this->addExtension(OID::CERT_EXT_SUBJECT_ALT_NAME, $sans); + } + + private function addExtension($oidString, ASNObject $extension) + { + $sequence = new Sequence(); + $sequence->addChild(new ObjectIdentifier($oidString)); + $sequence->addChild($extension); + + $this->innerSequence->addChild($sequence); + $this->extensions[] = $extension; + } + + public function getContent() + { + return $this->extensions; + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::SET, $offsetIndex++); + self::parseContentLength($binaryData, $offsetIndex); + + $tmpOffset = $offsetIndex; + $extensions = Sequence::fromBinary($binaryData, $offsetIndex); + $tmpOffset += 1 + $extensions->getNumberOfLengthOctets(); + + $parsedObject = new self(); + foreach ($extensions as $extension) { + if ($extension->getType() != Identifier::SEQUENCE) { + //FIXME wrong offset index + throw new ParserException('Could not parse Certificate Extensions: Expected ASN.1 Sequence but got '.$extension->getTypeName(), $offsetIndex); + } + + $tmpOffset += 1 + $extension->getNumberOfLengthOctets(); + $children = $extension->getChildren(); + if (count($children) < 2) { + throw new ParserException('Could not parse Certificate Extensions: Needs at least two child elements per extension sequence (object identifier and octet string)', $tmpOffset); + } + /** @var \FG\ASN1\ASNObject $objectIdentifier */ + $objectIdentifier = $children[0]; + + /** @var OctetString $octetString */ + $octetString = $children[1]; + + if ($objectIdentifier->getType() != Identifier::OBJECT_IDENTIFIER) { + throw new ParserException('Could not parse Certificate Extensions: Expected ASN.1 Object Identifier but got '.$extension->getTypeName(), $tmpOffset); + } + + $tmpOffset += $objectIdentifier->getObjectLength(); + + if ($objectIdentifier->getContent() == OID::CERT_EXT_SUBJECT_ALT_NAME) { + $sans = SubjectAlternativeNames::fromBinary($binaryData, $tmpOffset); + $parsedObject->addSubjectAlternativeNames($sans); + } else { + // can now only parse SANs. There might be more in the future + $tmpOffset += $octetString->getObjectLength(); + } + } + + $parsedObject->getBinary(); // Determine the number of content octets and object sizes once (just to let the equality unit tests pass :/ ) + return $parsedObject; + } +} diff --git a/vendor/fgrosse/phpasn1/lib/X509/CertificateSubject.php b/vendor/fgrosse/phpasn1/lib/X509/CertificateSubject.php new file mode 100644 index 0000000..0a04d57 --- /dev/null +++ b/vendor/fgrosse/phpasn1/lib/X509/CertificateSubject.php @@ -0,0 +1,108 @@ +<?php +/* + * This file is part of the PHPASN1 library. + * + * Copyright © Friedrich Große <friedrich.grosse@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509; + +use FG\ASN1\Composite\RelativeDistinguishedName; +use FG\ASN1\Identifier; +use FG\ASN1\OID; +use FG\ASN1\Parsable; +use FG\ASN1\Composite\RDNString; +use FG\ASN1\Universal\Sequence; + +class CertificateSubject extends Sequence implements Parsable +{ + private $commonName; + private $email; + private $organization; + private $locality; + private $state; + private $country; + private $organizationalUnit; + + /** + * @param string $commonName + * @param string $email + * @param string $organization + * @param string $locality + * @param string $state + * @param string $country + * @param string $organizationalUnit + */ + public function __construct($commonName, $email, $organization, $locality, $state, $country, $organizationalUnit) + { + parent::__construct( + new RDNString(OID::COUNTRY_NAME, $country), + new RDNString(OID::STATE_OR_PROVINCE_NAME, $state), + new RDNString(OID::LOCALITY_NAME, $locality), + new RDNString(OID::ORGANIZATION_NAME, $organization), + new RDNString(OID::OU_NAME, $organizationalUnit), + new RDNString(OID::COMMON_NAME, $commonName), + new RDNString(OID::PKCS9_EMAIL, $email) + ); + + $this->commonName = $commonName; + $this->email = $email; + $this->organization = $organization; + $this->locality = $locality; + $this->state = $state; + $this->country = $country; + $this->organizationalUnit = $organizationalUnit; + } + + public function getCommonName() + { + return $this->commonName; + } + + public function getEmail() + { + return $this->email; + } + + public function getOrganization() + { + return $this->organization; + } + + public function getLocality() + { + return $this->locality; + } + + public function getState() + { + return $this->state; + } + + public function getCountry() + { + return $this->country; + } + + public function getOrganizationalUnit() + { + return $this->organizationalUnit; + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::SEQUENCE, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + + $names = []; + $octetsToRead = $contentLength; + while ($octetsToRead > 0) { + $relativeDistinguishedName = RelativeDistinguishedName::fromBinary($binaryData, $offsetIndex); + $octetsToRead -= $relativeDistinguishedName->getObjectLength(); + $names[] = $relativeDistinguishedName; + } + } +} diff --git a/vendor/fgrosse/phpasn1/lib/X509/PrivateKey.php b/vendor/fgrosse/phpasn1/lib/X509/PrivateKey.php new file mode 100644 index 0000000..d57ad86 --- /dev/null +++ b/vendor/fgrosse/phpasn1/lib/X509/PrivateKey.php @@ -0,0 +1,35 @@ +<?php +/* + * This file is part of the PHPASN1 library. + * + * Copyright © Friedrich Große <friedrich.grosse@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509; + +use FG\ASN1\OID; +use FG\ASN1\Universal\NullObject; +use FG\ASN1\Universal\Sequence; +use FG\ASN1\Universal\BitString; +use FG\ASN1\Universal\ObjectIdentifier; + +class PrivateKey extends Sequence +{ + /** + * @param string $hexKey + * @param \FG\ASN1\ASNObject|string $algorithmIdentifierString + */ + public function __construct($hexKey, $algorithmIdentifierString = OID::RSA_ENCRYPTION) + { + parent::__construct( + new Sequence( + new ObjectIdentifier($algorithmIdentifierString), + new NullObject() + ), + new BitString($hexKey) + ); + } +} diff --git a/vendor/fgrosse/phpasn1/lib/X509/PublicKey.php b/vendor/fgrosse/phpasn1/lib/X509/PublicKey.php new file mode 100644 index 0000000..ab8b451 --- /dev/null +++ b/vendor/fgrosse/phpasn1/lib/X509/PublicKey.php @@ -0,0 +1,35 @@ +<?php +/* + * This file is part of the PHPASN1 library. + * + * Copyright © Friedrich Große <friedrich.grosse@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509; + +use FG\ASN1\OID; +use FG\ASN1\Universal\NullObject; +use FG\ASN1\Universal\Sequence; +use FG\ASN1\Universal\BitString; +use FG\ASN1\Universal\ObjectIdentifier; + +class PublicKey extends Sequence +{ + /** + * @param string $hexKey + * @param \FG\ASN1\ASNObject|string $algorithmIdentifierString + */ + public function __construct($hexKey, $algorithmIdentifierString = OID::RSA_ENCRYPTION) + { + parent::__construct( + new Sequence( + new ObjectIdentifier($algorithmIdentifierString), + new NullObject() + ), + new BitString($hexKey) + ); + } +} diff --git a/vendor/fgrosse/phpasn1/lib/X509/SAN/DNSName.php b/vendor/fgrosse/phpasn1/lib/X509/SAN/DNSName.php new file mode 100644 index 0000000..502738b --- /dev/null +++ b/vendor/fgrosse/phpasn1/lib/X509/SAN/DNSName.php @@ -0,0 +1,28 @@ +<?php +/* + * This file is part of the PHPASN1 library. + * + * Copyright © Friedrich Große <friedrich.grosse@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509\SAN; + +use FG\ASN1\Universal\GeneralString; + +class DNSName extends GeneralString +{ + const IDENTIFIER = 0x82; // not sure yet why this is the identifier used in SAN extensions + + public function __construct($dnsNameString) + { + parent::__construct($dnsNameString); + } + + public function getType() + { + return self::IDENTIFIER; + } +} diff --git a/vendor/fgrosse/phpasn1/lib/X509/SAN/IPAddress.php b/vendor/fgrosse/phpasn1/lib/X509/SAN/IPAddress.php new file mode 100644 index 0000000..f55be95 --- /dev/null +++ b/vendor/fgrosse/phpasn1/lib/X509/SAN/IPAddress.php @@ -0,0 +1,73 @@ +<?php +/* + * This file is part of the PHPASN1 library. + * + * Copyright © Friedrich Große <friedrich.grosse@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509\SAN; + +use FG\ASN1\ASNObject; +use FG\ASN1\Parsable; +use FG\ASN1\Exception\ParserException; + +class IPAddress extends ASNObject implements Parsable +{ + const IDENTIFIER = 0x87; // not sure yet why this is the identifier used in SAN extensions + + /** @var string */ + private $value; + + public function __construct($ipAddressString) + { + $this->value = $ipAddressString; + } + + public function getType() + { + return self::IDENTIFIER; + } + + public function getContent() + { + return $this->value; + } + + protected function calculateContentLength() + { + return 4; + } + + protected function getEncodedValue() + { + $ipParts = explode('.', $this->value); + $binary = chr($ipParts[0]); + $binary .= chr($ipParts[1]); + $binary .= chr($ipParts[2]); + $binary .= chr($ipParts[3]); + + return $binary; + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], self::IDENTIFIER, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + if ($contentLength != 4) { + throw new ParserException("A FG\\X509\SAN\IPAddress should have a content length of 4. Extracted length was {$contentLength}", $offsetIndex); + } + + $ipAddressString = ord($binaryData[$offsetIndex++]).'.'; + $ipAddressString .= ord($binaryData[$offsetIndex++]).'.'; + $ipAddressString .= ord($binaryData[$offsetIndex++]).'.'; + $ipAddressString .= ord($binaryData[$offsetIndex++]); + + $parsedObject = new self($ipAddressString); + $parsedObject->getObjectLength(); + + return $parsedObject; + } +} diff --git a/vendor/fgrosse/phpasn1/lib/X509/SAN/SubjectAlternativeNames.php b/vendor/fgrosse/phpasn1/lib/X509/SAN/SubjectAlternativeNames.php new file mode 100644 index 0000000..271ddde --- /dev/null +++ b/vendor/fgrosse/phpasn1/lib/X509/SAN/SubjectAlternativeNames.php @@ -0,0 +1,96 @@ +<?php +/* + * This file is part of the PHPASN1 library. + * + * Copyright © Friedrich Große <friedrich.grosse@gmail.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace FG\X509\SAN; + +use FG\ASN1\Exception\ParserException; +use FG\ASN1\ASNObject; +use FG\ASN1\OID; +use FG\ASN1\Parsable; +use FG\ASN1\Identifier; +use FG\ASN1\Universal\Sequence; + +/** + * See section 8.3.2.1 of ITU-T X.509. + */ +class SubjectAlternativeNames extends ASNObject implements Parsable +{ + private $alternativeNamesSequence; + + public function __construct() + { + $this->alternativeNamesSequence = new Sequence(); + } + + protected function calculateContentLength() + { + return $this->alternativeNamesSequence->getObjectLength(); + } + + public function getType() + { + return Identifier::OCTETSTRING; + } + + public function addDomainName(DNSName $domainName) + { + $this->alternativeNamesSequence->addChild($domainName); + } + + public function addIP(IPAddress $ip) + { + $this->alternativeNamesSequence->addChild($ip); + } + + public function getContent() + { + return $this->alternativeNamesSequence->getContent(); + } + + protected function getEncodedValue() + { + return $this->alternativeNamesSequence->getBinary(); + } + + public static function fromBinary(&$binaryData, &$offsetIndex = 0) + { + self::parseIdentifier($binaryData[$offsetIndex], Identifier::OCTETSTRING, $offsetIndex++); + $contentLength = self::parseContentLength($binaryData, $offsetIndex); + + if ($contentLength < 2) { + throw new ParserException('Can not parse Subject Alternative Names: The Sequence within the octet string after the Object identifier '.OID::CERT_EXT_SUBJECT_ALT_NAME." is too short ({$contentLength} octets)", $offsetIndex); + } + + $offsetOfSequence = $offsetIndex; + $sequence = Sequence::fromBinary($binaryData, $offsetIndex); + $offsetOfSequence += $sequence->getNumberOfLengthOctets() + 1; + + if ($sequence->getObjectLength() != $contentLength) { + throw new ParserException('Can not parse Subject Alternative Names: The Sequence length does not match the length of the surrounding octet string', $offsetIndex); + } + + $parsedObject = new self(); + /** @var \FG\ASN1\ASNObject $object */ + foreach ($sequence as $object) { + if ($object->getType() == DNSName::IDENTIFIER) { + $domainName = DNSName::fromBinary($binaryData, $offsetOfSequence); + $parsedObject->addDomainName($domainName); + } elseif ($object->getType() == IPAddress::IDENTIFIER) { + $ip = IPAddress::fromBinary($binaryData, $offsetOfSequence); + $parsedObject->addIP($ip); + } else { + throw new ParserException('Could not parse Subject Alternative Name: Only DNSName and IP SANs are currently supported', $offsetIndex); + } + } + + $parsedObject->getBinary(); // Determine the number of content octets and object sizes once (just to let the equality unit tests pass :/ ) + return $parsedObject; + } +} |