Update website

This commit is contained in:
Guilhem Lavaux 2024-11-19 09:35:33 +01:00
parent bb4b0f9be8
commit 011b183e28
4263 changed files with 3014 additions and 720369 deletions

View file

@ -1,355 +0,0 @@
<?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\ASN1;
use FG\ASN1\Exception\ParserException;
use FG\ASN1\Universal\BitString;
use FG\ASN1\Universal\Boolean;
use FG\ASN1\Universal\Enumerated;
use FG\ASN1\Universal\GeneralizedTime;
use FG\ASN1\Universal\Integer;
use FG\ASN1\Universal\NullObject;
use FG\ASN1\Universal\ObjectIdentifier;
use FG\ASN1\Universal\RelativeObjectIdentifier;
use FG\ASN1\Universal\OctetString;
use FG\ASN1\Universal\Sequence;
use FG\ASN1\Universal\Set;
use FG\ASN1\Universal\UTCTime;
use FG\ASN1\Universal\IA5String;
use FG\ASN1\Universal\PrintableString;
use FG\ASN1\Universal\NumericString;
use FG\ASN1\Universal\UTF8String;
use FG\ASN1\Universal\UniversalString;
use FG\ASN1\Universal\CharacterString;
use FG\ASN1\Universal\GeneralString;
use FG\ASN1\Universal\VisibleString;
use FG\ASN1\Universal\GraphicString;
use FG\ASN1\Universal\BMPString;
use FG\ASN1\Universal\T61String;
use FG\ASN1\Universal\ObjectDescriptor;
use FG\Utility\BigInteger;
use LogicException;
/**
* Class ASNObject is the base class for all concrete ASN.1 objects.
*/
abstract class ASNObject implements Parsable
{
private $contentLength;
private $nrOfLengthOctets;
/**
* Must return the number of octets of the content part.
*
* @return int
*/
abstract protected function calculateContentLength();
/**
* Encode the object using DER encoding.
*
* @see http://en.wikipedia.org/wiki/X.690#DER_encoding
*
* @return string the binary representation of an objects value
*/
abstract protected function getEncodedValue();
/**
* Return the content of this object in a non encoded form.
* This can be used to print the value in human readable form.
*
* @return mixed
*/
abstract public function getContent();
/**
* Return the object type octet.
* This should use the class constants of Identifier.
*
* @see Identifier
*
* @return int
*/
abstract public function getType();
/**
* Returns all identifier octets. If an inheriting class models a tag with
* the long form identifier format, it MUST reimplement this method to
* return all octets of the identifier.
*
* @throws LogicException If the identifier format is long form
*
* @return string Identifier as a set of octets
*/
public function getIdentifier()
{
$firstOctet = $this->getType();
if (Identifier::isLongForm($firstOctet)) {
throw new LogicException(sprintf('Identifier of %s uses the long form and must therefor override "ASNObject::getIdentifier()".', get_class($this)));
}
return chr($firstOctet);
}
/**
* Encode this object using DER encoding.
*
* @return string the full binary representation of the complete object
*/
public function getBinary()
{
$result = $this->getIdentifier();
$result .= $this->createLengthPart();
$result .= $this->getEncodedValue();
return $result;
}
private function createLengthPart()
{
$contentLength = $this->getContentLength();
$nrOfLengthOctets = $this->getNumberOfLengthOctets($contentLength);
if ($nrOfLengthOctets == 1) {
return chr($contentLength);
} else {
// the first length octet determines the number subsequent length octets
$lengthOctets = chr(0x80 | ($nrOfLengthOctets - 1));
for ($shiftLength = 8 * ($nrOfLengthOctets - 2); $shiftLength >= 0; $shiftLength -= 8) {
$lengthOctets .= chr($contentLength >> $shiftLength);
}
return $lengthOctets;
}
}
protected function getNumberOfLengthOctets($contentLength = null)
{
if (!isset($this->nrOfLengthOctets)) {
if ($contentLength == null) {
$contentLength = $this->getContentLength();
}
$this->nrOfLengthOctets = 1;
if ($contentLength > 127) {
do { // long form
$this->nrOfLengthOctets++;
$contentLength = $contentLength >> 8;
} while ($contentLength > 0);
}
}
return $this->nrOfLengthOctets;
}
protected function getContentLength()
{
if (!isset($this->contentLength)) {
$this->contentLength = $this->calculateContentLength();
}
return $this->contentLength;
}
protected function setContentLength($newContentLength)
{
$this->contentLength = $newContentLength;
$this->getNumberOfLengthOctets($newContentLength);
}
/**
* Returns the length of the whole object (including the identifier and length octets).
*/
public function getObjectLength()
{
$nrOfIdentifierOctets = strlen($this->getIdentifier());
$contentLength = $this->getContentLength();
$nrOfLengthOctets = $this->getNumberOfLengthOctets($contentLength);
return $nrOfIdentifierOctets + $nrOfLengthOctets + $contentLength;
}
public function __toString()
{
return $this->getContent();
}
/**
* Returns the name of the ASN.1 Type of this object.
*
* @see Identifier::getName()
*/
public function getTypeName()
{
return Identifier::getName($this->getType());
}
/**
* @param string $binaryData
* @param int $offsetIndex
*
* @throws ParserException
*
* @return \FG\ASN1\ASNObject
*/
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);
}
}
}
protected static function parseIdentifier($identifierOctet, $expectedIdentifier, $offsetForExceptionHandling)
{
if (is_string($identifierOctet) || is_numeric($identifierOctet) == false) {
$identifierOctet = ord($identifierOctet);
}
if ($identifierOctet != $expectedIdentifier) {
$message = 'Can not create an '.Identifier::getName($expectedIdentifier).' from an '.Identifier::getName($identifierOctet);
throw new ParserException($message, $offsetForExceptionHandling);
}
}
protected static function parseBinaryIdentifier($binaryData, &$offsetIndex)
{
if (strlen($binaryData) <= $offsetIndex) {
throw new ParserException('Can not parse identifier from data: Offset index larger than input size', $offsetIndex);
}
$identifier = $binaryData[$offsetIndex++];
if (Identifier::isLongForm(ord($identifier)) == false) {
return $identifier;
}
while (true) {
if (strlen($binaryData) <= $offsetIndex) {
throw new ParserException('Can not parse identifier (long form) from data: Offset index larger than input size', $offsetIndex);
}
$nextOctet = $binaryData[$offsetIndex++];
$identifier .= $nextOctet;
if ((ord($nextOctet) & 0x80) === 0) {
// the most significant bit is 0 to we have reached the end of the identifier
break;
}
}
return $identifier;
}
protected static function parseContentLength(&$binaryData, &$offsetIndex, $minimumLength = 0)
{
if (strlen($binaryData) <= $offsetIndex) {
throw new ParserException('Can not parse content length from data: Offset index larger than input size', $offsetIndex);
}
$contentLength = ord($binaryData[$offsetIndex++]);
if (($contentLength & 0x80) != 0) {
// bit 8 is set -> this is the long form
$nrOfLengthOctets = $contentLength & 0x7F;
$contentLength = BigInteger::create(0x00);
for ($i = 0; $i < $nrOfLengthOctets; $i++) {
if (strlen($binaryData) <= $offsetIndex) {
throw new ParserException('Can not parse content length (long form) from data: Offset index larger than input size', $offsetIndex);
}
$contentLength = $contentLength->shiftLeft(8)->add(ord($binaryData[$offsetIndex++]));
}
if ($contentLength->compare(PHP_INT_MAX) > 0) {
throw new ParserException("Can not parse content length from data: length > maximum integer", $offsetIndex);
}
$contentLength = $contentLength->toInteger();
}
if ($contentLength < $minimumLength) {
throw new ParserException('A '.get_called_class()." should have a content length of at least {$minimumLength}. Extracted length was {$contentLength}", $offsetIndex);
}
$lenDataRemaining = strlen($binaryData) - $offsetIndex;
if ($lenDataRemaining < $contentLength) {
throw new ParserException("Content length {$contentLength} exceeds remaining data length {$lenDataRemaining}", $offsetIndex);
}
return $contentLength;
}
}

