* SignerInfo ::= SEQUENCE { * version CMSVersion, * sid SignerIdentifier, * digestAlgorithm DigestAlgorithmIdentifier, * signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL, * signatureAlgorithm SignatureAlgorithmIdentifier, * signature SignatureValue, * unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL * } * * * @package asn1 * @subpackage cms * * @see http://tools.ietf.org/html/rfc3852#section-5.3 RFC 3852 */ class CMSSignerInfo { private $version; private $sid; private $digestAlgorithm; private $signedAttrs; private $signatureAlgorithm; private $signature; private $unsignedAttrs; /** * Constructs a new instance of CMSSignerInfo. */ public function __construct() { } /** * Decodes the given ASN1Sequence as CMSSignerInfo. * * @throws GTException * @param ASN1Sequence $object CMSSignerInfo encoded as ASN1Sequence * @return void */ public function decode($object) { if (!$object instanceof ASN1Sequence) { throw new GTException("Expecting an ASN1Sequence"); } $size = $object->getObjectCount(); if ($size < 5 || $size > 7) { throw new GTException("Invalid sequence size: {$size}"); } $version = $object->getObjectAt(0); if (!$version instanceof ASN1Integer) { throw new GTException("Expecting an ASN1Integer for version"); } $this->version = (int) $version->getValue(); if ($this->version != 1) { throw new GTException("Invalid version: {$this->version}"); } $sid = new CMSSignerIdentifier(); $sid->decode($object->getObjectAt(1)); $this->sid = $sid; $digestAlgorithm = new X509AlgorithmIdentifier(); $digestAlgorithm->decode($object->getObjectAt(2)); $this->digestAlgorithm = $digestAlgorithm; for ($i = 3; $i < $object->getObjectCount(); $i++) { $item = $object->getObjectAt($i); if ($item instanceof ASN1Tag) { switch ($item->getTagValue()) { case 0: $this->signedAttrs = array(); $items = $item->getObjectAs(ASN1_TAG_SET); foreach ($items->getObjects() as $a) { $attribute = new CMSAttribute(); $attribute->decode($a); array_push($this->signedAttrs, $attribute); } break; case 1: $this->unsignedAttrs = array(); $items = $item->getObjectAs(ASN1_TAG_SET); foreach ($items->getObjects() as $a) { $attribute = new CMSAttribute(); $attribute->decode($a); array_push($this->unsignedAttrs, $attribute); } break; default: throw new GTException("Unsupported TAG value: " . $item->getTagValue()); } } else if ($item instanceof ASN1Sequence) { // signature algorithm $signatureAlgorithm = new X509AlgorithmIdentifier(); $signatureAlgorithm->decode($item); $this->signatureAlgorithm = $signatureAlgorithm; } else if ($item instanceof ASN1OctetString) { // signature $this->signature = $item->getValue(); } else { throw new GTException("Unexpected ASN.1 TYPE: " . get_class($item)); } } if ($this->signature === null) { throw new GTException("Signature missing"); } if ($this->signatureAlgorithm === null) { throw new GTException("Signature algorithm missing"); } } /** * Encodes this CMSSignerInfo using DER. * * @return array byte array that contains the DER encoding of this CMSSignerInfo */ public function encodeDER() { $sequence = new ASN1Sequence(); $sequence->add(new ASN1Integer((int) $this->version)); $sequence->add($this->sid); $sequence->add($this->digestAlgorithm); if (!empty($this->signedAttrs)) { $signed = new ASN1Set(); foreach ($this->signedAttrs as $attr) { $signed->add($attr); } $tag = new ASN1Tag(); $tag->setExplicit(false); $tag->setTagType(ASN1_TAG_CONSTRUCTED); $tag->setTagClass(ASN1_TAG_CONTEXT); $tag->setTagValue(0); $tag->setObject($signed); $sequence->add($tag); } $sequence->add($this->signatureAlgorithm); $sequence->add(new ASN1OctetString($this->signature)); if (!empty($this->unsignedAttrs)) { $unsigned = new ASN1Set(); foreach ($this->unsignedAttrs as $attr) { $unsigned->add($attr); } $tag = new ASN1Tag(); $tag->setExplicit(false); $tag->setTagType(ASN1_TAG_CONSTRUCTED); $tag->setTagClass(ASN1_TAG_CONTEXT); $tag->setTagValue(1); $tag->setObject($unsigned); $sequence->add($tag); } return $sequence->encodeDER(); } /** * Gets the sid. * * @return CMSSignerIdentifier sid */ public function getSid() { return $this->sid; } /** * Gets the signature. * * @return array byte array containing the signature */ public function getSignature() { return $this->signature; } /** * Sets the signature. * * @param $signature byte array containing the signature * @return void */ public function setSignature($signature) { $this->signature = $signature; } /** * Gets the signature algorithm. * * @return X509AlgorithmIdentifier signature algorithm */ public function getSignatureAlgorithm() { return $this->signatureAlgorithm; } /** * Gets the digest algorithm. * * @return X509AlgorithmIdentifier digest algorithm */ public function getDigestAlgorithm() { return $this->digestAlgorithm; } /** * Gets the signet attributes. * * @return array array containing CMSAttribute instances */ public function getSignedAttrs() { return $this->signedAttrs; } /** * Gets the unsigned attributes. * * @return array array containing CMSAttribute instances */ public function getUnsignedAttrs() { return $this->unsignedAttrs; } } ?>