Skip to content

Commit

Permalink
Use attribute container from x501
Browse files Browse the repository at this point in the history
  • Loading branch information
sop committed Jun 27, 2019
1 parent 0b237d0 commit cd265f1
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 321 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"php": ">=7.2",
"ext-gmp": "*",
"sop/asn1": "^4.0.0",
"sop/x501": "^0.6.0",
"sop/x501": "^0.6.1",
"sop/crypto-types": "^0.3.0",
"sop/crypto-bridge": "^0.3.1",
"sop/crypto-encoding": "^0.3.0"
Expand Down
81 changes: 10 additions & 71 deletions lib/X509/AttributeCertificate/Attributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,23 @@

namespace Sop\X509\AttributeCertificate;

use Sop\ASN1\Type\Constructed\Sequence;
use Sop\ASN1\Type\UnspecifiedType;
use Sop\X501\ASN1\Attribute;
use Sop\X501\ASN1\AttributeType;
use Sop\X501\ASN1\AttributeValue\AttributeValue;
use Sop\X501\ASN1\Collection\SequenceOfAttributes;
use Sop\X509\AttributeCertificate\Attribute\AccessIdentityAttributeValue;
use Sop\X509\AttributeCertificate\Attribute\AuthenticationInfoAttributeValue;
use Sop\X509\AttributeCertificate\Attribute\ChargingIdentityAttributeValue;
use Sop\X509\AttributeCertificate\Attribute\GroupAttributeValue;
use Sop\X509\AttributeCertificate\Attribute\RoleAttributeValue;
use Sop\X509\Feature\AttributeContainer;

