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