Fix ECDSA sign/verify error

This commit is contained in:
microshine 2019-02-16 01:43:08 +03:00
parent feaf3cc798
commit 97c0c5956b
2 changed files with 42 additions and 9 deletions

View File

@ -19,7 +19,7 @@ export const AsnIntegerWithoutPaddingConverter: IAsnConverter<ArrayBuffer> = {
},
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 });

View File

@ -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<boolean> {
@ -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);
}
}