( type: SignatureType, rawPublicKey: Uint8Array )
| 138 | } |
| 139 | |
| 140 | export function parseRawPublicKey( |
| 141 | type: SignatureType, |
| 142 | rawPublicKey: Uint8Array |
| 143 | ): KeyObject { |
| 144 | if (type === SignatureType.Ed25519) { |
| 145 | const jwk = { |
| 146 | kty: 'OKP', |
| 147 | crv: 'Ed25519', |
| 148 | x: Buffer.from(rawPublicKey).toString('base64url'), |
| 149 | }; |
| 150 | return crypto.createPublicKey({ key: jwk, format: 'jwk' }); |
| 151 | } else if (type === SignatureType.EcdsaP256SHA256) { |
| 152 | // Node.js doesn't have a built-in helper to parse raw ECDSA public key points synchronously |
| 153 | // without manual ASN.1 wrapping. As a cleaner alternative, we uncompress the point, slice |
| 154 | // the X and Y coordinates manually, and import it using the standardized JWK format. |
| 155 | const uncompressedPub = crypto.ECDH.convertKey( |
| 156 | rawPublicKey, |
| 157 | 'prime256v1', |
| 158 | /*inputEncoding=*/ undefined, |
| 159 | /*outputEncoding=*/ undefined, |
| 160 | 'uncompressed' |
| 161 | ) as Buffer; |
| 162 | |
| 163 | // uncompressedPub is a 65-byte Buffer. |
| 164 | // Byte 0 is the prefix (0x04), bytes 1-32 are X, bytes 33-64 are Y. |
| 165 | const x = uncompressedPub.subarray(1, 33); |
| 166 | const y = uncompressedPub.subarray(33, 65); |
| 167 | |
| 168 | const jwk = { |
| 169 | kty: 'EC', |
| 170 | crv: 'P-256', |
| 171 | x: Buffer.from(x).toString('base64url'), |
| 172 | y: Buffer.from(y).toString('base64url'), |
| 173 | }; |
| 174 | return crypto.createPublicKey({ key: jwk, format: 'jwk' }); |
| 175 | } |
| 176 | throw new Error('Unsupported signature type.'); |
| 177 | } |
| 178 | |
| 179 | export function calcWebBundleHash(webBundle: Uint8Array): Uint8Array { |
| 180 | const hash = crypto.createHash('sha512'); |
no test coverage detected