import * as secp from "../../src/secp256k1-compat" ; import { sha256 } from "../../src/sha256" ; import { concatBytes , hexToBytes , toHex } from "../../src/utils" ; import { deepStrictEqual , throws } from "./assert" ; import { VECTORS } from "./secp256k1_lib_vectors" ; describe ( "secp256k1" , function ( ) { it ( "should create valid private keys" , async function ( ) { const asyncPk = await secp . createPrivateKey ( ) ; const syncPk = secp . createPrivateKeySync ( ) ; deepStrictEqual ( secp . privateKeyVerify ( asyncPk ) , true ) ; deepStrictEqual ( secp . privateKeyVerify ( syncPk ) , true ) ; } ) ; it ( "Should sign correctly" , function ( ) { const msgHash = hexToBytes ( "82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28" ) ; const privateKey = hexToBytes ( "3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1" ) ; const signature = secp . ecdsaSign ( msgHash , privateKey ) ; const sig = { r : signature . signature . slice ( 0 , 32 ) , s : signature . signature . slice ( 32 , 64 ) , v : signature . recid } ; deepStrictEqual ( secp . signatureImport ( secp . signatureExport ( signature . signature ) ) , signature . signature ) ; deepStrictEqual ( sig . r , hexToBytes ( "99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9" ) ) ; deepStrictEqual ( sig . s , hexToBytes ( "129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66" ) ) ; deepStrictEqual ( sig . v , 0 ) ; } ) ; it ( "Should recover signatures correctly" , function ( ) { const echash = hexToBytes ( "82ff40c0a986c6a5cfad4ddf4c3aa6996f1a7837f9c398e17e5de5cbd5a12b28" ) ; const recid = 0 ; const r = hexToBytes ( "99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9" ) ; const s = hexToBytes ( "129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66" ) ; const expected = hexToBytes ( "b4ac68eff3a82d86db5f0489d66f91707e99943bf796ae6a2dcb2205c9522fa7915428b5ac3d3b9291e62142e7246d85ad54504fabbdb2bae5795161f8ddf259" ) ; const signature = concatBytes ( r , s ) ; const senderPubKey = secp . ecdsaRecover ( signature , recid , echash ) ; const recovered = secp . publicKeyConvert ( senderPubKey , false ) . slice ( 1 ) ; deepStrictEqual ( recovered , expected ) ; deepStrictEqual ( secp . signatureImport ( secp . signatureExport ( signature ) ) , signature ) ; } ) ; it ( "ecdh with hashfn" , ( ) => { const privateKey = hexToBytes ( "3c9229289a6125f7fdf1885a77bb12c37a8d3b4962d936f7e3084dece32a3ca1" ) ; const publicKey = hexToBytes ( "04b4ac68eff3a82d86db5f0489d66f91707e99943bf796ae6a2dcb2205c9522fa7915428b5ac3d3b9291e62142e7246d85ad54504fabbdb2bae5795161f8ddf259" ) ; const output = new Uint8Array ( 32 ) ; const output2 = new Uint8Array ( 33 ) ; const xbuf = new Uint8Array ( 32 ) ; const ybuf = new Uint8Array ( 32 ) ; const hashfn = ( x , y , data ) => sha256 ( concatBytes ( x , y , data ) ) ; const hashfn2 = ( x , y , data ) => new Uint8Array ( 33 ) ; const d = new Uint8Array ( [ 1 , 2 , 3 , 4 , 5 ] ) ; const exp1 = "9461b13c2191424a2adafc45f8043504454dc37199b73a999bd12463b6904eeb" ; const exp2 = "6945269332a7e162866138faaffc09636e78ca742edbb555a2c274f7446cf6fb" ; deepStrictEqual ( toHex ( secp . ecdh ( publicKey , privateKey , { } ) ) , exp1 ) ; deepStrictEqual ( toHex ( secp . ecdh ( publicKey , privateKey , { data : d } ) ) , exp1 ) ; throws ( ( ) => secp . ecdh ( publicKey , privateKey , { data : d , hashfn } ) ) ; throws ( ( ) => secp . ecdh ( publicKey , privateKey , { data : d , hashfn } , output2 ) ) ; deepStrictEqual ( toHex ( secp . ecdh ( publicKey , privateKey , { data : d , hashfn } , output ) ) , exp2 ) ; deepStrictEqual ( toHex ( output ) , exp2 ) ; deepStrictEqual ( toHex ( secp . ecdh ( publicKey , privateKey , { data : d , hashfn , xbuf , ybuf } , output ) ) , exp2 ) ; deepStrictEqual ( toHex ( output ) , exp2 ) ; deepStrictEqual ( toHex ( xbuf ) , "8b2983e19282e35890fa04abc0ca4a1981723c50413db91a1387c43caae4888f" ) ; deepStrictEqual ( toHex ( ybuf ) , "6a4ee6fcc9e1403ab90236594278dfe158cd79608f4434f27506c5dd39776f97" ) ; throws ( ( ) => secp . ecdh ( publicKey , privateKey , { data : d , hashfn : hashfn2 , xbuf , ybuf } , output ) ) ; } ) ; describe ( "Test vectors against library" , ( ) => { const unserialize = ( obj ) : any => { if ( Array . isArray ( obj ) ) { return obj . map ( i => unserialize ( i ) ) ; } if ( typeof obj === "object" && obj !== null ) { if ( obj . __BigInt__ ) { return BigInt ( `0x${ obj . __BigInt__ }` ) ; } else if ( obj . __Buffer__ ) { return hexToBytes ( obj . __Buffer__ ) ; } else if ( obj . __Bytes__ ) { return hexToBytes ( obj . __Bytes__ ) ; } const res = { } ; for ( const key of Object . keys ( obj ) ) { res [ key ] = unserialize ( obj [ key ] ) ; } return res ; } return obj ; } ; const genTest = ( vectors , name , fn ) => { for ( let i = 0 ; i < vectors [ name ] . length ; i ++ ) { const vector = vectors [ name ] [ i ] ; it ( `${ name } (${ i })${ vector . err ? ` ERR: ${ vector . err }` : "" }` , ( ) => { if ( vector . err ) { throws ( ( ) => fn ( ... vector . args ) ) ; } else { deepStrictEqual ( fn ( ... vector . args ) , vector . res ) ; } deepStrictEqual ( vector . args , vector . argsAfter ) ; } ) ; } } ; const genTests = ( vectors , library ) => { for ( const k of Object . keys ( vectors ) ) { const path = k . split ( "." ) ; let cur = library ; for ( const i of path ) { if ( ! cur || typeof cur !== "object" ) { throw new Error ( `genTests: not object: ${ k }, ${ i }, ${ typeof cur }` ) ; } cur = cur [ i ] ; } if ( typeof cur !== "function" ) { throw new Error ( `genTests: not function ${ k }` ) ; } genTest ( vectors , k , cur ) ; } } ; genTests ( unserialize ( VECTORS ) , { secp256k1 : secp } ) ; } ) ; } ) ;