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.

CertificationPathBuilder   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 136
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 17
eloc 40
dl 0
loc 136
ccs 42
cts 42
cp 1
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A shortestPathToTarget() 0 12 3
A _findIssuers() 0 20 5
A __construct() 0 3 1
A allPathsToTarget() 0 9 1
B _resolvePathsToTarget() 0 30 7
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Sop\X509\CertificationPath\PathBuilding;
6
7
use Sop\X509\Certificate\Certificate;
8
use Sop\X509\Certificate\CertificateBundle;
9
use Sop\X509\CertificationPath\CertificationPath;
10
use Sop\X509\CertificationPath\Exception\PathBuildingException;
11
12
/**
13
 * Class for resolving certification paths.
14
 *
15
 * @see https://tools.ietf.org/html/rfc4158
16
 */
17
class CertificationPathBuilder
18
{
19
    /**
20
     * Trust anchors.
21
     *
22
     * @var CertificateBundle
23
     */
24
    protected $_trustList;
25
26
    /**
27
     * Constructor.
28
     *
29
     * @param CertificateBundle $trust_list List of trust anchors
30
     */
31 9
    public function __construct(CertificateBundle $trust_list)
32
    {
33 9
        $this->_trustList = $trust_list;
34 9
    }
35
36
    /**
37
     * Get all certification paths to given target certificate from
38
     * any trust anchor.
39
     *
40
     * @param Certificate            $target       Target certificate
41
     * @param null|CertificateBundle $intermediate Optional intermediate certificates
42
     *
43
     * @return CertificationPath[]
44
     */
45 9
    public function allPathsToTarget(Certificate $target,
46
        ?CertificateBundle $intermediate = null): array
47
    {
48 9
        $paths = $this->_resolvePathsToTarget($target, $intermediate);
49
        // map paths to CertificationPath objects
50 9
        return array_map(
51
            function ($certs) {
52 8
                return new CertificationPath(...$certs);
53 9
            }, $paths);
54
    }
55
56
    /**
57
     * Get shortest path to given target certificate from any trust anchor.
58
     *
59
     * @param Certificate            $target       Target certificate
60
     * @param null|CertificateBundle $intermediate Optional intermediate certificates
61
     *
62
     * @throws PathBuildingException
63
     *
64
     * @return CertificationPath
65
     */
66 8
    public function shortestPathToTarget(Certificate $target,
67
        ?CertificateBundle $intermediate = null): CertificationPath
68
    {
69 8
        $paths = $this->allPathsToTarget($target, $intermediate);
70 8
        if (!count($paths)) {
71 1
            throw new PathBuildingException('No certification paths.');
72
        }
73 7
        usort($paths,
74
            function ($a, $b) {
75 1
                return count($a) < count($b) ? -1 : 1;
76 7
            });
77 7
        return reset($paths);
78
    }
79
80
    /**
81
     * Find all issuers of the target certificate from a given bundle.
82
     *
83
     * @param Certificate       $target Target certificate
84
     * @param CertificateBundle $bundle Certificates to search
85
     *
86
     * @return Certificate[]
87
     */
88 9
    protected function _findIssuers(Certificate $target,
89
        CertificateBundle $bundle): array
90
    {
91 9
        $issuers = [];
92 9
        $issuer_name = $target->tbsCertificate()->issuer();
93 9
        $extensions = $target->tbsCertificate()->extensions();
94
        // find by authority key identifier
95 9
        if ($extensions->hasAuthorityKeyIdentifier()) {
96 9
            $ext = $extensions->authorityKeyIdentifier();
97 9
            if ($ext->hasKeyIdentifier()) {
98 9
                foreach ($bundle->allBySubjectKeyIdentifier(
99 9
                    $ext->keyIdentifier()) as $issuer) {
100
                    // check that issuer name matches
101 8
                    if ($issuer->tbsCertificate()->subject()->equals($issuer_name)) {
102 8
                        $issuers[] = $issuer;
103
                    }
104
                }
105
            }
106
        }
107 9
        return $issuers;
108
    }
109
110
    /**
111
     * Resolve all possible certification paths from any trust anchor to
112
     * the target certificate, using optional intermediate certificates.
113
     *
114
     * Helper method for allPathsToTarget to be called recursively.
115
     *
116
     * @todo Implement loop detection
117
     *
118
     * @param Certificate            $target
119
     * @param null|CertificateBundle $intermediate
120
     *
121
     * @return array[] Array of arrays containing path certificates
122
     */
123 9
    private function _resolvePathsToTarget(Certificate $target,
124
        ?CertificateBundle $intermediate = null): array
125
    {
126
        // array of possible paths
127 9
        $paths = [];
128
        // signed by certificate in the trust list
129 9
        foreach ($this->_findIssuers($target, $this->_trustList) as $issuer) {
130
            // if target is self-signed, path consists of only
131
            // the target certificate
132 8
            if ($target->equals($issuer)) {
133 1
                $paths[] = [$target];
134
            } else {
135 8
                $paths[] = [$issuer, $target];
136
            }
137
        }
138 9
        if (isset($intermediate)) {
139
            // signed by intermediate certificate
140 6
            foreach ($this->_findIssuers($target, $intermediate) as $issuer) {
141
                // intermediate certificate must not be self-signed
142 5
                if ($issuer->isSelfIssued()) {
143 2
                    continue;
144
                }
145
                // resolve paths to issuer
146 5
                $subpaths = $this->_resolvePathsToTarget($issuer, $intermediate);
147 5
                foreach ($subpaths as $path) {
148 5
                    $paths[] = array_merge($path, [$target]);
149
                }
150
            }
151
        }
152 9
        return $paths;
153
    }
154
}
155