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.
Completed
Pull Request — master (#30)
by Alex
04:45
created

Certificate::convertDer2Pem()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
namespace Spatie\CertificateChain;
4
5
use phpseclib\File\ASN1;
6
use phpseclib\File\X509;
7
use Spatie\CertificateChain\Exceptions\CouldNotLoadCertificate;
8
use Spatie\CertificateChain\Exceptions\CouldNotCreateCertificate;
9
10
class Certificate
11
{
12
    /**
13
     * @param string
14
     */
15
    protected $contents;
16
17
    /**
18
     * @param string $inputFile
19
     *
20
     * @return static
21
     */
22
    public static function loadFromFile(string $inputFile)
23
    {
24
        $contents = @file_get_contents($inputFile);
25
26
        if ($contents === false) {
27
            throw CouldNotLoadCertificate::cannotGetContents($inputFile);
28
        }
29
30
        return new static($contents);
31
    }
32
33
    /**
34
     * @param string $url
35
     *
36
     * @return static
37
     */
38
    public static function loadFromUrl(string $url)
39
    {
40
        return static::loadFromFile($url);
41
    }
42
43
    public function __construct(string $contents)
44
    {
45
        // If we are missing the pem certificate header, try to convert it to a pem format first
46
        if (!empty($contents) && strpos($contents, '-----BEGIN CERTIFICATE-----') === false) {
47
            // Extract from either a PKCS#7 format or DER formatted contents
48
            $contents = self::convertPkcs72Pem($contents) ?? self::convertDer2Pem($contents);
49
        }
50
51
        $this->guardAgainstInvalidContents($contents);
52
53
        $this->contents = $contents;
54
    }
55
56
    /**
57
     * Get the URL of the parent certificate.
58
     */
59
    public function getParentCertificateUrl(): string
60
    {
61
        $x509 = new X509();
62
63
        $certProperties = $x509->loadX509($this->contents);
64
65
        if (empty($certProperties['tbsCertificate']['extensions'])) {
66
            return '';
67
        }
68
69
        foreach ($certProperties['tbsCertificate']['extensions'] as $extension) {
70
            if ($extension['extnId'] == 'id-pe-authorityInfoAccess') {
71
                foreach ($extension['extnValue'] as $extnValue) {
72
                    if ($extnValue['accessMethod'] == 'id-ad-caIssuers') {
73
                        return $extnValue['accessLocation']['uniformResourceIdentifier'];
74
                    }
75
                }
76
            }
77
        }
78
79
        return '';
80
    }
81
82
    public function fetchParentCertificate(): self
83
    {
84
        return static::loadFromUrl($this->getParentCertificateUrl());
85
    }
86
87
    public function hasParentInTrustChain(): bool
88
    {
89
        return ! $this->getParentCertificateUrl() == '';
90
    }
91
92
    public function getContents(): string
93
    {
94
        $x509 = new X509();
95
96
        return $x509->saveX509($x509->loadX509($this->contents)).PHP_EOL;
97
    }
98
99
    protected function guardAgainstInvalidContents(string $content)
100
    {
101
        if (! (new X509())->loadX509($content)) {
102
            throw CouldNotCreateCertificate::invalidContent($content);
103
        }
104
    }
105
106
    protected function convertPkcs72Pem(string $pkcs7)
107
    {
108
        $asn     = new ASN1();
109
        $decoded = $asn->decodeBER($pkcs7);
110
        $data    = $decoded[0]['content'] ?? [];
111
112
        // Make sure we are dealing with actual data
113
        if (empty($data)) {
114
            return null;
115
        }
116
117
        // Make sure this is an PKCS#7 signedData object
118
        if ($data[0]['type'] === ASN1::TYPE_OBJECT_IDENTIFIER && $data[0]['content'] === '1.2.840.113549.1.7.2') {
119
            // Loop over all the content in the signedData object
120
            foreach ($data[1]['content'] as $pkcs7SignedData) {
121
                // Find all sequences of data
122
                if ($pkcs7SignedData['type'] === ASN1::TYPE_SEQUENCE) {
123
                    // Extract the sequence identifier if possible
124
                    $identifier = $pkcs7SignedData['content'][2] ?? '';
125
126
                    // Make sure the sequence is a PKCS#7 data object we are dealing with
127
                    if ($identifier['type'] === ASN1::TYPE_SEQUENCE && $identifier['content'][0]['content'] === '1.2.840.113549.1.7.1') {
128
                        // Extract the certificate data
129
                        $certificate = $pkcs7SignedData['content'][3];
130
131
                        // Extract the raw certificate data from the PKCS#7 string
132
                        $rawCert = substr($pkcs7, $certificate['start'] + $certificate['headerlength'], $certificate['length'] - $certificate['headerlength']);
133
134
                        // Return the PEM encoded certificate
135
                        return $this->convertDer2Pem($rawCert);
136
                    }
137
                }
138
            }
139
        }
140
141
        return null;
142
    }
143
144
    protected function convertDer2Pem(string $der_data, $type = 'CERTIFICATE'): string
145
    {
146
        $pem = chunk_split(base64_encode($der_data), 64, "\n");
147
148
        return "-----BEGIN {$type}-----\n{$pem}-----END {$type}-----\n";
149
    }
150
}
151