Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
 
4
namespace lbuchs\WebAuthn\Attestation\Format;
5
use lbuchs\WebAuthn\WebAuthnException;
6
use lbuchs\WebAuthn\Attestation\AuthenticatorData;
7
 
8
 
9
abstract class FormatBase {
10
    protected $_attestationObject = null;
11
    protected $_authenticatorData = null;
12
    protected $_x5c_chain = array();
13
    protected $_x5c_tempFile = null;
14
 
15
    /**
16
     *
17
     * @param Array $AttestionObject
18
     * @param AuthenticatorData $authenticatorData
19
     */
20
    public function __construct($AttestionObject, AuthenticatorData $authenticatorData) {
21
        $this->_attestationObject = $AttestionObject;
22
        $this->_authenticatorData = $authenticatorData;
23
    }
24
 
25
    /**
26
     *
27
     */
28
    public function __destruct() {
29
        // delete X.509 chain certificate file after use
30
        if ($this->_x5c_tempFile && \is_file($this->_x5c_tempFile)) {
31
            \unlink($this->_x5c_tempFile);
32
        }
33
    }
34
 
35
    /**
36
     * returns the certificate chain in PEM format
37
     * @return string|null
38
     */
39
    public function getCertificateChain() {
40
        if ($this->_x5c_tempFile && \is_file($this->_x5c_tempFile)) {
41
            return \file_get_contents($this->_x5c_tempFile);
42
        }
43
        return null;
44
    }
45
 
46
    /**
47
     * returns the key X.509 certificate in PEM format
48
     * @return string
49
     */
50
    public function getCertificatePem() {
51
        // need to be overwritten
52
        return null;
53
    }
54
 
55
    /**
56
     * checks validity of the signature
57
     * @param string $clientDataHash
58
     * @return bool
59
     * @throws WebAuthnException
60
     */
61
    public function validateAttestation($clientDataHash) {
62
        // need to be overwritten
63
        return false;
64
    }
65
 
66
    /**
67
     * validates the certificate against root certificates
68
     * @param array $rootCas
69
     * @return boolean
70
     * @throws WebAuthnException
71
     */
72
    public function validateRootCertificate($rootCas) {
73
        // need to be overwritten
74
        return false;
75
    }
76
 
77
 
78
    /**
79
     * create a PEM encoded certificate with X.509 binary data
80
     * @param string $x5c
81
     * @return string
82
     */
83
    protected function _createCertificatePem($x5c) {
84
        $pem = '-----BEGIN CERTIFICATE-----' . "\n";
85
        $pem .= \chunk_split(\base64_encode($x5c), 64, "\n");
86
        $pem .= '-----END CERTIFICATE-----' . "\n";
87
        return $pem;
88
    }
89
 
90
    /**
91
     * creates a PEM encoded chain file
92
     * @return type
93
     */
94
    protected function _createX5cChainFile() {
95
        $content = '';
96
        if (\is_array($this->_x5c_chain) && \count($this->_x5c_chain) > 0) {
97
            foreach ($this->_x5c_chain as $x5c) {
98
                $certInfo = \openssl_x509_parse($this->_createCertificatePem($x5c));
99
 
100
                // check if certificate is self signed
101
                if (\is_array($certInfo) && \is_array($certInfo['issuer']) && \is_array($certInfo['subject'])) {
102
                    $selfSigned = false;
103
 
104
                    $subjectKeyIdentifier = $certInfo['extensions']['subjectKeyIdentifier'] ?? null;
105
                    $authorityKeyIdentifier = $certInfo['extensions']['authorityKeyIdentifier'] ?? null;
106
 
107
                    if ($authorityKeyIdentifier && substr($authorityKeyIdentifier, 0, 6) === 'keyid:') {
108
                        $authorityKeyIdentifier = substr($authorityKeyIdentifier, 6);
109
                    }
110
                    if ($subjectKeyIdentifier && substr($subjectKeyIdentifier, 0, 6) === 'keyid:') {
111
                        $subjectKeyIdentifier = substr($subjectKeyIdentifier, 6);
112
                    }
113
 
114
                    if (($subjectKeyIdentifier && !$authorityKeyIdentifier) || ($authorityKeyIdentifier && $authorityKeyIdentifier === $subjectKeyIdentifier)) {
115
                        $selfSigned = true;
116
                    }
117
 
118
                    if (!$selfSigned) {
119
                        $content .= "\n" . $this->_createCertificatePem($x5c) . "\n";
120
                    }
121
                }
122
            }
123
        }
124
 
125
        if ($content) {
126
            $this->_x5c_tempFile = \tempnam(\sys_get_temp_dir(), 'x5c_');
127
            if (\file_put_contents($this->_x5c_tempFile, $content) !== false) {
128
                return $this->_x5c_tempFile;
129
            }
130
        }
131
 
132
        return null;
133
    }
134
 
135
 
136
    /**
137
     * returns the name and openssl key for provided cose number.
138
     * @param int $coseNumber
139
     * @return \stdClass|null
140
     */
141
    protected function _getCoseAlgorithm($coseNumber) {
142
        // https://www.iana.org/assignments/cose/cose.xhtml#algorithms
143
        $coseAlgorithms = array(
144
            array(
145
                'hash' => 'SHA1',
146
                'openssl' => OPENSSL_ALGO_SHA1,
147
                'cose' => array(
148
                    -65535  // RS1
149
                )),
150
 
151
            array(
152
                'hash' => 'SHA256',
153
                'openssl' => OPENSSL_ALGO_SHA256,
154
                'cose' => array(
155
                    -257, // RS256
156
                    -37,  // PS256
157
                    -7,   // ES256
158
                    5     // HMAC256
159
                )),
160
 
161
            array(
162
                'hash' => 'SHA384',
163
                'openssl' => OPENSSL_ALGO_SHA384,
164
                'cose' => array(
165
                    -258, // RS384
166
                    -38,  // PS384
167
                    -35,  // ES384
168
                    6     // HMAC384
169
                )),
170
 
171
            array(
172
                'hash' => 'SHA512',
173
                'openssl' => OPENSSL_ALGO_SHA512,
174
                'cose' => array(
175
                    -259, // RS512
176
                    -39,  // PS512
177
                    -36,  // ES512
178
                    7     // HMAC512
179
                ))
180
        );
181
 
182
        foreach ($coseAlgorithms as $coseAlgorithm) {
183
            if (\in_array($coseNumber, $coseAlgorithm['cose'], true)) {
184
                $return = new \stdClass();
185
                $return->hash = $coseAlgorithm['hash'];
186
                $return->openssl = $coseAlgorithm['openssl'];
187
                return $return;
188
            }
189
        }
190
 
191
        return null;
192
    }
193
}