1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3    return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6exports.getPublicKey = void 0;
7const crypto_1 = __importDefault(require("crypto"));
8const error_1 = require("../error");
9const oid_1 = require("./oid");
10const ASN1_TAG_SEQUENCE = 0x30;
11const ANS1_TAG_BIT_STRING = 0x03;
12const NULL_BYTE = 0x00;
13const OID_EDDSA = '1.3.101.112';
14const OID_EC_PUBLIC_KEY = '1.2.840.10045.2.1';
15const OID_EC_CURVE_P256V1 = '1.2.840.10045.3.1.7';
16const PEM_HEADER = '-----BEGIN PUBLIC KEY-----';
17function getPublicKey(keyInfo) {
18    switch (keyInfo.keyType) {
19        case 'rsa':
20            return getRSAPublicKey(keyInfo);
21        case 'ed25519':
22            return getED25519PublicKey(keyInfo);
23        case 'ecdsa':
24        case 'ecdsa-sha2-nistp256':
25        case 'ecdsa-sha2-nistp384':
26            return getECDCSAPublicKey(keyInfo);
27        default:
28            throw new error_1.UnsupportedAlgorithmError(`Unsupported key type: ${keyInfo.keyType}`);
29    }
30}
31exports.getPublicKey = getPublicKey;
32function getRSAPublicKey(keyInfo) {
33    // Only support PEM-encoded RSA keys
34    if (!keyInfo.keyVal.startsWith(PEM_HEADER)) {
35        throw new error_1.CryptoError('Invalid key format');
36    }
37    const key = crypto_1.default.createPublicKey(keyInfo.keyVal);
38    switch (keyInfo.scheme) {
39        case 'rsassa-pss-sha256':
40            return {
41                key: key,
42                padding: crypto_1.default.constants.RSA_PKCS1_PSS_PADDING,
43            };
44        default:
45            throw new error_1.UnsupportedAlgorithmError(`Unsupported RSA scheme: ${keyInfo.scheme}`);
46    }
47}
48function getED25519PublicKey(keyInfo) {
49    let key;
50    // If key is already PEM-encoded we can just parse it
51    if (keyInfo.keyVal.startsWith(PEM_HEADER)) {
52        key = crypto_1.default.createPublicKey(keyInfo.keyVal);
53    }
54    else {
55        // If key is not PEM-encoded it had better be hex
56        if (!isHex(keyInfo.keyVal)) {
57            throw new error_1.CryptoError('Invalid key format');
58        }
59        key = crypto_1.default.createPublicKey({
60            key: ed25519.hexToDER(keyInfo.keyVal),
61            format: 'der',
62            type: 'spki',
63        });
64    }
65    return { key };
66}
67function getECDCSAPublicKey(keyInfo) {
68    let key;
69    // If key is already PEM-encoded we can just parse it
70    if (keyInfo.keyVal.startsWith(PEM_HEADER)) {
71        key = crypto_1.default.createPublicKey(keyInfo.keyVal);
72    }
73    else {
74        // If key is not PEM-encoded it had better be hex
75        if (!isHex(keyInfo.keyVal)) {
76            throw new error_1.CryptoError('Invalid key format');
77        }
78        key = crypto_1.default.createPublicKey({
79            key: ecdsa.hexToDER(keyInfo.keyVal),
80            format: 'der',
81            type: 'spki',
82        });
83    }
84    return { key };
85}
86const ed25519 = {
87    // Translates a hex key into a crypto KeyObject
88    // https://keygen.sh/blog/how-to-use-hexadecimal-ed25519-keys-in-node/
89    hexToDER: (hex) => {
90        const key = Buffer.from(hex, 'hex');
91        const oid = (0, oid_1.encodeOIDString)(OID_EDDSA);
92        // Create a byte sequence containing the OID and key
93        const elements = Buffer.concat([
94            Buffer.concat([
95                Buffer.from([ASN1_TAG_SEQUENCE]),
96                Buffer.from([oid.length]),
97                oid,
98            ]),
99            Buffer.concat([
100                Buffer.from([ANS1_TAG_BIT_STRING]),
101                Buffer.from([key.length + 1]),
102                Buffer.from([NULL_BYTE]),
103                key,
104            ]),
105        ]);
106        // Wrap up by creating a sequence of elements
107        const der = Buffer.concat([
108            Buffer.from([ASN1_TAG_SEQUENCE]),
109            Buffer.from([elements.length]),
110            elements,
111        ]);
112        return der;
113    },
114};
115const ecdsa = {
116    hexToDER: (hex) => {
117        const key = Buffer.from(hex, 'hex');
118        const bitString = Buffer.concat([
119            Buffer.from([ANS1_TAG_BIT_STRING]),
120            Buffer.from([key.length + 1]),
121            Buffer.from([NULL_BYTE]),
122            key,
123        ]);
124        const oids = Buffer.concat([
125            (0, oid_1.encodeOIDString)(OID_EC_PUBLIC_KEY),
126            (0, oid_1.encodeOIDString)(OID_EC_CURVE_P256V1),
127        ]);
128        const oidSequence = Buffer.concat([
129            Buffer.from([ASN1_TAG_SEQUENCE]),
130            Buffer.from([oids.length]),
131            oids,
132        ]);
133        // Wrap up by creating a sequence of elements
134        const der = Buffer.concat([
135            Buffer.from([ASN1_TAG_SEQUENCE]),
136            Buffer.from([oidSequence.length + bitString.length]),
137            oidSequence,
138            bitString,
139        ]);
140        return der;
141    },
142};
143const isHex = (key) => /^[0-9a-fA-F]+$/.test(key);
144