GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

OneAsymmetricKey::toDER()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Sop\CryptoTypes\Asymmetric;
6
7
use Sop\ASN1\Type\Constructed\Sequence;
8
use Sop\ASN1\Type\Primitive\Integer;
9
use Sop\ASN1\Type\Primitive\OctetString;
10
use Sop\ASN1\Type\UnspecifiedType;
11
use Sop\CryptoEncoding\PEM;
12
use Sop\CryptoTypes\AlgorithmIdentifier\AlgorithmIdentifier;
13
use Sop\CryptoTypes\AlgorithmIdentifier\Asymmetric\ECPublicKeyAlgorithmIdentifier;
14
use Sop\CryptoTypes\AlgorithmIdentifier\Feature\AlgorithmIdentifierType;
15
16
/**
17
 * Implements PKCS #8 PrivateKeyInfo / OneAsymmetricKey ASN.1 type.
18
 *
19
 * @see https://tools.ietf.org/html/rfc5208#section-5
20
 * @see https://tools.ietf.org/html/rfc5958#section-2
21
 */
22
class OneAsymmetricKey
23
{
24
    /**
25
     * Version number for PrivateKeyInfo.
26
     *
27
     * @var int
28
     */
29
    const VERSION_1 = 0;
30
31
    /**
32
     * Version number for OneAsymmetricKey.
33
     *
34
     * @var int
35
     */
36
    const VERSION_2 = 1;
37
38
    /**
39
     * Version number.
40
     *
41
     * @var int
42
     */
43
    protected $_version;
44
45
    /**
46
     * Algorithm identifier.
47
     *
48
     * @var AlgorithmIdentifierType
49
     */
50
    protected $_algo;
51
52
    /**
53
     * Private key data.
54
     *
55
     * @var string
56
     */
57
    protected $_privateKeyData;
58
59
    /**
60
     * Constructor.
61
     *
62
     * @param AlgorithmIdentifierType $algo Algorithm
63
     * @param string                  $key  Private key data
64
     */
65 15
    public function __construct(AlgorithmIdentifierType $algo, string $key)
66
    {
67 15
        $this->_version = self::VERSION_1;
68 15
        $this->_algo = $algo;
69 15
        $this->_privateKeyData = $key;
70 15
    }
71
72
    /**
73
     * Initialize from ASN.1.
74
     *
75
     * @param Sequence $seq
76
     *
77
     * @throws \UnexpectedValueException
78
     *
79
     * @return self
80
     */
81 11
    public static function fromASN1(Sequence $seq): self
82
    {
83 11
        $version = $seq->at(0)->asInteger()->intNumber();
84 11
        if (!in_array($version, [self::VERSION_1, self::VERSION_2])) {
85 1
            throw new \UnexpectedValueException(
86 1
                "Version {$version} not supported.");
87
        }
88 10
        $algo = AlgorithmIdentifier::fromASN1($seq->at(1)->asSequence());
89 10
        $key = $seq->at(2)->asOctetString()->string();
90
        // @todo parse attributes and public key
91 10
        $obj = new static($algo, $key);
92 10
        $obj->_version = $version;
93 10
        return $obj;
94
    }
95
96
    /**
97
     * Initialize from DER data.
98
     *
99
     * @param string $data
100
     *
101
     * @return self
102
     */
103 9
    public static function fromDER(string $data): self
104
    {
105 9
        return self::fromASN1(UnspecifiedType::fromDER($data)->asSequence());
106
    }
107
108
    /**
109
     * Initialize from a PrivateKey.
110
     *
111
     * @param PrivateKey $private_key
112
     *
113
     * @return self
114
     */
115 4
    public static function fromPrivateKey(PrivateKey $private_key): self
116
    {
117 4
        return new static($private_key->algorithmIdentifier(), $private_key->toDER());
118
    }
119
120
    /**
121
     * Initialize from PEM.
122
     *
123
     * @param PEM $pem
124
     *
125
     * @throws \UnexpectedValueException If PEM type is not supported
126
     *
127
     * @return self
128
     */
129 4
    public static function fromPEM(PEM $pem): self
130
    {
131 4
        switch ($pem->type()) {
132 4
            case PEM::TYPE_PRIVATE_KEY:
133 1
                return self::fromDER($pem->data());
134 3
            case PEM::TYPE_RSA_PRIVATE_KEY:
135 1
                return self::fromPrivateKey(
136 1
                    RSA\RSAPrivateKey::fromDER($pem->data()));
137 2
            case PEM::TYPE_EC_PRIVATE_KEY:
138 1
                return self::fromPrivateKey(
139 1
                    EC\ECPrivateKey::fromDER($pem->data()));
140
        }
141 1
        throw new \UnexpectedValueException('Invalid PEM type.');
142
    }
143
144
    /**
145
     * Get algorithm identifier.
146
     *
147
     * @return AlgorithmIdentifierType
148
     */
149 13
    public function algorithmIdentifier(): AlgorithmIdentifierType
150
    {
151 13
        return $this->_algo;
152
    }
153
154
    /**
155
     * Get private key data.
156
     *
157
     * @return string
158
     */
159 1
    public function privateKeyData(): string
160
    {
161 1
        return $this->_privateKeyData;
162
    }
163
164
    /**
165
     * Get private key.
166
     *
167
     * @throws \RuntimeException
168
     *
169
     * @return PrivateKey
170
     */
171 12
    public function privateKey(): PrivateKey
172
    {
173 12
        $algo = $this->algorithmIdentifier();
174 12
        switch ($algo->oid()) {
175
            // RSA
176
            case AlgorithmIdentifier::OID_RSA_ENCRYPTION:
177 5
                return RSA\RSAPrivateKey::fromDER($this->_privateKeyData);
178
            // elliptic curve
179
            case AlgorithmIdentifier::OID_EC_PUBLIC_KEY:
180 6
                $pk = EC\ECPrivateKey::fromDER($this->_privateKeyData);
181
                // NOTE: OpenSSL strips named curve from ECPrivateKey structure
182
                // when serializing into PrivateKeyInfo. However RFC 5915 dictates
183
                // that parameters (NamedCurve) must always be included.
184
                // If private key doesn't encode named curve, assign from parameters.
185 6
                if (!$pk->hasNamedCurve()) {
186 6
                    if (!$algo instanceof ECPublicKeyAlgorithmIdentifier) {
187 1
                        throw new \UnexpectedValueException('Not an EC algorithm.');
188
                    }
189 5
                    $pk = $pk->withNamedCurve($algo->namedCurve());
190
                }
191 5
                return $pk;
192
        }
193 1
        throw new \RuntimeException(
194 1
            'Private key ' . $algo->name() . ' not supported.');
195
    }
196
197
    /**
198
     * Get public key info corresponding to the private key.
199
     *
200
     * @return PublicKeyInfo
201
     */
202 2
    public function publicKeyInfo(): PublicKeyInfo
203
    {
204 2
        return $this->privateKey()->publicKey()->publicKeyInfo();
205
    }
206
207
    /**
208
     * Generate ASN.1 structure.
209
     *
210
     * @return Sequence
211
     */
212 3
    public function toASN1(): Sequence
213
    {
214 3
        $elements = [new Integer($this->_version), $this->_algo->toASN1(),
215 3
            new OctetString($this->_privateKeyData), ];
216
        // @todo decode attributes and public key
217 3
        return new Sequence(...$elements);
218
    }
219
220
    /**
221
     * Generate DER encoding.
222
     *
223
     * @return string
224
     */
225 1
    public function toDER(): string
226
    {
227 1
        return $this->toASN1()->toDER();
228
    }
229
230
    /**
231
     * Generate PEM.
232
     *
233
     * @return PEM
234
     */
235 1
    public function toPEM(): PEM
236
    {
237 1
        return new PEM(PEM::TYPE_PRIVATE_KEY, $this->toDER());
238
    }
239
}
240