View file

@ -1,136 +0,0 @@
<?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\ASN1;
use Exception;
abstract class AbstractString extends ASNObject implements Parsable
{
/** @var string */
protected $value;
private $checkStringForIllegalChars = true;
private $allowedCharacters = [];
/**
* The abstract base class for ASN.1 classes which represent some string of character.
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
}
public function getContent()
{
return $this->value;
}
protected function allowCharacter($character)
{
$this->allowedCharacters[] = $character;
}
protected function allowCharacters(...$characters)
{
foreach ($characters as $character) {
$this->allowedCharacters[] = $character;
}
}
protected function allowNumbers()
{
foreach (range('0', '9') as $char) {
$this->allowedCharacters[] = (string) $char;
}
}
protected function allowAllLetters()
{
$this->allowSmallLetters();
$this->allowCapitalLetters();
}
protected function allowSmallLetters()
{
foreach (range('a', 'z') as $char) {
$this->allowedCharacters[] = $char;
}
}
protected function allowCapitalLetters()
{
foreach (range('A', 'Z') as $char) {
$this->allowedCharacters[] = $char;
}
}
protected function allowSpaces()
{
$this->allowedCharacters[] = ' ';
}
protected function allowAll()
{
$this->checkStringForIllegalChars = false;
}
protected function calculateContentLength()
{
return strlen($this->value);
}
protected function getEncodedValue()
{
if ($this->checkStringForIllegalChars) {
$this->checkString();
}
return $this->value;
}
protected function checkString()
{
$stringLength = $this->getContentLength();
for ($i = 0; $i < $stringLength; $i++) {
if (in_array($this->value[$i], $this->allowedCharacters) == false) {
$typeName = Identifier::getName($this->getType());
throw new Exception("Could not create a {$typeName} from the character sequence '{$this->value}'.");
}
}
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
$parsedObject = new static('');
self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
$string = substr($binaryData, $offsetIndex, $contentLength);
$offsetIndex += $contentLength;
$parsedObject->value = $string;
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
public static function isValid($string)
{
$testObject = new static($string);
try {
$testObject->checkString();
return true;
} catch (Exception $exception) {
return false;
}
}
}

View file

@ -1,78 +0,0 @@
<?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\ASN1;
use DateInterval;
use DateTime;
use DateTimeZone;
use Exception;
abstract class AbstractTime extends ASNObject
{
/** @var DateTime */
protected $value;
public function __construct($dateTime = null, $dateTimeZone = 'UTC')
{
if ($dateTime == null || is_string($dateTime)) {
$timeZone = new DateTimeZone($dateTimeZone);
$dateTimeObject = new DateTime($dateTime, $timeZone);
if ($dateTimeObject == false) {
$errorMessage = $this->getLastDateTimeErrors();
$className = Identifier::getName($this->getType());
throw new Exception(sprintf("Could not create %s from date time string '%s': %s", $className, $dateTime, $errorMessage));
}
$dateTime = $dateTimeObject;
} elseif (!$dateTime instanceof DateTime) {
throw new Exception('Invalid first argument for some instance of AbstractTime constructor');
}
$this->value = $dateTime;
}
public function getContent()
{
return $this->value;
}
protected function getLastDateTimeErrors()
{
$messages = '';
$lastErrors = DateTime::getLastErrors() ?: ['errors' => []];
foreach ($lastErrors['errors'] as $errorMessage) {
$messages .= "{$errorMessage}, ";
}
return substr($messages, 0, -2);
}
public function __toString()
{
return $this->value->format("Y-m-d\tH:i:s");
}
protected static function extractTimeZoneData(&$binaryData, &$offsetIndex, DateTime $dateTime)
{
$sign = $binaryData[$offsetIndex++];
$timeOffsetHours = intval(substr($binaryData, $offsetIndex, 2));
$timeOffsetMinutes = intval(substr($binaryData, $offsetIndex + 2, 2));
$offsetIndex += 4;
$interval = new DateInterval("PT{$timeOffsetHours}H{$timeOffsetMinutes}M");
if ($sign == '+') {
$dateTime->sub($interval);
} else {
$dateTime->add($interval);
}
return $dateTime;
}
}

View file

@ -1,63 +0,0 @@
<?php
namespace FG\ASN1;
use FG\Utility\BigInteger;
use InvalidArgumentException;
/**
* A base-128 decoder.
*/
class Base128
{
/**
* @param int $value
*
* @return string
*/
public static function encode($value)
{
$value = BigInteger::create($value);
$octets = chr($value->modulus(0x80)->toInteger());
$value = $value->shiftRight(7);
while ($value->compare(0) > 0) {
$octets .= chr(0x80 | $value->modulus(0x80)->toInteger());
$value = $value->shiftRight(7);
}
return strrev($octets);
}
/**
* @param string $octets
*
* @throws InvalidArgumentException if the given octets represent a malformed base-128 value or the decoded value would exceed the the maximum integer length
*
* @return int
*/
public static function decode($octets)
{
$bitsPerOctet = 7;
$value = BigInteger::create(0);
$i = 0;
while (true) {
if (!isset($octets[$i])) {
throw new InvalidArgumentException(sprintf('Malformed base-128 encoded value (0x%s).', strtoupper(bin2hex($octets)) ?: '0'));
}
$octet = ord($octets[$i++]);
$l1 = $value->shiftLeft($bitsPerOctet);
$r1 = $octet & 0x7f;
$value = $l1->add($r1);
if (0 === ($octet & 0x80)) {
break;
}
}
return (string)$value;
}
}

View file

@ -1,35 +0,0 @@
<?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\ASN1\Composite;
use FG\ASN1\ASNObject;
use FG\ASN1\Universal\Sequence;
use FG\ASN1\Universal\ObjectIdentifier;
class AttributeTypeAndValue extends Sequence
{
/**
* @param ObjectIdentifier|string $objIdentifier
* @param \FG\ASN1\ASNObject $value
*/
public function __construct($objIdentifier, ASNObject $value)
{
if ($objIdentifier instanceof ObjectIdentifier == false) {
$objIdentifier = new ObjectIdentifier($objIdentifier);
}
parent::__construct($objIdentifier, $value);
}
public function __toString()
{
return $this->children[0].': '.$this->children[1];
}
}

View file

@ -1,37 +0,0 @@
<?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\ASN1\Composite;
use FG\ASN1\Universal\PrintableString;
use FG\ASN1\Universal\IA5String;
use FG\ASN1\Universal\UTF8String;
class RDNString extends RelativeDistinguishedName
{
/**
* @param string|\FG\ASN1\Universal\ObjectIdentifier $objectIdentifierString
* @param string|\FG\ASN1\ASNObject $value
*/
public function __construct($objectIdentifierString, $value)
{
if (PrintableString::isValid($value)) {
$value = new PrintableString($value);
} else {
if (IA5String::isValid($value)) {
$value = new IA5String($value);
} else {
$value = new UTF8String($value);
}
}
parent::__construct($objectIdentifierString, $value);
}
}

