UNPKG

@credo-ts/core

Version:

<p align="center"> <br /> <img alt="Credo Logo" src="https://github.com/openwallet-foundation/credo-ts/blob/c7886cb8377ceb8ee4efe8d264211e561a75072d/images/credo-logo.png" height="250px" /> </p> <h1 align="center"><b>Credo - Core</b></h1

94 lines (90 loc) • 3.5 kB
import { KeyManagementError } from "../../../error/KeyManagementError.mjs"; import { ecCrvToCurveParams } from "./ecPublicKey.mjs"; import { ECDSASigValue } from "@peculiar/asn1-ecc"; import { AsnConvert } from "@peculiar/asn1-schema"; //#region src/modules/kms/jwk/kty/ec/ecSignature.ts /** * Converts a RAW EC signature to DER format * * @param rawSignature - Raw signature as r || s concatenated values * @param crv - The EC crv of the key used for the signature * @returns DER encoded signature */ function rawEcSignatureToDer(rawSignature, crv) { const pointBitLength = ecCrvToCurveParams[crv].pointBitLength; const pointByteLength = Math.ceil(pointBitLength / 8); if (rawSignature.length !== pointByteLength * 2) throw new KeyManagementError(`Invalid raw signature length for EC signature conversion. Expected ${pointByteLength * 2} bytes for crv ${crv}`); const r = rawSignature.slice(0, pointByteLength); const s = rawSignature.slice(pointByteLength); const rValue = removeLeadingZeros(r); const sValue = removeLeadingZeros(s); const signature = new ECDSASigValue(); signature.r = new Uint8Array(ensurePositive(rValue)).buffer; signature.s = new Uint8Array(ensurePositive(sValue)).buffer; return new Uint8Array(AsnConvert.serialize(signature)); } /** * Converts a DER encoded EC signature to RAW format * * @param derSignature - DER encoded signature * @param crv - The EC crv of the key used for the signature * @returns Raw signature as r || s concatenated values */ function derEcSignatureToRaw(derSignature, crv) { const asn = AsnConvert.parse(derSignature, ECDSASigValue); const pointBitLength = ecCrvToCurveParams[crv].pointBitLength; const pointByteLength = Math.ceil(pointBitLength / 8); const rPadded = padToLength(new Uint8Array(asn.r), pointByteLength); const sPadded = padToLength(new Uint8Array(asn.s), pointByteLength); const rawSignature = new Uint8Array(pointByteLength * 2); rawSignature.set(rPadded, 0); rawSignature.set(sPadded, pointByteLength); return rawSignature; } /** * Helper function to remove unnecessary leading zeros from an integer representation * * @param data - The integer bytes * @returns - Data with leading zeros removed */ function removeLeadingZeros(data) { let startIndex = 0; while (startIndex < data.length - 1 && data[startIndex] === 0) startIndex++; return data.slice(startIndex); } /** * Ensures an integer value is represented as positive in ASN.1 by * adding a leading zero if the high bit is set * * @param data - The integer bytes * @returns Data ensuring positive integer representation */ function ensurePositive(data) { if (data.length > 0 && (data[0] & 128) !== 0) { const result = new Uint8Array(data.length + 1); result.set(data, 1); return result; } return data; } /** * Pads an integer value to the specified length * * @param data - The integer bytes * @param targetLength - The desired length * @returns Padded data */ function padToLength(data, targetLength) { if (data.length === targetLength) return data; if (data.length > targetLength) { const significantStart = data.length - targetLength; for (let i = 0; i < significantStart; i++) if (data[i] !== 0) throw new KeyManagementError("Value too large for the specified point size"); return data.slice(significantStart); } const result = new Uint8Array(targetLength); result.set(data, targetLength - data.length); return result; } //#endregion export { derEcSignatureToRaw, rawEcSignatureToDer }; //# sourceMappingURL=ecSignature.mjs.map