diff --git a/src/common.ts b/src/common.ts index df7d89954..aeafa7cc3 100644 --- a/src/common.ts +++ b/src/common.ts @@ -1,9 +1,14 @@ import * as asn1js from "asn1js"; import * as pvutils from "pvutils"; -import { AlgorithmIdentifier } from "./AlgorithmIdentifier"; -import { EMPTY_BUFFER } from "./constants"; -import type { CryptoEngineAlgorithmOperation, CryptoEngineAlgorithmParams, ICryptoEngine } from "./CryptoEngine/CryptoEngineInterface"; -import { ArgumentError } from "./errors"; +import {Convert} from "pvtsutils"; +import {AlgorithmIdentifier} from "./AlgorithmIdentifier"; +import {EMPTY_BUFFER} from "./constants"; +import type { + CryptoEngineAlgorithmOperation, + CryptoEngineAlgorithmParams, + ICryptoEngine +} from "./CryptoEngine/CryptoEngineInterface"; +import {ArgumentError} from "./errors"; //#region Crypto engine related function export { ICryptoEngine } from "./CryptoEngine/CryptoEngineInterface"; @@ -189,13 +194,15 @@ export function createCMSECDSASignature(signatureBuffer: ArrayBuffer): ArrayBuff const rView = new Uint8Array(rBuffer); rView.set(new Uint8Array(signatureBuffer, 0, length)); - const rInteger = new asn1js.Integer({ valueHex: rBuffer }); + const rBigInt= bufferToBigInt(rBuffer); + const rInteger= asn1js.Integer.fromBigInt(rBigInt); const sBuffer = new ArrayBuffer(length); const sView = new Uint8Array(sBuffer); sView.set(new Uint8Array(signatureBuffer, length, length)); - const sInteger = new asn1js.Integer({ valueHex: sBuffer }); + const sBigInt = bufferToBigInt(sBuffer); + const sInteger = asn1js.Integer.fromBigInt(sBigInt); //#endregion return (new asn1js.Sequence({ @@ -406,6 +413,13 @@ export async function kdf(hashFunction: string, Zbuffer: ArrayBuffer, keydatalen //#endregion //#endregion } -//#endregion -import { CryptoEngine } from "./CryptoEngine/CryptoEngine"; \ No newline at end of file +//#region To ensure correct ASN.1 formatting, convert buffer to BigInt to use asn1js.Integer.fromBigInt +function bufferToBigInt(buffer: ArrayBuffer): bigint { + const hex = "0x" + Convert.ToHex(buffer); + return BigInt(hex); +} + +//#endregion +//#endregion +import {CryptoEngine} from "./CryptoEngine/CryptoEngine"; \ No newline at end of file diff --git a/test/asn1jIntTest.spec.ts b/test/asn1jIntTest.spec.ts new file mode 100644 index 000000000..7b0455ce8 --- /dev/null +++ b/test/asn1jIntTest.spec.ts @@ -0,0 +1,44 @@ +import * as asn1js from "asn1js"; +import * as assert from "assert"; +import {Convert} from "pvtsutils"; +import {createCMSECDSASignature} from "../src"; + +const testVectors = [ + { + rHex: "010fc11f9fa733d62042904c2a4f5077d84a0cb61162e10dec784830521327a4a50d8be8a7b3778568a6c51355519ea12dad6347583c0ff6921285c7ed3db7439586", + sHex: "000000000dadfe9ce0563383ef6dc2f06a6cb35f72cc66b5626bf91a1508b309207390ff302164c2e78f7e2958ee8d9e9cc7cca4a6a20cb9a011b0850212a50ca515" + + }, + { + rHex: "00000000068e322ecf4487d24ab2484276f20f5b660e1f651df2d24623f74e216588de5fe4ee65b84cb62579e06dedb4be87bd96e0d9726ac64f6cdfd4369465b31b", + sHex: "01ead398135ff59757a0400074f885a7a22eb624349d3cd245309266f7229e8ca977492634b8960c2ea86215d8a9dcfb8d3e17775bcbf33cf46f1f8e8d7c3f3e4c53" + + }, + { + rHex: "000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + sHex: "000000000000000000000000000000000000000000000000000000000000000000000000000000000002" + }, + { + rHex: "52e3f7b727fba9e8eddb1d083b75c1882517e6dc63ded9c0524f8f9a45dc8661", + sHex: "b8930438de8d33bdab12c3a2bdad979592a1fd6576d1734c3eb0af340456aef4" + }, +]; + +describe("createCMSECDSASignature - ", () => { + testVectors.forEach(({rHex, sHex}, no) => { + it(`should encode signature vector #${no + 1} correctly`, () => { + const signatureBuffer = Convert.FromHex(rHex + sHex); + const derBuffer = createCMSECDSASignature(signatureBuffer); + const asn1 = asn1js.fromBER(derBuffer); + + const seq = asn1.result as asn1js.Sequence; + const [rInt, sInt] = seq.valueBlock.value as [asn1js.Integer, asn1js.Integer]; + + const rValueHex = Convert.ToHex(rInt.valueBlock.valueHexView); + const sValueHex = Convert.ToHex(sInt.valueBlock.valueHexView); + + assert.ok(rValueHex.endsWith(rHex.replace(/^00+/, "")), "r not encoded correctly"); + assert.ok(sValueHex.endsWith(sHex.replace(/^00+/, "")), "s not encoded correctly"); + }); + }); +}); \ No newline at end of file