|
1 |
| -import { decode as decodeBase64URL, encodeBase64, decodeBase64 } from '../runtime/base64url.js' |
2 |
| -import { fromSPKI as importPublic } from '../runtime/asn1.js' |
3 |
| -import { fromPKCS8 as importPrivate } from '../runtime/asn1.js' |
| 1 | +import { decode as decodeBase64URL } from '../runtime/base64url.js' |
| 2 | +import { fromSPKI, fromPKCS8, fromX509 } from '../runtime/asn1.js' |
4 | 3 | import asKeyObject from '../runtime/jwk_to_key.js'
|
5 | 4 |
|
6 | 5 | import { JOSENotSupported } from '../util/errors.js'
|
7 |
| -import formatPEM from '../lib/format_pem.js' |
8 | 6 | import isObject from '../lib/is_object.js'
|
9 | 7 | import type { JWK, KeyLike } from '../types.d'
|
10 | 8 |
|
11 |
| -function getElement(seq: Uint8Array) { |
12 |
| - let result = [] |
13 |
| - let next = 0 |
14 |
| - |
15 |
| - while (next < seq.length) { |
16 |
| - let nextPart = parseElement(seq.subarray(next)) |
17 |
| - result.push(nextPart) |
18 |
| - next += nextPart.byteLength |
19 |
| - } |
20 |
| - return result |
21 |
| -} |
22 |
| - |
23 |
| -function parseElement(bytes: Uint8Array) { |
24 |
| - let position = 0 |
25 |
| - |
26 |
| - // tag |
27 |
| - let tag = bytes[0] & 0x1f |
28 |
| - position++ |
29 |
| - if (tag === 0x1f) { |
30 |
| - tag = 0 |
31 |
| - while (bytes[position] >= 0x80) { |
32 |
| - tag = tag * 128 + bytes[position] - 0x80 |
33 |
| - position++ |
34 |
| - } |
35 |
| - tag = tag * 128 + bytes[position] - 0x80 |
36 |
| - position++ |
37 |
| - } |
38 |
| - |
39 |
| - // length |
40 |
| - let length = 0 |
41 |
| - if (bytes[position] < 0x80) { |
42 |
| - length = bytes[position] |
43 |
| - position++ |
44 |
| - } else if (length === 0x80) { |
45 |
| - length = 0 |
46 |
| - |
47 |
| - while (bytes[position + length] !== 0 || bytes[position + length + 1] !== 0) { |
48 |
| - if (length > bytes.byteLength) { |
49 |
| - throw new TypeError('invalid indefinite form length') |
50 |
| - } |
51 |
| - length++ |
52 |
| - } |
53 |
| - |
54 |
| - const byteLength = position + length + 2 |
55 |
| - return { |
56 |
| - byteLength, |
57 |
| - contents: bytes.subarray(position, position + length), |
58 |
| - raw: bytes.subarray(0, byteLength), |
59 |
| - } |
60 |
| - } else { |
61 |
| - let numberOfDigits = bytes[position] & 0x7f |
62 |
| - position++ |
63 |
| - length = 0 |
64 |
| - for (let i = 0; i < numberOfDigits; i++) { |
65 |
| - length = length * 256 + bytes[position] |
66 |
| - position++ |
67 |
| - } |
68 |
| - } |
69 |
| - |
70 |
| - const byteLength = position + length |
71 |
| - return { |
72 |
| - byteLength, |
73 |
| - contents: bytes.subarray(position, byteLength), |
74 |
| - raw: bytes.subarray(0, byteLength), |
75 |
| - } |
76 |
| -} |
77 |
| - |
78 |
| -function spkiFromX509(buf: Uint8Array) { |
79 |
| - const tbsCertificate = getElement(getElement(parseElement(buf).contents)[0].contents) |
80 |
| - return encodeBase64(tbsCertificate[tbsCertificate[0].raw[0] === 0xa0 ? 6 : 5].raw) |
81 |
| -} |
82 |
| - |
83 |
| -function getSPKI(x509: string): string { |
84 |
| - const pem = x509.replace(/(?:-----(?:BEGIN|END) CERTIFICATE-----|\s)/g, '') |
85 |
| - const raw = decodeBase64(pem) |
86 |
| - return formatPEM(spkiFromX509(raw), 'PUBLIC KEY') |
87 |
| -} |
88 |
| - |
89 | 9 | export interface PEMImportOptions {
|
90 | 10 | /**
|
91 | 11 | * (Web Cryptography API specific) The value to use as
|
@@ -122,7 +42,7 @@ export async function importSPKI(
|
122 | 42 | if (typeof spki !== 'string' || spki.indexOf('-----BEGIN PUBLIC KEY-----') !== 0) {
|
123 | 43 | throw new TypeError('"spki" must be SPKI formatted string')
|
124 | 44 | }
|
125 |
| - return importPublic(spki, alg, options) |
| 45 | + return fromSPKI(spki, alg, options) |
126 | 46 | }
|
127 | 47 |
|
128 | 48 | /**
|
@@ -159,14 +79,7 @@ export async function importX509(
|
159 | 79 | if (typeof x509 !== 'string' || x509.indexOf('-----BEGIN CERTIFICATE-----') !== 0) {
|
160 | 80 | throw new TypeError('"x509" must be X.509 formatted string')
|
161 | 81 | }
|
162 |
| - let spki: string |
163 |
| - try { |
164 |
| - spki = getSPKI(x509) |
165 |
| - } catch (cause) { |
166 |
| - // @ts-ignore |
167 |
| - throw new TypeError('failed to parse the X.509 certificate', { cause }) |
168 |
| - } |
169 |
| - return importPublic(spki, alg, options) |
| 82 | + return fromX509(x509, alg, options) |
170 | 83 | }
|
171 | 84 |
|
172 | 85 | /**
|
@@ -197,7 +110,7 @@ export async function importPKCS8(
|
197 | 110 | if (typeof pkcs8 !== 'string' || pkcs8.indexOf('-----BEGIN PRIVATE KEY-----') !== 0) {
|
198 | 111 | throw new TypeError('"pkcs8" must be PKCS#8 formatted string')
|
199 | 112 | }
|
200 |
| - return importPrivate(pkcs8, alg, options) |
| 113 | + return fromPKCS8(pkcs8, alg, options) |
201 | 114 | }
|
202 | 115 |
|
203 | 116 | /**
|
|
0 commit comments