View file

@ -1,50 +0,0 @@
<?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\ASN1\Composite;
use FG\ASN1\Exception\NotImplementedException;
use FG\ASN1\ASNObject;
use FG\ASN1\Universal\Set;
class RelativeDistinguishedName extends Set
{
/**
* @param string|\FG\ASN1\Universal\ObjectIdentifier $objIdentifierString
* @param \FG\ASN1\ASNObject $value
*/
public function __construct($objIdentifierString, ASNObject $value)
{
// TODO: This does only support one element in the RelativeDistinguishedName Set but it it is defined as follows:
// RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
parent::__construct(new AttributeTypeAndValue($objIdentifierString, $value));
}
public function getContent()
{
/** @var \FG\ASN1\ASNObject $firstObject */
$firstObject = $this->children[0];
return $firstObject->__toString();
}
/**
* At the current version this code can not work since the implementation of Construct requires
* the class to support a constructor without arguments.
*
* @deprecated this function is not yet implemented! Feel free to submit a pull request on github
* @param string $binaryData
* @param int $offsetIndex
* @throws NotImplementedException
*/
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
throw new NotImplementedException();
}
}

View file

@ -1,202 +0,0 @@
<?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\ASN1;
use ArrayAccess;
use ArrayIterator;
use Countable;
use FG\ASN1\Exception\ParserException;
use Iterator;
abstract class Construct extends ASNObject implements Countable, ArrayAccess, Iterator, Parsable
{
/** @var \FG\ASN1\ASNObject[] */
protected $children;
private $iteratorPosition;
/**
* @param \FG\ASN1\ASNObject[] $children the variadic type hint is commented due to https://github.com/facebook/hhvm/issues/4858
*/
public function __construct(/* HH_FIXME[4858]: variadic + strict */ ...$children)
{
$this->children = $children;
$this->iteratorPosition = 0;
}
public function getContent()
{
return $this->children;
}
#[\ReturnTypeWillChange]
public function rewind()
{
$this->iteratorPosition = 0;
}
#[\ReturnTypeWillChange]
public function current()
{
return $this->children[$this->iteratorPosition];
}
#[\ReturnTypeWillChange]
public function key()
{
return $this->iteratorPosition;
}
#[\ReturnTypeWillChange]
public function next()
{
$this->iteratorPosition++;
}
#[\ReturnTypeWillChange]
public function valid()
{
return isset($this->children[$this->iteratorPosition]);
}
#[\ReturnTypeWillChange]
public function offsetExists($offset)
{
return array_key_exists($offset, $this->children);
}
#[\ReturnTypeWillChange]
public function offsetGet($offset)
{
return $this->children[$offset];
}
#[\ReturnTypeWillChange]
public function offsetSet($offset, $value)
{
if ($offset === null) {
$offset = count($this->children);
}
$this->children[$offset] = $value;
}
#[\ReturnTypeWillChange]
public function offsetUnset($offset)
{
unset($this->children[$offset]);
}
protected function calculateContentLength()
{
$length = 0;
foreach ($this->children as $component) {
$length += $component->getObjectLength();
}
return $length;
}
protected function getEncodedValue()
{
$result = '';
foreach ($this->children as $component) {
$result .= $component->getBinary();
}
return $result;
}
public function addChild(ASNObject $child)
{
$this->children[] = $child;
}
public function addChildren(array $children)
{
foreach ($children as $child) {
$this->addChild($child);
}
}
public function __toString()
{
$nrOfChildren = $this->getNumberOfChildren();
$childString = $nrOfChildren == 1 ? 'child' : 'children';
return "[{$nrOfChildren} {$childString}]";
}
public function getNumberOfChildren()
{
return count($this->children);
}
/**
* @return \FG\ASN1\ASNObject[]
*/
public function getChildren()
{
return $this->children;
}
/**
* @return \FG\ASN1\ASNObject
*/
public function getFirstChild()
{
return $this->children[0];
}
/**
* @param string $binaryData
* @param int $offsetIndex
*
* @throws Exception\ParserException
*
* @return Construct|static
*/
#[\ReturnTypeWillChange]
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
$parsedObject = new static();
self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
$startIndex = $offsetIndex;
$children = [];
$octetsToRead = $contentLength;
while ($octetsToRead > 0) {
$newChild = ASNObject::fromBinary($binaryData, $offsetIndex);
$octetsToRead -= $newChild->getObjectLength();
$children[] = $newChild;
}
if ($octetsToRead !== 0) {
throw new ParserException("Sequence length incorrect", $startIndex);
}
$parsedObject->addChildren($children);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
#[\ReturnTypeWillChange]
public function count($mode = COUNT_NORMAL)
{
return count($this->children, $mode);
}
public function getIterator()
{
return new ArrayIterator($this->children);
}
}

View file

@ -1,15 +0,0 @@
<?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\ASN1\Exception;
class NotImplementedException extends \Exception
{
}

View file

@ -1,29 +0,0 @@
<?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\ASN1\Exception;
class ParserException extends \Exception
{
private $errorMessage;
private $offset;
public function __construct($errorMessage, $offset)
{
$this->errorMessage = $errorMessage;
$this->offset = $offset;
parent::__construct("ASN.1 Parser Exception at offset {$this->offset}: {$this->errorMessage}");
}
public function getOffset()
{
return $this->offset;
}
}

View file

@ -1,131 +0,0 @@
<?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\ASN1;
use FG\ASN1\Exception\ParserException;
/**
* Class ExplicitlyTaggedObject decorate an inner object with an additional tag that gives information about
* its context specific meaning.
*
* Explanation taken from A Layman's Guide to a Subset of ASN.1, BER, and DER:
* >>> An RSA Laboratories Technical Note
* >>> Burton S. Kaliski Jr.
* >>> Revised November 1, 1993
*
* [...]
* Explicitly tagged types are derived from other types by adding an outer tag to the underlying type.
* In effect, explicitly tagged types are structured types consisting of one component, the underlying type.
* Explicit tagging is denoted by the ASN.1 keywords [class number] EXPLICIT (see Section 5.2).
* [...]
*
* @see http://luca.ntop.org/Teaching/Appunti/asn1.html
*/
class ExplicitlyTaggedObject extends ASNObject
{
/** @var \FG\ASN1\ASNObject[] */
private $decoratedObjects;
private $tag;
/**
* @param int $tag
* @param \FG\ASN1\ASNObject $objects,...
*/
public function __construct($tag, /* HH_FIXME[4858]: variadic + strict */ ...$objects)
{
$this->tag = $tag;
$this->decoratedObjects = $objects;
}
protected function calculateContentLength()
{
$length = 0;
foreach ($this->decoratedObjects as $object) {
$length += $object->getObjectLength();
}
return $length;
}
protected function getEncodedValue()
{
$encoded = '';
foreach ($this->decoratedObjects as $object) {
$encoded .= $object->getBinary();
}
return $encoded;
}
public function getContent()
{
return $this->decoratedObjects;
}
public function __toString()
{
switch ($length = count($this->decoratedObjects)) {
case 0:
return "Context specific empty object with tag [{$this->tag}]";
case 1:
$decoratedType = Identifier::getShortName($this->decoratedObjects[0]->getType());
return "Context specific $decoratedType with tag [{$this->tag}]";
default:
return "$length context specific objects with tag [{$this->tag}]";
}
}
public function getType()
{
return ord($this->getIdentifier());
}
public function getIdentifier()
{
$identifier = Identifier::create(Identifier::CLASS_CONTEXT_SPECIFIC, true, $this->tag);
return is_int($identifier) ? chr($identifier) : $identifier;
}
public function getTag()
{
return $this->tag;
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
$identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex);
$firstIdentifierOctet = ord($identifier);
assert(Identifier::isContextSpecificClass($firstIdentifierOctet), 'identifier octet should indicate context specific class');
assert(Identifier::isConstructed($firstIdentifierOctet), 'identifier octet should indicate constructed object');
$tag = Identifier::getTagNumber($identifier);
$totalContentLength = self::parseContentLength($binaryData, $offsetIndex);
$remainingContentLength = $totalContentLength;
$offsetIndexOfDecoratedObject = $offsetIndex;
$decoratedObjects = [];
while ($remainingContentLength > 0) {
$nextObject = ASNObject::fromBinary($binaryData, $offsetIndex);
$remainingContentLength -= $nextObject->getObjectLength();
$decoratedObjects[] = $nextObject;
}
if ($remainingContentLength != 0) {
throw new ParserException("Context-Specific explicitly tagged object [$tag] starting at offset $offsetIndexOfDecoratedObject specifies a length of $totalContentLength octets but $remainingContentLength remain after parsing the content", $offsetIndexOfDecoratedObject);
}
$parsedObject = new self($tag, ...$decoratedObjects);
$parsedObject->setContentLength($totalContentLength);
return $parsedObject;
}
}

