AttributeCertificate::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
nc 1
cc 1
nop 3
crap 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace X509\AttributeCertificate;
6
7
use ASN1\Type\UnspecifiedType;
8
use ASN1\Type\Constructed\Sequence;
9
use Sop\CryptoBridge\Crypto;
10
use Sop\CryptoEncoding\PEM;
11
use Sop\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
12
use Sop\CryptoTypes\AlgorithmIdentifier\Feature\SignatureAlgorithmIdentifier;
13
use Sop\CryptoTypes\Asymmetric\PublicKeyInfo;
14
use Sop\CryptoTypes\Signature\Signature;
15
use X509\Certificate\Certificate;
16
17
/**
18
 * Implements <i>AttributeCertificate</i> ASN.1 type.
19
 *
20
 * @link https://tools.ietf.org/html/rfc5755#section-4.1
21
 */
22
class AttributeCertificate
23
{
24
    /**
25
     * Attribute certificate info.
26
     *
27
     * @var AttributeCertificateInfo $_acinfo
28
     */
29
    protected $_acinfo;
30
    
31
    /**
32
     * Signature algorithm identifier.
33
     *
34
     * @var SignatureAlgorithmIdentifier $_signatureAlgorithm
35
     */
36
    protected $_signatureAlgorithm;
37
    
38
    /**
39
     * Signature value.
40
     *
41
     * @var Signature $_signatureValue
42
     */
43
    protected $_signatureValue;
44
    
45
    /**
46
     * Constructor.
47
     *
48
     * @param AttributeCertificateInfo $acinfo
49
     * @param SignatureAlgorithmIdentifier $algo
50
     * @param Signature $signature
51
     */
52 5
    public function __construct(AttributeCertificateInfo $acinfo,
53
        SignatureAlgorithmIdentifier $algo, Signature $signature)
54
    {
55 5
        $this->_acinfo = $acinfo;
56 5
        $this->_signatureAlgorithm = $algo;
57 5
        $this->_signatureValue = $signature;
58 5
    }
59
    
60
    /**
61
     * Initialize from ASN.1.
62
     *
63
     * @param Sequence $seq
64
     * @return self
65
     */
66 4
    public static function fromASN1(Sequence $seq): self
67
    {
68 4
        $acinfo = AttributeCertificateInfo::fromASN1($seq->at(0)->asSequence());
69 4
        $algo = AlgorithmIdentifier::fromASN1($seq->at(1)->asSequence());
70 4
        if (!$algo instanceof SignatureAlgorithmIdentifier) {
71 1
            throw new \UnexpectedValueException(
72 1
                "Unsupported signature algorithm " . $algo->oid() . ".");
73
        }
74 3
        $signature = Signature::fromSignatureData(
75 3
            $seq->at(2)
76 3
                ->asBitString()
77 3
                ->string(), $algo);
78 3
        return new self($acinfo, $algo, $signature);
79
    }
80
    
81
    /**
82
     * Initialize from DER data.
83
     *
84
     * @param string $data
85
     * @return self
86
     */
87 1
    public static function fromDER(string $data): self
88
    {
89 1
        return self::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
90
    }
91
    
92
    /**
93
     * Initialize from PEM.
94
     *
95
     * @param PEM $pem
96
     * @throws \UnexpectedValueException
97
     * @return self
98
     */
99 2
    public static function fromPEM(PEM $pem): self
100
    {
101 2
        if ($pem->type() !== PEM::TYPE_ATTRIBUTE_CERTIFICATE) {
102 1
            throw new \UnexpectedValueException("Invalid PEM type.");
103
        }
104 1
        return self::fromDER($pem->data());
105
    }
106
    
107
    /**
108
     * Get attribute certificate info.
109
     *
110
     * @return AttributeCertificateInfo
111
     */
112 7
    public function acinfo(): AttributeCertificateInfo
113
    {
114 7
        return $this->_acinfo;
115
    }
116
    
117
    /**
118
     * Get signature algorithm identifier.
119
     *
120
     * @return SignatureAlgorithmIdentifier
121
     */
122 2
    public function signatureAlgorithm(): SignatureAlgorithmIdentifier
123
    {
124 2
        return $this->_signatureAlgorithm;
125
    }
126
    
127
    /**
128
     * Get signature value.
129
     *
130
     * @return Signature
131
     */
132 1
    public function signatureValue(): Signature
133
    {
134 1
        return $this->_signatureValue;
135
    }
136
    
137
    /**
138
     * Get ASN.1 structure.
139
     *
140
     * @return Sequence
141
     */
142 4
    public function toASN1(): Sequence
143
    {
144 4
        return new Sequence($this->_acinfo->toASN1(),
145 4
            $this->_signatureAlgorithm->toASN1(),
146 4
            $this->_signatureValue->bitString());
147
    }
148
    
149
    /**
150
     * Get attribute certificate as a DER.
151
     *
152
     * @return string
153
     */
154 2
    public function toDER(): string
155
    {
156 2
        return $this->toASN1()->toDER();
157
    }
158
    
159
    /**
160
     * Get attribute certificate as a PEM.
161
     *
162
     * @return PEM
163
     */
164 2
    public function toPEM(): PEM
165
    {
166 2
        return new PEM(PEM::TYPE_ATTRIBUTE_CERTIFICATE, $this->toDER());
167
    }
168
    
169
    /**
170
     * Check whether attribute certificate is issued to the subject identified
171
     * by given public key certificate.
172
     *
173
     * @param Certificate $cert Certificate
174
     * @return boolean
175
     */
176 13
    public function isHeldBy(Certificate $cert): bool
177
    {
178 13
        if (!$this->_acinfo->holder()->identifiesPKC($cert)) {
179 2
            return false;
180
        }
181 11
        return true;
182
    }
183
    
184
    /**
185
     * Check whether attribute certificate is issued by given public key
186
     * certificate.
187
     *
188
     * @param Certificate $cert Certificate
189
     * @return boolean
190
     */
191 11
    public function isIssuedBy(Certificate $cert): bool
192
    {
193 11
        if (!$this->_acinfo->issuer()->identifiesPKC($cert)) {
194 2
            return false;
195
        }
196 9
        return true;
197
    }
198
    
199
    /**
200
     * Verify signature.
201
     *
202
     * @param PublicKeyInfo $pubkey_info Signer's public key
203
     * @param Crypto|null $crypto Crypto engine, use default if not set
204
     * @return bool
205
     */
206 10
    public function verify(PublicKeyInfo $pubkey_info, Crypto $crypto = null): bool
207
    {
208 10
        $crypto = $crypto ?: Crypto::getDefault();
209 10
        $data = $this->_acinfo->toASN1()->toDER();
210 10
        return $crypto->verify($data, $this->_signatureValue, $pubkey_info,
211 10
            $this->_signatureAlgorithm);
212
    }
213
    
214
    /**
215
     * Get attribute certificate as a PEM formatted string.
216
     *
217
     * @return string
218
     */
219 1
    public function __toString()
220
    {
221 1
        return $this->toPEM()->string();
222
    }
223
}
224