public function format(PublicKeyInterface $key) { if (!$key->getCurve() instanceof NamedCurveFp) { throw new \RuntimeException('Not implemented for unnamed curves'); } $sequence = new Sequence(new Sequence(new ObjectIdentifier(DerPublicKeySerializer::X509_ECDSA_OID), CurveOidMapper::getCurveOid($key->getCurve())), new BitString($this->encodePoint($key->getPoint()))); return $sequence->getBinary(); }
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); }
/** * @param NamedCurveFp $c * @param GeneratorPoint $G * @return string */ public function serialize(NamedCurveFp $c, GeneratorPoint $G) { $math = $G->getAdapter(); $fieldID = $this->getFieldIdAsn($math, $c); $curve = $this->getCurveAsn($math, $c); $domain = new Sequence(new Integer(1), $fieldID, $curve, new OctetString($this->pointSerializer->serialize($G)), new Integer($G->getOrder()), new Integer(1)); $payload = $domain->getBinary(); $content = self::HEADER . PHP_EOL . trim(chunk_split(base64_encode($payload), 64, PHP_EOL)) . PHP_EOL . self::FOOTER; return $content; }
public function testParseBase64() { $sequence = new Sequence(new Set(new ObjectIdentifier('1.2.250.1.16.9'), new Sequence(new Integer(42), new BitString('A0 12 00 43')))); $data = base64_encode($sequence->getBinary()); $template = [Identifier::SEQUENCE => [Identifier::SET => [Identifier::OBJECT_IDENTIFIER, Identifier::SEQUENCE => [Identifier::INTEGER, Identifier::BITSTRING]]]]; $parser = new TemplateParser(); $object = $parser->parseBase64($data, $template); $this->assertInstanceOf(Set::class, $object[0]); $this->assertInstanceOf(ObjectIdentifier::class, $object[0][0]); $this->assertInstanceOf(Sequence::class, $object[0][1]); $this->assertInstanceOf(Integer::class, $object[0][1][0]); $this->assertInstanceOf(BitString::class, $object[0][1][1]); }
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\Object $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; }
/** * @param ObjectIdentifier|string $objIdentifier * @param \FG\ASN1\Object $value */ public function __construct($objIdentifier, Object $value) { if ($objIdentifier instanceof ObjectIdentifier == false) { $objIdentifier = new ObjectIdentifier($objIdentifier); } parent::__construct($objIdentifier, $value); }
public function testREADME_encoding() { $this->expectOutputString('MBgCAwHiQAEB/woBARYLSGVsbG8gd29ybGQxODAYAgMB4kABAf8KAQEWC0hlbGxvIHdvcmxkBQAGBiqBegEQCQYJKoZIhvcNAQEBEwdGb28gYmFy'); $integer = new Integer(123456); $boolean = new Boolean(true); $enum = new Enumerated(1); $ia5String = new IA5String('Hello world'); $asnNull = new NullObject(); $objectIdentifier1 = new ObjectIdentifier('1.2.250.1.16.9'); $objectIdentifier2 = new ObjectIdentifier(OID::RSA_ENCRYPTION); $printableString = new PrintableString('Foo bar'); $sequence = new Sequence($integer, $boolean, $enum, $ia5String); $set = new Set($sequence, $asnNull, $objectIdentifier1, $objectIdentifier2, $printableString); $myBinary = $sequence->getBinary(); $myBinary .= $set->getBinary(); echo base64_encode($myBinary); }
/** * @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; }
/** * @depends testFromBinary */ public function testFromBinaryWithOffset() { $originalObject1 = new Sequence(new Boolean(true), new Integer(123)); $originalObject2 = new Sequence(new Integer(64), new Boolean(false)); $binaryData = $originalObject1->getBinary(); $binaryData .= $originalObject2->getBinary(); $offset = 0; $parsedObject = Sequence::fromBinary($binaryData, $offset); $this->assertEquals($originalObject1, $parsedObject); $this->assertEquals(8, $offset); $parsedObject = Sequence::fromBinary($binaryData, $offset); $this->assertEquals($originalObject2, $parsedObject); $this->assertEquals(16, $offset); }
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\Object $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; }
<?php require_once __DIR__ . '/../vendor/autoload.php'; use FG\ASN1\OID; use FG\ASN1\Universal\Integer; use FG\ASN1\Universal\Boolean; use FG\ASN1\Universal\Enumerated; use FG\ASN1\Universal\IA5String; use FG\ASN1\Universal\ObjectIdentifier; use FG\ASN1\Universal\PrintableString; use FG\ASN1\Universal\Sequence; use FG\ASN1\Universal\Set; use FG\ASN1\Universal\NullObject; $integer = new Integer(123456); $boolean = new Boolean(true); $enum = new Enumerated(1); $ia5String = new IA5String('Hello world'); $asnNull = new NullObject(); $objectIdentifier1 = new ObjectIdentifier('1.2.250.1.16.9'); $objectIdentifier2 = new ObjectIdentifier(OID::RSA_ENCRYPTION); $printableString = new PrintableString('Foo bar'); $sequence = new Sequence($integer, $boolean, $enum, $ia5String); $set = new Set($sequence, $asnNull, $objectIdentifier1, $objectIdentifier2, $printableString); $myBinary = $sequence->getBinary(); $myBinary .= $set->getBinary(); echo base64_encode($myBinary);
/** * @param Sequence $sigSection * @return string * @throws \Exception */ public function parseSigAlg(Sequence $sigSection) { $sigInfo = $sigSection->getContent(); if (!$sigInfo[0] instanceof ObjectIdentifier) { throw new \Exception('Invaid sig: object identfier'); } return SigAlgorithmOidMapper::getAlgorithmFromOid($sigInfo[0]); }
/** * */ private function initPrivateKey() { $this->addChild(new Integer(0)); $oid_sequence = new Sequence(); $oid_sequence->addChild(new ObjectIdentifier('1.2.840.113549.1.1.1')); $oid_sequence->addChild(new NullObject()); $this->addChild($oid_sequence); $v = new Integer(0); $n = new Integer($this->fromBase64ToInteger($this->n)); $e = new Integer($this->fromBase64ToInteger($this->e)); $d = new Integer($this->fromBase64ToInteger($this->d)); $p = new Integer($this->fromBase64ToInteger($this->p)); $q = new Integer($this->fromBase64ToInteger($this->q)); $dp = new Integer($this->fromBase64ToInteger($this->dp)); $dq = new Integer($this->fromBase64ToInteger($this->dq)); $qi = new Integer($this->fromBase64ToInteger($this->qi)); $key_sequence = new Sequence(); $key_sequence->addChild($v); $key_sequence->addChild($n); $key_sequence->addChild($e); $key_sequence->addChild($d); $key_sequence->addChild($p); $key_sequence->addChild($q); $key_sequence->addChild($dp); $key_sequence->addChild($dq); $key_sequence->addChild($qi); $key_octet_string = new OctetString(bin2hex($key_sequence->getBinary())); $this->addChild($key_octet_string); }
/** * {@inheritDoc} * @see \Mdanter\Ecc\Serializer\PrivateKeySerializerInterface::serialize() */ public function serialize(PrivateKeyInterface $key) { $privateKeyInfo = new Sequence(new Integer(self::VERSION), new OctetString($this->formatKey($key)), new ExplicitlyTaggedObject(0, CurveOidMapper::getCurveOid($key->getPoint()->getCurve())), new ExplicitlyTaggedObject(1, $this->encodePubKey($key))); return $privateKeyInfo->getBinary(); }
private function initPublicKey() { $oid_sequence = new Sequence(); $oid_sequence->addChild(new ObjectIdentifier('1.2.840.10045.2.1')); $oid_sequence->addChild(new ObjectIdentifier($this->getOID($this->values['crv']))); $this->addChild($oid_sequence); $bits = '04'; $bits .= bin2hex(Base64Url::decode($this->values['x'])); $bits .= bin2hex(Base64Url::decode($this->values['y'])); $this->addChild(new BitString($bits)); }
// this should contain a sequence of extensions $certExtensions = $certExtensions->getFirstChild(); assert($certExtensions->getType() == Identifier::SEQUENCE); // now check all extensions and search for the SAN /** @var Object $extensionSequence */ foreach ($certExtensions as $extensionSequence) { assert($extensionSequence->getType() == Identifier::SEQUENCE); assert($extensionSequence->getNumberofChildren() >= 2); $extensionSequenceChildren = $extensionSequence->getChildren(); $objectIdentifier = $extensionSequenceChildren[0]; /* @var ObjectIdentifier $objectIdentifier */ assert($objectIdentifier->getType() == Identifier::OBJECT_IDENTIFIER); if ($objectIdentifier->getContent() == OID::CERT_EXT_SUBJECT_ALT_NAME) { // now we have the wanted octet string $octetString = $extensionSequenceChildren[1]; /* @var OctetString $octetString */ $octetStringBinary = $octetString->getBinaryContent(); // At this point you may want to create the sequence from the binary value of // the octet string and parse its structure like we did so far. // However a more general approach would be to understand the format of the // contained SAN fields and implement them in SubjectAlternativeNames. $sequence = Sequence::fromBinary($octetStringBinary); echo 'This is the parsed content of the SAN certificate extension field so far:' . PHP_EOL; printObject($sequence); // The following does not work yet because PHPASN1 SAn does only support DNS and IP //SubjectAlternativeNames::fromBinary($octetStringBinary); } } } catch (\Exception $exception) { echo '[ERROR] Caught exception:' . PHP_EOL . $exception->getMessage() . PHP_EOL; }
/** * @param string $binaryData * @param int $offsetIndex * * @throws ParserException * * @return \FG\ASN1\Object */ public static function fromBinary(&$binaryData, &$offsetIndex = 0) { if (strlen($binaryData) <= $offsetIndex) { throw new ParserException('Can not parse binary from data: Offset index larger than input size', $offsetIndex); } $identifierOctet = ord($binaryData[$offsetIndex]); if (Identifier::isContextSpecificClass($identifierOctet) && Identifier::isConstructed($identifierOctet)) { return ExplicitlyTaggedObject::fromBinary($binaryData, $offsetIndex); } switch ($identifierOctet) { case Identifier::BITSTRING: return BitString::fromBinary($binaryData, $offsetIndex); case Identifier::BOOLEAN: return Boolean::fromBinary($binaryData, $offsetIndex); case Identifier::ENUMERATED: return Enumerated::fromBinary($binaryData, $offsetIndex); case Identifier::INTEGER: return Integer::fromBinary($binaryData, $offsetIndex); case Identifier::NULL: return NullObject::fromBinary($binaryData, $offsetIndex); case Identifier::OBJECT_IDENTIFIER: return ObjectIdentifier::fromBinary($binaryData, $offsetIndex); case Identifier::RELATIVE_OID: return RelativeObjectIdentifier::fromBinary($binaryData, $offsetIndex); case Identifier::OCTETSTRING: return OctetString::fromBinary($binaryData, $offsetIndex); case Identifier::SEQUENCE: return Sequence::fromBinary($binaryData, $offsetIndex); case Identifier::SET: return Set::fromBinary($binaryData, $offsetIndex); case Identifier::UTC_TIME: return UTCTime::fromBinary($binaryData, $offsetIndex); case Identifier::GENERALIZED_TIME: return GeneralizedTime::fromBinary($binaryData, $offsetIndex); case Identifier::IA5_STRING: return IA5String::fromBinary($binaryData, $offsetIndex); case Identifier::PRINTABLE_STRING: return PrintableString::fromBinary($binaryData, $offsetIndex); case Identifier::NUMERIC_STRING: return NumericString::fromBinary($binaryData, $offsetIndex); case Identifier::UTF8_STRING: return UTF8String::fromBinary($binaryData, $offsetIndex); case Identifier::UNIVERSAL_STRING: return UniversalString::fromBinary($binaryData, $offsetIndex); case Identifier::CHARACTER_STRING: return CharacterString::fromBinary($binaryData, $offsetIndex); case Identifier::GENERAL_STRING: return GeneralString::fromBinary($binaryData, $offsetIndex); case Identifier::VISIBLE_STRING: return VisibleString::fromBinary($binaryData, $offsetIndex); case Identifier::GRAPHIC_STRING: return GraphicString::fromBinary($binaryData, $offsetIndex); case Identifier::BMP_STRING: return BMPString::fromBinary($binaryData, $offsetIndex); case Identifier::T61_STRING: return T61String::fromBinary($binaryData, $offsetIndex); case Identifier::OBJECT_DESCRIPTOR: return ObjectDescriptor::fromBinary($binaryData, $offsetIndex); default: // At this point the identifier may be >1 byte. if (Identifier::isConstructed($identifierOctet)) { return new UnknownConstructedObject($binaryData, $offsetIndex); } else { $identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex); $lengthOfUnknownObject = self::parseContentLength($binaryData, $offsetIndex); $offsetIndex += $lengthOfUnknownObject; return new UnknownObject($identifier, $lengthOfUnknownObject); } } }
/** * @param \Jose\Object\JWKInterface $key * @param string $data * @param string $R * @param string $S * * @return bool */ private function verifyOpenSSLSignature(JWKInterface $key, $data, $R, $S) { $pem = ECKey::toPublic(new ECKey($key))->toPEM(); $oid_sequence = new Sequence(); $oid_sequence->addChildren([new Integer(gmp_strval($this->convertHexToGmp($R), 10)), new Integer(gmp_strval($this->convertHexToGmp($S), 10))]); return 1 === openssl_verify($data, $oid_sequence->getBinary(), $pem, $this->getHashAlgorithm()); }
/** * @param string $hexKey * @param \FG\ASN1\Object|string $algorithmIdentifierString */ public function __construct($hexKey, $algorithmIdentifierString = OID::RSA_ENCRYPTION) { parent::__construct(new Sequence(new ObjectIdentifier($algorithmIdentifierString), new NullObject()), new BitString($hexKey)); }
private function initPrivateKey() { $this->addChild(new Integer(0)); $oid_sequence = new Sequence(); $oid_sequence->addChild(new ObjectIdentifier('1.2.840.113549.1.1.1')); $oid_sequence->addChild(new NullObject()); $this->addChild($oid_sequence); $v = new Integer(0); $n = new Integer($this->fromBase64ToInteger($this->values['n'])); $e = new Integer($this->fromBase64ToInteger($this->values['e'])); $d = new Integer($this->fromBase64ToInteger($this->values['d'])); $p = new Integer($this->fromBase64ToInteger($this->values['p'])); $q = new Integer($this->fromBase64ToInteger($this->values['q'])); $dp = array_key_exists('dp', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['dp'])) : new Integer(0); $dq = array_key_exists('dq', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['dq'])) : new Integer(0); $qi = array_key_exists('qi', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['qi'])) : new Integer(0); $key_sequence = new Sequence(); $key_sequence->addChild($v); $key_sequence->addChild($n); $key_sequence->addChild($e); $key_sequence->addChild($d); $key_sequence->addChild($p); $key_sequence->addChild($q); $key_sequence->addChild($dp); $key_sequence->addChild($dq); $key_sequence->addChild($qi); $key_octet_string = new OctetString(bin2hex($key_sequence->getBinary())); $this->addChild($key_octet_string); }
mk+8uP4/x61UWBliqW08/1jMA83Qj2yuCAvhMhmuq8BvyWP4jnXoxTy3iTZFDXIj 5Vg2FlHWna0TMsU5jlmv8W/mu9U3+q7i1+339JrEZkrDLNDpJ23gqKBgC1OaNH7+ vicBRmoP5kj2X62XMaKT5TMFBZzTtSF7IaUjt9SVXQjG3aHIy7D1mOypvEw4LSS+ RvvJTezSQeCoLpX7HziRnoVUNkJWZHL2wG5rb/SJzpXwHkRa7R250vN8TFtSSsp4 YXzK6aks/qkxRJ1UkBLUAZlRasUD+zu8gyTIz0sNgFrOtx8EOzjZRiJ/vBiVOn88 Brf4i0D+fVXmJQIDAQABow8wDTALBgNVHQ8EBAMCAAIwCwYJKoZIhvcNAQEFA4IB AQBfubKPTvmDGrDxoqCbPwFoPRC0STwPL2GV8f5sD/Sbyc0NoJdygUO2DvquGGn5 6UJCfLo1u6Dn4zuuDs3m6if86HTpAf9Z3a72ok2Tor/NFwYt+vDOrFY5F4bXDZkf u4zuDLmjpj26Dk4te3BVohsLTXbvJ5a/TT2VanwNOyx85lXPxy3V8Rr1AwlmHZoz DDbUGbe/noUDJCgMjvaKKvLykIhIcW+g6W7SOcKRflw5H8kzDv816XFODSC3X1Uw o3aVy9du/0mH+g4HvyVVplO90tdoHD1gHUMZwuen4dbTzhWv4dtLFelWM5lGWbLE Wn7kJghclgIxv10nkGyfrowt'; // OCSP response status according to // https://tools.ietf.org/html/rfc6960#section-4.2.1 $validResponseStatuses = array(0 => 'Response has valid confirmations', 1 => 'Illegal confirmation request', 2 => 'Internal error in issuer', 3 => 'Try again later', 5 => 'Must sign the request', 6 => 'Request unauthorized'); $ocspResponse = Sequence::fromBinary(base64_decode($data)); /* @var Enumerated $responseStatus */ $elements = $ocspResponse->getChildren(); $responseStatus = $elements[0]; $responseStatusCode = $responseStatus->getContent(); echo PHP_EOL; echo "OCSP response status: {$responseStatusCode} ({$validResponseStatuses[$responseStatusCode]})" . PHP_EOL; /** @var ExplicitlyTaggedObject $responseBytes */ $responseBytes = $elements[1]; /** @var Sequence $responseBytesSequence */ $responseBytesSequence = $responseBytes->getContent(); /** @var ObjectIdentifier $responseType */ $responseType = $responseBytesSequence->getChildren()[0]; echo "ResponseType: {$responseType}" . PHP_EOL; $response = $responseBytesSequence->getChildren()[1]; echo "Response (octet string): {$response}" . PHP_EOL;