View file

@ -1,339 +0,0 @@
<?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\ASN1;
use Exception;
/**
* The Identifier encodes the ASN.1 tag (class and number) of the type of a data value.
*
* Every identifier whose number is in the range 0 to 30 has the following structure:
*
* Bits: 8 7 6 5 4 3 2 1
* | Class | P/C | Tag number |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Bits 8 and 7 define the class of this type ( Universal, Application, Context-specific or Private).
* Bit 6 encoded whether this type is primitive or constructed
* The remaining bits 5 - 1 encode the tag number
*/
class Identifier
{
const CLASS_UNIVERSAL = 0x00;
const CLASS_APPLICATION = 0x01;
const CLASS_CONTEXT_SPECIFIC = 0x02;
const CLASS_PRIVATE = 0x03;
const EOC = 0x00; // unsupported for now
const BOOLEAN = 0x01;
const INTEGER = 0x02;
const BITSTRING = 0x03;
const OCTETSTRING = 0x04;
const NULL = 0x05;
const OBJECT_IDENTIFIER = 0x06;
const OBJECT_DESCRIPTOR = 0x07;
const EXTERNAL = 0x08; // unsupported for now
const REAL = 0x09; // unsupported for now
const ENUMERATED = 0x0A;
const EMBEDDED_PDV = 0x0B; // unsupported for now
const UTF8_STRING = 0x0C;
const RELATIVE_OID = 0x0D;
// value 0x0E and 0x0F are reserved for future use
const SEQUENCE = 0x30;
const SET = 0x31;
const NUMERIC_STRING = 0x12;
const PRINTABLE_STRING = 0x13;
const T61_STRING = 0x14; // sometimes referred to as TeletextString
const VIDEOTEXT_STRING = 0x15;
const IA5_STRING = 0x16;
const UTC_TIME = 0x17;
const GENERALIZED_TIME = 0x18;
const GRAPHIC_STRING = 0x19;
const VISIBLE_STRING = 0x1A;
const GENERAL_STRING = 0x1B;
const UNIVERSAL_STRING = 0x1C;
const CHARACTER_STRING = 0x1D; // Unrestricted character type
const BMP_STRING = 0x1E;
const LONG_FORM = 0x1F;
const IS_CONSTRUCTED = 0x20;
/**
* Creates an identifier. Short form identifiers are returned as integers
* for BC, long form identifiers will be returned as a string of octets.
*
* @param int $class
* @param bool $isConstructed
* @param int $tagNumber
*
* @throws Exception if the given arguments are invalid
*
* @return int|string
*/
public static function create($class, $isConstructed, $tagNumber)
{
if (!is_numeric($class) || $class < self::CLASS_UNIVERSAL || $class > self::CLASS_PRIVATE) {
throw new Exception(sprintf('Invalid class %d given', $class));
}
if (!is_bool($isConstructed)) {
throw new Exception("\$isConstructed must be a boolean value ($isConstructed given)");
}
$tagNumber = self::makeNumeric($tagNumber);
if ($tagNumber < 0) {
throw new Exception(sprintf('Invalid $tagNumber %d given. You can only use positive integers.', $tagNumber));
}
if ($tagNumber < self::LONG_FORM) {
return ($class << 6) | ($isConstructed << 5) | $tagNumber;
}
$firstOctet = ($class << 6) | ($isConstructed << 5) | self::LONG_FORM;
// Tag numbers formatted in long form are base-128 encoded. See X.609#8.1.2.4
return chr($firstOctet).Base128::encode($tagNumber);
}
public static function isConstructed($identifierOctet)
{
return ($identifierOctet & self::IS_CONSTRUCTED) === self::IS_CONSTRUCTED;
}
public static function isLongForm($identifierOctet)
{
return ($identifierOctet & self::LONG_FORM) === self::LONG_FORM;
}
/**
* Return the name of the mapped ASN.1 type with a preceding "ASN.1 ".
*
* Example: ASN.1 Octet String
*
* @see Identifier::getShortName()
*
* @param int|string $identifier
*
* @return string
*/
public static function getName($identifier)
{
$identifierOctet = self::makeNumeric($identifier);
$typeName = static::getShortName($identifier);
if (($identifierOctet & self::LONG_FORM) < self::LONG_FORM) {
$typeName = "ASN.1 {$typeName}";
}
return $typeName;
}
/**
* Return the short version of the type name.
*
* If the given identifier octet can be mapped to a known universal type this will
* return its name. Else Identifier::getClassDescription() is used to retrieve
* information about the identifier.
*
* @see Identifier::getName()
* @see Identifier::getClassDescription()
*
* @param int|string $identifier
*
* @return string
*/
public static function getShortName($identifier)
{
$identifierOctet = self::makeNumeric($identifier);
switch ($identifierOctet) {
case self::EOC:
return 'End-of-contents octet';
case self::BOOLEAN:
return 'Boolean';
case self::INTEGER:
return 'Integer';
case self::BITSTRING:
return 'Bit String';
case self::OCTETSTRING:
return 'Octet String';
case self::NULL:
return 'NULL';
case self::OBJECT_IDENTIFIER:
return 'Object Identifier';
case self::OBJECT_DESCRIPTOR:
return 'Object Descriptor';
case self::EXTERNAL:
return 'External Type';
case self::REAL:
return 'Real';
case self::ENUMERATED:
return 'Enumerated';
case self::EMBEDDED_PDV:
return 'Embedded PDV';
case self::UTF8_STRING:
return 'UTF8 String';
case self::RELATIVE_OID:
return 'Relative OID';
case self::SEQUENCE:
return 'Sequence';
case self::SET:
return 'Set';
case self::NUMERIC_STRING:
return 'Numeric String';
case self::PRINTABLE_STRING:
return 'Printable String';
case self::T61_STRING:
return 'T61 String';
case self::VIDEOTEXT_STRING:
return 'Videotext String';
case self::IA5_STRING:
return 'IA5 String';
case self::UTC_TIME:
return 'UTC Time';
case self::GENERALIZED_TIME:
return 'Generalized Time';
case self::GRAPHIC_STRING:
return 'Graphic String';
case self::VISIBLE_STRING:
return 'Visible String';
case self::GENERAL_STRING:
return 'General String';
case self::UNIVERSAL_STRING:
return 'Universal String';
case self::CHARACTER_STRING:
return 'Character String';
case self::BMP_STRING:
return 'BMP String';
case 0x0E:
return 'RESERVED (0x0E)';
case 0x0F:
return 'RESERVED (0x0F)';
case self::LONG_FORM:
default:
$classDescription = self::getClassDescription($identifier);
if (is_int($identifier)) {
$identifier = chr($identifier);
}
return "$classDescription (0x".strtoupper(bin2hex($identifier)).')';
}
}
/**
* Returns a textual description of the information encoded in a given identifier octet.
*
* The first three (most significant) bytes are evaluated to determine if this is a
* constructed or primitive type and if it is either universal, application, context-specific or
* private.
*
* Example:
* Constructed context-specific
* Primitive universal
*
* @param int|string $identifier
*
* @return string
*/
public static function getClassDescription($identifier)
{
$identifierOctet = self::makeNumeric($identifier);
if (self::isConstructed($identifierOctet)) {
$classDescription = 'Constructed ';
} else {
$classDescription = 'Primitive ';
}
$classBits = $identifierOctet >> 6;
switch ($classBits) {
case self::CLASS_UNIVERSAL:
$classDescription .= 'universal';
break;
case self::CLASS_APPLICATION:
$classDescription .= 'application';
break;
case self::CLASS_CONTEXT_SPECIFIC:
$tagNumber = self::getTagNumber($identifier);
$classDescription = "[$tagNumber] Context-specific";
break;
case self::CLASS_PRIVATE:
$classDescription .= 'private';
break;
default:
return "INVALID IDENTIFIER OCTET: {$identifierOctet}";
}
return $classDescription;
}
/**
* @param int|string $identifier
*
* @return int
*/
public static function getTagNumber($identifier)
{
$firstOctet = self::makeNumeric($identifier);
$tagNumber = $firstOctet & self::LONG_FORM;
if ($tagNumber < self::LONG_FORM) {
return $tagNumber;
}
if (is_numeric($identifier)) {
$identifier = chr($identifier);
}
return Base128::decode(substr($identifier, 1));
}
public static function isUniversalClass($identifier)
{
$identifier = self::makeNumeric($identifier);
return $identifier >> 6 == self::CLASS_UNIVERSAL;
}
public static function isApplicationClass($identifier)
{
$identifier = self::makeNumeric($identifier);
return $identifier >> 6 == self::CLASS_APPLICATION;
}
public static function isContextSpecificClass($identifier)
{
$identifier = self::makeNumeric($identifier);
return $identifier >> 6 == self::CLASS_CONTEXT_SPECIFIC;
}
public static function isPrivateClass($identifier)
{
$identifier = self::makeNumeric($identifier);
return $identifier >> 6 == self::CLASS_PRIVATE;
}
private static function makeNumeric($identifierOctet)
{
if (!is_numeric($identifierOctet)) {
return ord($identifierOctet);
} else {
return $identifierOctet;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,32 +0,0 @@
<?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\ASN1;
use FG\ASN1\Exception\ParserException;
/**
* The Parsable interface describes classes that can be parsed from their binary DER representation.
*/
interface Parsable
{
/**
* Parse an instance of this class from its binary DER encoded representation.
*
* @param string $binaryData
* @param int $offsetIndex the offset at which parsing of the $binaryData is started. This parameter ill be modified
* to contain the offset index of the next object after this object has been parsed
*
* @throws ParserException if the given binary data is either invalid or not currently supported
*
* @return static
*/
public static function fromBinary(&$binaryData, &$offsetIndex = null);
}

View file

@ -1,70 +0,0 @@
<?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\ASN1;
use Exception;
use FG\ASN1\Exception\ParserException;
use FG\ASN1\Universal\Sequence;
class TemplateParser
{
/**
* @param string $data
* @param array $template
* @return \FG\ASN1\ASNObject|Sequence
* @throws ParserException if there was an issue parsing
*/
public function parseBase64($data, array $template)
{
// TODO test with invalid data
return $this->parseBinary(base64_decode($data), $template);
}
/**
* @param string $binary
* @param array $template
* @return \FG\ASN1\ASNObject|Sequence
* @throws ParserException if there was an issue parsing
*/
public function parseBinary($binary, array $template)
{
$parsedObject = ASNObject::fromBinary($binary);
foreach ($template as $key => $value) {
$this->validate($parsedObject, $key, $value);
}
return $parsedObject;
}
private function validate(ASNObject $object, $key, $value)
{
if (is_array($value)) {
$this->assertTypeId($key, $object);
/* @var Construct $object */
foreach ($value as $key => $child) {
$this->validate($object->current(), $key, $child);
$object->next();
}
} else {
$this->assertTypeId($value, $object);
}
}
private function assertTypeId($expectedTypeId, ASNObject $object)
{
$actualType = $object->getType();
if ($expectedTypeId != $actualType) {
throw new Exception("Expected type ($expectedTypeId) does not match actual type ($actualType");
}
}
}

View file

@ -1,41 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class BMPString extends AbstractString
{
/**
* Creates a new ASN.1 BMP String.
*
* BMPString is a subtype of UniversalString that has its own
* unique tag and contains only the characters in the
* Basic Multilingual Plane (those corresponding to the first
* 64K-2 cells, less cells whose encoding is used to address
* characters outside the Basic Multilingual Plane) of ISO/IEC 10646-1.
*
* TODO The encodable characters of this type are not yet checked.
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::BMP_STRING;
}
}

View file

@ -1,88 +0,0 @@
<?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\ASN1\Universal;
use Exception;
use FG\ASN1\Exception\ParserException;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
class BitString extends OctetString implements Parsable
{
private $nrOfUnusedBits;
/**
* Creates a new ASN.1 BitString object.
*
* @param string|int $value Either the hexadecimal value as a string (spaces are allowed - leading 0x is optional) or a numeric value
* @param int $nrOfUnusedBits the number of unused bits in the last octet [optional].
*
* @throws Exception if the second parameter is no positive numeric value
*/
public function __construct($value, $nrOfUnusedBits = 0)
{
parent::__construct($value);
if (!is_numeric($nrOfUnusedBits) || $nrOfUnusedBits < 0) {
throw new Exception('BitString: second parameter needs to be a positive number (or zero)!');
}
$this->nrOfUnusedBits = $nrOfUnusedBits;
}
public function getType()
{
return Identifier::BITSTRING;
}
protected function calculateContentLength()
{
// add one to the length for the first octet which encodes the number of unused bits in the last octet
return parent::calculateContentLength() + 1;
}
protected function getEncodedValue()
{
// the first octet determines the number of unused bits
$nrOfUnusedBitsOctet = chr($this->nrOfUnusedBits);
$actualContent = parent::getEncodedValue();
return $nrOfUnusedBitsOctet.$actualContent;
}
public function getNumberOfUnusedBits()
{
return $this->nrOfUnusedBits;
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::BITSTRING, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex, 2);
$nrOfUnusedBits = ord($binaryData[$offsetIndex]);
$value = substr($binaryData, $offsetIndex + 1, $contentLength - 1);
if ($nrOfUnusedBits > 7 || // no less than 1 used, otherwise non-minimal
($contentLength - 1) == 1 && $nrOfUnusedBits > 0 || // content length only 1, no
(ord($value[strlen($value)-1])&((1<<$nrOfUnusedBits)-1)) != 0 // unused bits set
) {
throw new ParserException("Can not parse bit string with invalid padding", $offsetIndex);
}
$offsetIndex += $contentLength;
$parsedObject = new self(bin2hex($value), $nrOfUnusedBits);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View file

@ -1,75 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\ASNObject;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Exception\ParserException;
class Boolean extends ASNObject implements Parsable
{
private $value;
/**
* @param bool $value
*/
public function __construct($value)
{
$this->value = $value;
}
public function getType()
{
return Identifier::BOOLEAN;
}
protected function calculateContentLength()
{
return 1;
}
protected function getEncodedValue()
{
if ($this->value == false) {
return chr(0x00);
} else {
return chr(0xFF);
}
}
public function getContent()
{
if ($this->value == true) {
return 'TRUE';
} else {
return 'FALSE';
}
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::BOOLEAN, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
if ($contentLength != 1) {
throw new ParserException("An ASN.1 Boolean should not have a length other than one. Extracted length was {$contentLength}", $offsetIndex);
}
$value = ord($binaryData[$offsetIndex++]);
$booleanValue = $value == 0xFF ? true : false;
$parsedObject = new self($booleanValue);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View file

@ -1,28 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class CharacterString extends AbstractString
{
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::CHARACTER_STRING;
}
}

View file

@ -1,21 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\Identifier;
class Enumerated extends Integer
{
public function getType()
{
return Identifier::ENUMERATED;
}
}

View file

@ -1,34 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class GeneralString extends AbstractString
{
/**
* Creates a new ASN.1 GeneralString.
* TODO The encodable characters of this type are not yet checked.
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::GENERAL_STRING;
}
}

View file

@ -1,134 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractTime;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Exception\ParserException;
/**
* This ASN.1 universal type contains date and time information according to ISO 8601.
*
* The type consists of values representing:
* a) a calendar date, as defined in ISO 8601; and
* b) a time of day, to any of the precisions defined in ISO 8601, except for the hours value 24 which shall not be used; and
* c) the local time differential factor as defined in ISO 8601.
*
* Decoding of this type will accept the Basic Encoding Rules (BER)
* The encoding will comply with the Distinguished Encoding Rules (DER).
*/
class GeneralizedTime extends AbstractTime implements Parsable
{
private $microseconds;
public function __construct($dateTime = null, $dateTimeZone = 'UTC')
{
parent::__construct($dateTime, $dateTimeZone);
$this->microseconds = $this->value->format('u');
if ($this->containsFractionalSecondsElement()) {
// DER requires us to remove trailing zeros
$this->microseconds = preg_replace('/([1-9]+)0+$/', '$1', $this->microseconds);
}
}
public function getType()
{
return Identifier::GENERALIZED_TIME;
}
protected function calculateContentLength()
{
$contentSize = 15; // YYYYMMDDHHmmSSZ
if ($this->containsFractionalSecondsElement()) {
$contentSize += 1 + strlen($this->microseconds);
}
return $contentSize;
}
public function containsFractionalSecondsElement()
{
return intval($this->microseconds) > 0;
}
protected function getEncodedValue()
{
$encodedContent = $this->value->format('YmdHis');
if ($this->containsFractionalSecondsElement()) {
$encodedContent .= ".{$this->microseconds}";
}
return $encodedContent.'Z';
}
public function __toString()
{
if ($this->containsFractionalSecondsElement()) {
return $this->value->format("Y-m-d\tH:i:s.uP");
} else {
return $this->value->format("Y-m-d\tH:i:sP");
}
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::GENERALIZED_TIME, $offsetIndex++);
$lengthOfMinimumTimeString = 14; // YYYYMMDDHHmmSS
$contentLength = self::parseContentLength($binaryData, $offsetIndex, $lengthOfMinimumTimeString);
$maximumBytesToRead = $contentLength;
$format = 'YmdGis';
$content = substr($binaryData, $offsetIndex, $contentLength);
$dateTimeString = substr($content, 0, $lengthOfMinimumTimeString);
$offsetIndex += $lengthOfMinimumTimeString;
$maximumBytesToRead -= $lengthOfMinimumTimeString;
if ($contentLength == $lengthOfMinimumTimeString) {
$localTimeZone = new \DateTimeZone(date_default_timezone_get());
$dateTime = \DateTime::createFromFormat($format, $dateTimeString, $localTimeZone);
} else {
if ($binaryData[$offsetIndex] == '.') {
$maximumBytesToRead--; // account for the '.'
$nrOfFractionalSecondElements = 1; // account for the '.'
while ($maximumBytesToRead > 0
&& $binaryData[$offsetIndex + $nrOfFractionalSecondElements] != '+'
&& $binaryData[$offsetIndex + $nrOfFractionalSecondElements] != '-'
&& $binaryData[$offsetIndex + $nrOfFractionalSecondElements] != 'Z') {
$nrOfFractionalSecondElements++;
$maximumBytesToRead--;
}
$dateTimeString .= substr($binaryData, $offsetIndex, $nrOfFractionalSecondElements);
$offsetIndex += $nrOfFractionalSecondElements;
$format .= '.u';
}
$dateTime = \DateTime::createFromFormat($format, $dateTimeString, new \DateTimeZone('UTC'));
if ($maximumBytesToRead > 0) {
if ($binaryData[$offsetIndex] == '+'
|| $binaryData[$offsetIndex] == '-') {
$dateTime = static::extractTimeZoneData($binaryData, $offsetIndex, $dateTime);
} elseif ($binaryData[$offsetIndex++] != 'Z') {
throw new ParserException('Invalid ISO 8601 Time String', $offsetIndex);
}
}
}
$parsedObject = new self($dateTime);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View file

@ -1,34 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class GraphicString extends AbstractString
{
/**
* Creates a new ASN.1 Graphic String.
* TODO The encodable characters of this type are not yet checked.
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::GRAPHIC_STRING;
}
}

View file

@ -1,35 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
/**
* The International Alphabet No.5 (IA5) references the encoding of the ASCII characters.
*
* Each character in the data is encoded as 1 byte.
*/
class IA5String extends AbstractString
{
public function __construct($string)
{
parent::__construct($string);
for ($i = 1; $i < 128; $i++) {
$this->allowCharacter(chr($i));
}
}
public function getType()
{
return Identifier::IA5_STRING;
}
}

View file

@ -1,130 +0,0 @@
<?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\ASN1\Universal;
use Exception;
use FG\Utility\BigInteger;
use FG\ASN1\Exception\ParserException;
use FG\ASN1\ASNObject;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
class Integer extends ASNObject implements Parsable
{
/** @var int */
private $value;
/**
* @param int $value
*
* @throws Exception if the value is not numeric
*/
public function __construct($value)
{
if (is_numeric($value) == false) {
throw new Exception("Invalid VALUE [{$value}] for ASN1_INTEGER");
}
$this->value = $value;
}
public function getType()
{
return Identifier::INTEGER;
}
public function getContent()
{
return $this->value;
}
protected function calculateContentLength()
{
return strlen($this->getEncodedValue());
}
protected function getEncodedValue()
{
$value = BigInteger::create($this->value, 10);
$negative = $value->compare(0) < 0;
if ($negative) {
$value = $value->absoluteValue();
$limit = 0x80;
} else {
$limit = 0x7f;
}
$mod = 0xff+1;
$values = [];
while($value->compare($limit) > 0) {
$values[] = $value->modulus($mod)->toInteger();
$value = $value->shiftRight(8);
}
$values[] = $value->modulus($mod)->toInteger();
$numValues = count($values);
if ($negative) {
for ($i = 0; $i < $numValues; $i++) {
$values[$i] = 0xff - $values[$i];
}
for ($i = 0; $i < $numValues; $i++) {
$values[$i] += 1;
if ($values[$i] <= 0xff) {
break;
}
assert($i != $numValues - 1);
$values[$i] = 0;
}
if ($values[$numValues - 1] == 0x7f) {
$values[] = 0xff;
}
}
$values = array_reverse($values);
$r = pack("C*", ...$values);
return $r;
}
private static function ensureMinimalEncoding($binaryData, $offsetIndex)
{
// All the first nine bits cannot equal 0 or 1, which would
// be non-minimal encoding for positive and negative integers respectively
if ((ord($binaryData[$offsetIndex]) == 0x00 && (ord($binaryData[$offsetIndex+1]) & 0x80) == 0) ||
(ord($binaryData[$offsetIndex]) == 0xff && (ord($binaryData[$offsetIndex+1]) & 0x80) == 0x80)) {
throw new ParserException("Integer not minimally encoded", $offsetIndex);
}
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
$parsedObject = new static(0);
self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex, 1);
if ($contentLength > 1) {
self::ensureMinimalEncoding($binaryData, $offsetIndex);
}
$isNegative = (ord($binaryData[$offsetIndex]) & 0x80) != 0x00;
$number = BigInteger::create(ord($binaryData[$offsetIndex++]) & 0x7F);
for ($i = 0; $i < $contentLength - 1; $i++) {
$number = $number->multiply(0x100)->add(ord($binaryData[$offsetIndex++]));
}
if ($isNegative) {
$number = $number->subtract(BigInteger::create(2)->toPower(8 * $contentLength - 1));
}
$parsedObject = new static((string)$number);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View file

@ -1,54 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\ASNObject;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Exception\ParserException;
class NullObject extends ASNObject implements Parsable
{
public function getType()
{
return Identifier::NULL;
}
protected function calculateContentLength()
{
return 0;
}
protected function getEncodedValue()
{
return null;
}
public function getContent()
{
return 'NULL';
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::NULL, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
if ($contentLength != 0) {
throw new ParserException("An ASN.1 Null should not have a length other than zero. Extracted length was {$contentLength}", $offsetIndex);
}
$parsedObject = new self();
$parsedObject->setContentLength(0);
return $parsedObject;
}
}

View file

@ -1,38 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class NumericString extends AbstractString
{
/**
* Creates a new ASN.1 NumericString.
*
* The following characters are permitted:
* Digits 0,1, ... 9
* SPACE (space)
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowNumbers();
$this->allowSpaces();
}
public function getType()
{
return Identifier::NUMERIC_STRING;
}
}

View file

@ -1,26 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\Identifier;
class ObjectDescriptor extends GraphicString
{
public function __construct($objectDescription)
{
parent::__construct($objectDescription);
}
public function getType()
{
return Identifier::OBJECT_DESCRIPTOR;
}
}

View file

@ -1,138 +0,0 @@
<?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\ASN1\Universal;
use Exception;
use FG\ASN1\Base128;
use FG\ASN1\OID;
use FG\ASN1\ASNObject;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Exception\ParserException;
class ObjectIdentifier extends ASNObject implements Parsable
{
protected $subIdentifiers;
protected $value;
public function __construct($value)
{
$this->subIdentifiers = explode('.', $value);
$nrOfSubIdentifiers = count($this->subIdentifiers);
for ($i = 0; $i < $nrOfSubIdentifiers; $i++) {
if (is_numeric($this->subIdentifiers[$i])) {
// enforce the integer type
$this->subIdentifiers[$i] = intval($this->subIdentifiers[$i]);
} else {
throw new Exception("[{$value}] is no valid object identifier (sub identifier ".($i + 1).' is not numeric)!');
}
}
// Merge the first to arcs of the OID registration tree (per ASN definition!)
if ($nrOfSubIdentifiers >= 2) {
$this->subIdentifiers[1] = ($this->subIdentifiers[0] * 40) + $this->subIdentifiers[1];
unset($this->subIdentifiers[0]);
}
$this->value = $value;
}
public function getContent()
{
return $this->value;
}
public function getType()
{
return Identifier::OBJECT_IDENTIFIER;
}
protected function calculateContentLength()
{
$length = 0;
foreach ($this->subIdentifiers as $subIdentifier) {
do {
$subIdentifier = $subIdentifier >> 7;
$length++;
} while ($subIdentifier > 0);
}
return $length;
}
protected function getEncodedValue()
{
$encodedValue = '';
foreach ($this->subIdentifiers as $subIdentifier) {
$encodedValue .= Base128::encode($subIdentifier);
}
return $encodedValue;
}
public function __toString()
{
return OID::getName($this->value);
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::OBJECT_IDENTIFIER, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex, 1);
$firstOctet = ord($binaryData[$offsetIndex++]);
$oidString = floor($firstOctet / 40).'.'.($firstOctet % 40);
$oidString .= '.'.self::parseOid($binaryData, $offsetIndex, $contentLength - 1);
$parsedObject = new self($oidString);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
/**
* Parses an object identifier except for the first octet, which is parsed
* differently. This way relative object identifiers can also be parsed
* using this.
*
* @param $binaryData
* @param $offsetIndex
* @param $octetsToRead
*
* @throws ParserException
*
* @return string
*/
protected static function parseOid(&$binaryData, &$offsetIndex, $octetsToRead)
{
$oid = '';
while ($octetsToRead > 0) {
$octets = '';
do {
if (0 === $octetsToRead) {
throw new ParserException('Malformed ASN.1 Object Identifier', $offsetIndex - 1);
}
$octetsToRead--;
$octet = $binaryData[$offsetIndex++];
$octets .= $octet;
} while (ord($octet) & 0x80);
$oid .= sprintf('%d.', Base128::decode($octets));
}
// Remove trailing '.'
return substr($oid, 0, -1) ?: '';
}
}

View file

@ -1,91 +0,0 @@
<?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\ASN1\Universal;
use Exception;
use FG\ASN1\ASNObject;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
class OctetString extends ASNObject implements Parsable
{
protected $value;
public function __construct($value)
{
if (is_string($value)) {
// remove gaps between hex digits
$value = preg_replace('/\s|0x/', '', $value);
} elseif (is_numeric($value)) {
$value = dechex($value);
} elseif ($value === null) {
return;
} else {
throw new Exception('OctetString: unrecognized input type!');
}
if (strlen($value) % 2 != 0) {
// transform values like 1F2 to 01F2
$value = '0'.$value;
}
$this->value = $value;
}
public function getType()
{
return Identifier::OCTETSTRING;
}
protected function calculateContentLength()
{
return strlen($this->value) / 2;
}
protected function getEncodedValue()
{
$value = $this->value;
$result = '';
//Actual content
while (strlen($value) >= 2) {
// get the hex value byte by byte from the string and and add it to binary result
$result .= chr(hexdec(substr($value, 0, 2)));
$value = substr($value, 2);
}
return $result;
}
public function getContent()
{
return strtoupper($this->value);
}
public function getBinaryContent()
{
return $this->getEncodedValue();
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::OCTETSTRING, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
$value = substr($binaryData, $offsetIndex, $contentLength);
$offsetIndex += $contentLength;
$parsedObject = new self(bin2hex($value));
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View file

@ -1,53 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class PrintableString extends AbstractString
{
/**
* Creates a new ASN.1 PrintableString.
*
* The ITU-T X.680 Table 8 permits the following characters:
* Latin capital letters A,B, ... Z
* Latin small letters a,b, ... z
* Digits 0,1, ... 9
* SPACE (space)
* APOSTROPHE '
* LEFT PARENTHESIS (
* RIGHT PARENTHESIS )
* PLUS SIGN +
* COMMA ,
* HYPHEN-MINUS -
* FULL STOP .
* SOLIDUS /
* COLON :
* EQUALS SIGN =
* QUESTION MARK ?
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowNumbers();
$this->allowAllLetters();
$this->allowSpaces();
$this->allowCharacters("'", '(', ')', '+', '-', '.', ',', '/', ':', '=', '?');
}
public function getType()
{
return Identifier::PRINTABLE_STRING;
}
}

View file

@ -1,57 +0,0 @@
<?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\ASN1\Universal;
use Exception;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Exception\ParserException;
class RelativeObjectIdentifier extends ObjectIdentifier implements Parsable
{
public function __construct($subIdentifiers)
{
$this->value = $subIdentifiers;
$this->subIdentifiers = explode('.', $subIdentifiers);
$nrOfSubIdentifiers = count($this->subIdentifiers);
for ($i = 0; $i < $nrOfSubIdentifiers; $i++) {
if (is_numeric($this->subIdentifiers[$i])) {
// enforce the integer type
$this->subIdentifiers[$i] = intval($this->subIdentifiers[$i]);
} else {
throw new Exception("[{$subIdentifiers}] is no valid object identifier (sub identifier ".($i + 1).' is not numeric)!');
}
}
}
public function getType()
{
return Identifier::RELATIVE_OID;
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::RELATIVE_OID, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex, 1);
try {
$oidString = self::parseOid($binaryData, $offsetIndex, $contentLength);
} catch (ParserException $e) {
throw new ParserException('Malformed ASN.1 Relative Object Identifier', $e->getOffset());
}
$parsedObject = new self($oidString);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View file

@ -1,23 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\Construct;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
class Sequence extends Construct implements Parsable
{
public function getType()
{
return Identifier::SEQUENCE;
}
}

View file

@ -1,21 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\Identifier;
class Set extends Sequence
{
public function getType()
{
return Identifier::SET;
}
}

View file

@ -1,36 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class T61String extends AbstractString
{
/**
* Creates a new ASN.1 T61 String.
* TODO The encodable characters of this type are not yet checked.
*
* @see http://en.wikipedia.org/wiki/ITU_T.61
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::T61_STRING;
}
}

View file

@ -1,77 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractTime;
use FG\ASN1\Parsable;
use FG\ASN1\Identifier;
use FG\ASN1\Exception\ParserException;
/**
* This ASN.1 universal type contains the calendar date and time.
*
* The precision is one minute or one second and optionally a
* local time differential from coordinated universal time.
*
* Decoding of this type will accept the Basic Encoding Rules (BER)
* The encoding will comply with the Distinguished Encoding Rules (DER).
*/
class UTCTime extends AbstractTime implements Parsable
{
public function getType()
{
return Identifier::UTC_TIME;
}
protected function calculateContentLength()
{
return 13; // Content is a string o the following format: YYMMDDhhmmssZ (13 octets)
}
protected function getEncodedValue()
{
return $this->value->format('ymdHis').'Z';
}
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
{
self::parseIdentifier($binaryData[$offsetIndex], Identifier::UTC_TIME, $offsetIndex++);
$contentLength = self::parseContentLength($binaryData, $offsetIndex, 11);
$format = 'ymdGi';
$dateTimeString = substr($binaryData, $offsetIndex, 10);
$offsetIndex += 10;
// extract optional seconds part
if ($binaryData[$offsetIndex] != 'Z'
&& $binaryData[$offsetIndex] != '+'
&& $binaryData[$offsetIndex] != '-') {
$dateTimeString .= substr($binaryData, $offsetIndex, 2);
$offsetIndex += 2;
$format .= 's';
}
$dateTime = \DateTime::createFromFormat($format, $dateTimeString, new \DateTimeZone('UTC'));
// extract time zone settings
if ($binaryData[$offsetIndex] == '+'
|| $binaryData[$offsetIndex] == '-') {
$dateTime = static::extractTimeZoneData($binaryData, $offsetIndex, $dateTime);
} elseif ($binaryData[$offsetIndex++] != 'Z') {
throw new ParserException('Invalid UTC String', $offsetIndex);
}
$parsedObject = new self($dateTime);
$parsedObject->setContentLength($contentLength);
return $parsedObject;
}
}

View file

@ -1,34 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class UTF8String extends AbstractString
{
/**
* Creates a new ASN.1 Universal String.
* TODO The encodable characters of this type are not yet checked.
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::UTF8_STRING;
}
}

View file

@ -1,36 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class UniversalString extends AbstractString
{
/**
* Creates a new ASN.1 Universal String.
* TODO The encodable characters of this type are not yet checked.
*
* @see http://en.wikipedia.org/wiki/Universal_Character_Set
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::UNIVERSAL_STRING;
}
}

View file

@ -1,34 +0,0 @@
<?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\ASN1\Universal;
use FG\ASN1\AbstractString;
use FG\ASN1\Identifier;
class VisibleString extends AbstractString
{
/**
* Creates a new ASN.1 Visible String.
* TODO The encodable characters of this type are not yet checked.
*
* @param string $string
*/
public function __construct($string)
{
$this->value = $string;
$this->allowAll();
}
public function getType()
{
return Identifier::VISIBLE_STRING;
}
}

View file

@ -1,59 +0,0 @@
<?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\ASN1;
class UnknownConstructedObject extends Construct
{
private $identifier;
private $contentLength;
/**
* @param string $binaryData
* @param int $offsetIndex
*
* @throws \FG\ASN1\Exception\ParserException
*/
public function __construct($binaryData, &$offsetIndex)
{
$this->identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex);
$this->contentLength = self::parseContentLength($binaryData, $offsetIndex);
$children = [];
$octetsToRead = $this->contentLength;
while ($octetsToRead > 0) {
$newChild = ASNObject::fromBinary($binaryData, $offsetIndex);
$octetsToRead -= $newChild->getObjectLength();
$children[] = $newChild;
}
parent::__construct(...$children);
}
public function getType()
{
return ord($this->identifier);
}
public function getIdentifier()
{
return $this->identifier;
}
protected function calculateContentLength()
{
return $this->contentLength;
}
protected function getEncodedValue()
{
return '';
}
}

View file

@ -1,59 +0,0 @@
<?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\ASN1;
class UnknownObject extends ASNObject
{
/** @var string */
private $value;
private $identifier;
/**
* @param string|int $identifier Either the first identifier octet as int or all identifier bytes as a string
* @param int $contentLength
*/
public function __construct($identifier, $contentLength)
{
if (is_int($identifier)) {
$identifier = chr($identifier);
}
$this->identifier = $identifier;
$this->value = "Unparsable Object ({$contentLength} bytes)";
$this->setContentLength($contentLength);
}
public function getContent()
{
return $this->value;
}
public function getType()
{
return ord($this->identifier[0]);
}
public function getIdentifier()
{
return $this->identifier;
}
protected function calculateContentLength()
{
return $this->getContentLength();
}
protected function getEncodedValue()
{
return '';
}
}