/**
* Implements *Attributes* ASN.1 type as a *SEQUENCE OF Attribute*.
*
* Used in *AttributeCertificateInfo*.
* Implements *Attributes* ASN.1 type of *AttributeCertificateInfo*.
*
* @see https://tools.ietf.org/html/rfc5755#section-4.1
* @see https://tools.ietf.org/html/rfc5755#section-4.2.7
*/
class Attributes implements \Countable, \IteratorAggregate
class Attributes extends SequenceOfAttributes
{
use AttributeContainer;

/**
* Mapping from OID to attribute value class name.
*
Expand All @@ -43,58 +36,6 @@ class Attributes implements \Countable, \IteratorAggregate
AttributeType::OID_ROLE => RoleAttributeValue::class,
];

/**
* Constructor.
*
* @param Attribute ...$attribs
*/
public function __construct(Attribute ...$attribs)
{
$this->_attributes = $attribs;
}

/**
* Initialize from attribute values.
*
* @param AttributeValue ...$values
*
* @return self
*/
public static function fromAttributeValues(AttributeValue ...$values): self
{
$attribs = array_map(
function (AttributeValue $value) {
return $value->toAttribute();
}, $values);
return new self(...$attribs);
}

/**
* Initialize from ASN.1.
*
* @param Sequence $seq
*
* @return self
*/
public static function fromASN1(Sequence $seq): self
{
$attribs = array_map(
function (UnspecifiedType $el) {
return Attribute::fromASN1($el->asSequence());
}, $seq->elements());
// cast attributes
$attribs = array_map(
function (Attribute $attr) {
$oid = $attr->oid();
if (array_key_exists($oid, self::MAP_OID_TO_CLASS)) {
$cls = self::MAP_OID_TO_CLASS[$oid];
$attr = $attr->castValues($cls);
}
return $attr;
}, $attribs);
return new self(...$attribs);
}

/**
* Check whether 'Access Identity' attribute is present.
*
Expand Down Expand Up @@ -210,16 +151,14 @@ function (Attribute $attr) {
}

/**
* Generate ASN.1 structure.
*
* @return Sequence
* {@inheritdoc}
*/
public function toASN1(): Sequence
protected static function _castAttributeValues(Attribute $attribute): Attribute
{
$elements = array_map(
function (Attribute $attr) {
return $attr->toASN1();
}, array_values($this->_attributes));
return new Sequence(...$elements);
$oid = $attribute->oid();
if (isset(self::MAP_OID_TO_CLASS[$oid])) {
return $attribute->castValues(self::MAP_OID_TO_CLASS[$oid]);
}
return $attribute;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
namespace Sop\X509\Certificate\Extension;

use Sop\ASN1\Element;
use Sop\ASN1\Type\Constructed\Sequence;
use Sop\ASN1\Type\UnspecifiedType;
use Sop\X501\ASN1\Attribute;
use Sop\X509\Feature\AttributeContainer;
use Sop\X501\ASN1\Collection\SequenceOfAttributes;

/**
* Implements 'Subject Directory Attributes' certificate extension.
Expand All @@ -17,7 +16,12 @@
*/
class SubjectDirectoryAttributesExtension extends Extension implements \Countable, \IteratorAggregate
{
use AttributeContainer;
/**
* Attributes.
*
* @var SequenceOfAttributes
*/
private $_attributes;

/**
* Constructor.
Expand All @@ -28,23 +32,89 @@ class SubjectDirectoryAttributesExtension extends Extension implements \Countabl
public function __construct(bool $critical, Attribute ...$attribs)
{
parent::__construct(self::OID_SUBJECT_DIRECTORY_ATTRIBUTES, $critical);
$this->_attributes = $attribs;
$this->_attributes = new SequenceOfAttributes(...$attribs);
}

/**
* Check whether attribute is present.
*
* @param string $name OID or attribute name
*
* @return bool
*/
public function has(string $name): bool
{
return $this->_attributes->has($name);
}

/**
* Get first attribute by OID or attribute name.
*
* @param string $name OID or attribute name
*
* @throws \UnexpectedValueException if attribute is not present
*
* @return Attribute
*/
public function firstOf(string $name): Attribute
{
return $this->_attributes->firstOf($name);
}

/**
* Get all attributes of given name.
*
* @param string $name OID or attribute name
*
* @return Attribute[]
*/
public function allOf(string $name): array
{
return $this->_attributes->allOf($name);
}

/**
* Get all attributes.
*
* @return Attribute[]
*/
public function all(): array
{
return $this->_attributes->all();
}

/**
* Get number of attributes.
*
* @return int
*/
public function count(): int
{
return count($this->_attributes);
}

/**
* Get iterator for attributes.
*
* @return \ArrayIterator|Attribute[]
*/
public function getIterator(): \ArrayIterator
{
return $this->_attributes->getIterator();
}

/**
* {@inheritdoc}
*/
protected static function _fromDER(string $data, bool $critical): Extension
{
$attribs = array_map(
function (UnspecifiedType $el) {
return Attribute::fromASN1($el->asSequence());
}, UnspecifiedType::fromDER($data)->asSequence()->elements());
$attribs = SequenceOfAttributes::fromASN1(
UnspecifiedType::fromDER($data)->asSequence());
if (!count($attribs)) {
throw new \UnexpectedValueException(
'SubjectDirectoryAttributes must have at least one Attribute.');
}
return new self($critical, ...$attribs);
return new self($critical, ...$attribs->all());
}

/**
Expand All @@ -55,10 +125,6 @@ protected function _valueASN1(): Element
if (!count($this->_attributes)) {
throw new \LogicException('No attributes');
}
$elements = array_map(
function (Attribute $attr) {
return $attr->toASN1();
}, array_values($this->_attributes));
return new Sequence(...$elements);
return $this->_attributes->toASN1();
}
}
82 changes: 10 additions & 72 deletions lib/X509/CertificationRequest/Attributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,17 @@

namespace Sop\X509\CertificationRequest;

use Sop\ASN1\Type\Constructed\Set;
use Sop\ASN1\Type\UnspecifiedType;
use Sop\X501\ASN1\Attribute;
use Sop\X501\ASN1\AttributeValue\AttributeValue;
use Sop\X501\ASN1\Collection\SetOfAttributes;
use Sop\X509\CertificationRequest\Attribute\ExtensionRequestValue;
use Sop\X509\Feature\AttributeContainer;

/**
* Implements *Attributes* ASN.1 type as a *SET OF Attribute*.
*
* Used in *CertificationRequestInfo*.
* Implements *Attributes* ASN.1 type of *CertificationRequestInfo*.
*
* @see https://tools.ietf.org/html/rfc2986#section-4
*/
class Attributes implements \Countable, \IteratorAggregate
class Attributes extends SetOfAttributes
{
use AttributeContainer;

/**
* Mapping from OID to attribute value class name.
*
Expand All @@ -33,58 +26,6 @@ class Attributes implements \Countable, \IteratorAggregate
ExtensionRequestValue::OID => ExtensionRequestValue::class,
];

/**
* Constructor.
*
* @param Attribute ...$attribs Attribute objects
*/
public function __construct(Attribute ...$attribs)
{
$this->_attributes = $attribs;
}

/**
* Initialize from attribute values.
*
* @param AttributeValue ...$values
*
* @return self
*/
public static function fromAttributeValues(AttributeValue ...$values): Attributes
{
$attribs = array_map(
function (AttributeValue $value) {
return $value->toAttribute();
}, $values);
return new self(...$attribs);
}

/**
* Initialize from ASN.1.
*
* @param Set $set
*
* @return self
*/
public static function fromASN1(Set $set): Attributes
{
$attribs = array_map(
function (UnspecifiedType $el) {
return Attribute::fromASN1($el->asSequence());
}, $set->elements());
// cast attributes
$attribs = array_map(
function (Attribute $attr) {
$oid = $attr->oid();
if (array_key_exists($oid, self::MAP_OID_TO_CLASS)) {
$cls = self::MAP_OID_TO_CLASS[$oid];
return $attr->castValues($cls);
}
return $attr;
}, $attribs);
return new self(...$attribs);
}

/**
* Check whether extension request attribute is present.
*
Expand All @@ -111,17 +52,14 @@ public function extensionRequest(): ExtensionRequestValue
}

/**
* Generate ASN.1 structure.
*
* @return Set
* {@inheritdoc}
*/
public function toASN1(): Set
protected static function _castAttributeValues(Attribute $attribute): Attribute
{
$elements = array_map(
function (Attribute $attr) {
return $attr->toASN1();
}, array_values($this->_attributes));
$set = new Set(...$elements);
return $set->sortedSetOf();
$oid = $attribute->oid();
if (isset(self::MAP_OID_TO_CLASS[$oid])) {
return $attribute->castValues(self::MAP_OID_TO_CLASS[$oid]);
}
return $attribute;
}
}
Loading

0 comments on commit cd265f1

Please sign in to comment.