diff --git a/src/asn/ec_signature.ts b/src/asn/ec_signature.ts index 9b21ee9..27cb412 100644 --- a/src/asn/ec_signature.ts +++ b/src/asn/ec_signature.ts @@ -19,7 +19,7 @@ export const AsnIntegerWithoutPaddingConverter: IAsnConverter = { }, toASN: (value: ArrayBuffer) => { const bytes = new Uint8Array(value); - if (bytes[0] > 128) { + if (bytes[0] > 127) { const newValue = new Uint8Array(bytes.length + 1); newValue.set(bytes, 1); return new asn1.Integer({ valueHex: newValue }); diff --git a/src/mechs/ec/crypto.ts b/src/mechs/ec/crypto.ts index f5ccdb8..11c69e3 100644 --- a/src/mechs/ec/crypto.ts +++ b/src/mechs/ec/crypto.ts @@ -62,10 +62,12 @@ export class EcCrypto { const signature = signer.sign(options); const ecSignature = AsnParser.parse(signature, asn.EcDsaSignature); - return new Uint8Array(Buffer.concat([ - Buffer.from(ecSignature.r), - Buffer.from(ecSignature.s), - ])).buffer; + const pointSize = this.getPointSize(key.algorithm.namedCurve); + const r = this.addPadding(pointSize, Buffer.from(ecSignature.r)); + const s = this.addPadding(pointSize, Buffer.from(ecSignature.s)); + + const signatureRaw = new Uint8Array(Buffer.concat([r, s])).buffer; + return signatureRaw; } public static async verify(algorithm: EcdsaParams, key: EcPublicKey, signature: Uint8Array, data: Uint8Array): Promise { @@ -78,11 +80,12 @@ export class EcCrypto { }; const ecSignature = new asn.EcDsaSignature(); - const size = signature.length / 2; - ecSignature.r = signature.buffer.slice(0, size); - ecSignature.s = signature.buffer.slice(size, size + size); + const pointSize = this.getPointSize(key.algorithm.namedCurve); + ecSignature.r = this.removePadding(signature.slice(0, pointSize)); + ecSignature.s = this.removePadding(signature.slice(pointSize, pointSize + pointSize)); - const ok = signer.verify(options, Buffer.from(AsnSerializer.serialize(ecSignature))); + const ecSignatureRaw = Buffer.from(AsnSerializer.serialize(ecSignature)); + const ok = signer.verify(options, ecSignatureRaw); return ok; } @@ -192,4 +195,34 @@ export class EcCrypto { } } + private static getPointSize(namedCurve: string) { + switch (namedCurve) { + case "P-256": + case "K-256": + return 32; + case "P-384": + return 48; + case "P-521": + return 66; + default: + throw new Error(`Cannot get size for the named curve '${namedCurve}'`); + } + } + + private static addPadding(pointSize: number, bytes: Buffer) { + const res = Buffer.alloc(pointSize); + res.set(Buffer.from(bytes), pointSize - bytes.length); + return res; + } + + private static removePadding(bytes: Uint8Array) { + for (let i = 0; i < bytes.length; i++) { + if (!bytes[i]) { + continue; + } + return bytes.slice(i).buffer; + } + return new ArrayBuffer(0); + } + }