diff --git a/src/libMPC/SCL_ecc.mjs b/src/libMPC/SCL_ecc.mjs index b4ec431..3438614 100644 --- a/src/libMPC/SCL_ecc.mjs +++ b/src/libMPC/SCL_ecc.mjs @@ -12,6 +12,8 @@ /********************************************************************************************/ +import { etc, utils, getPublicKey } from '@noble/secp256k1'; + import { ed25519 } from '@noble/curves/ed25519'; import { secp256k1 } from '@noble/curves/secp256k1'; import { reverse, int_from_bytes, int_to_bytes } from './common.mjs'; @@ -32,7 +34,20 @@ export class SCL_ecc throw new Error('Unsupported curve'); } } - + + IndividualPubKey_array(scalar_array){ + + if (this.curve === 'secp256k1') { + const publicKey = getPublicKey(scalar_array); + return publicKey; + } + if (this.curve === 'ed25519') { + const publicKey = this.curve.GetBase().multiply(int_from_bytes(scalar_array)); // 'true' for compressed format + return this.curve.PointCompress(publicKey);//the getPublicKey is replaced by a scalar multiplication to be compatible with key aggregation + } + + throw new Error('Unsupported curve'); + } GetBase(){ if (this.curve === 'secp256k1') { diff --git a/src/libMPC/SCL_frost.mjs b/src/libMPC/SCL_frost.mjs index c405064..34d6285 100644 --- a/src/libMPC/SCL_frost.mjs +++ b/src/libMPC/SCL_frost.mjs @@ -18,68 +18,194 @@ import { secp256k1 } from '@noble/curves/secp256k1'; import { etc, utils, getPublicKey } from '@noble/secp256k1'; import{SCL_ecc} from './SCL_ecc.mjs'; import { randomBytes } from 'crypto'; // Use Node.js's crypto module +import { Field } from "@noble/curves/abstract/modular"; -import{SCL_Musig2} from './SCL_Musig2.mjs'; -export class SCL_polynomials{ - constructor(modulus, coeffs){ - this.coeffs=coeffs; - this.modulus=this.modulus; +//beware that because horner method is used degree 0 coefficient is last of the list +function Evaluate(coeffs,x, modulus){ + let res=coeffs[0];//a0 + for(let i=1;ipoints[0]); + } //in the future, improve it with a PRNG using secret and random generator GetRandomElement(){ - return this.signer.curve.Get_Random_privateKey() + return this.curve.Get_Random_privateKey(); } - KeyGen(n, k){ + KeyGen(n, min_participants){ + + if(min_participants<1) return false; + this.n=n;//maximum number of participants - this.k=k;//minimum number of participants = degree of polynomial-1 + this.degree=min_participants-1;//minimum number of participants = degree of polynomial-1 - //generate secret shares: - for(i=0;i0;i--){ + let ai=this.GetRandomElement(); + this.coeffs.push(int_from_bytes(ai)); + } + this.coeffs.push(int_from_bytes(this.sk));//a0=P(0)=secret + + + //Shares are evaluation of P starting from 1, P(0) being the secret + for(let xi=1;xipoints[0]),x, this.curve.order);//yi * interpolate(L,xi) + P0=(P0 + delta)%this.curve.order; + } + return P0; + } + + //interpolate the points (xi,P(xi).G) in 0 (group public key) + Interpolate_group_pubkey(pubkeys, ids){ + let Q = this.curve.GetZero(); + if(pubkeys.length!=ids.length){ + return false; + } + for(let i=0;i, + __Q: undefined, + compressed: true, + network: { + messagePrefix: '\x18Bitcoin Signed Message:\n', + bech32: 'tb', + bip32: { public: 70617039, private: 70615956 }, + pubKeyHash: 111, + scriptHash: 196, + wif: 239 + }, + lowR: false + } + key pub Uint8Array(33) [ + 2, 248, 59, 32, 158, 235, 60, 129, + 164, 106, 165, 105, 84, 237, 54, 69, + 94, 92, 106, 152, 120, 142, 249, 156, + 21, 141, 229, 187, 241, 24, 201, 176, + 35 + ] + Private Key (WIF): cVeV7EtdSB2waytpSAikiuXakmWvmaaAnyw1X9cxrokKEdWgWuxz + Testnet Address: tb1plqajp8ht8jq6g649d92w6dj9tewx4xrc3muec9vdukalzxxfkq3s2vk3nu + + //funded with TxID 62d9b44b6a6268bd4a74ab2141133343849f012b694e0ff7c32b0b3f5e3c87fa + */ \ No newline at end of file diff --git a/src/libMPC/test_frost.mjs b/src/libMPC/test_frost.mjs new file mode 100644 index 0000000..47532e9 --- /dev/null +++ b/src/libMPC/test_frost.mjs @@ -0,0 +1,51 @@ +/********************************************************************************************/ +/* +/* ___ _ _ ___ _ _ _ _ +/* / __|_ __ ___ ___| |_| |_ / __|_ _ _ _ _ __| |_ ___ | | (_) |__ +/* \__ \ ' \/ _ \/ _ \ _| ' \ | (__| '_| || | '_ \ _/ _ \ | |__| | '_ \ +/* |___/_|_|_\___/\___/\__|_||_| \___|_| \_, | .__/\__\___/ |____|_|_.__/ +/* |__/|_| +/* +/* Copyright (C) 2024 - Renaud Dubois - This file is part of SCL (Smooth CryptoLib) project +/* License: This software is licensed under MIT License +/********************************************************************************************/ + +import { ed25519 } from '@noble/curves/ed25519'; +import{reverse, bytes_xor, int_from_bytes, int_to_bytes, tagged_hashBTC, taghash_rfc8032} from "./common.mjs"; + +import { secp256k1 } from '@noble/curves/secp256k1'; +import { etc, utils, getPublicKey } from '@noble/secp256k1'; +import{SCL_ecc} from './SCL_ecc.mjs'; +import { randomBytes } from 'crypto'; // Use Node.js's crypto module +import { Field } from "@noble/curves/abstract/modular"; + +import { SCL_trustedKeyGen } from './SCL_frost.mjs'; + +function test_randomInterpolate_secret(){ + + let curve=new SCL_ecc('secp256k1'); + let sk=curve.Get_Random_privateKey(); + + let dealer=new SCL_trustedKeyGen( 'secp256k1',sk, 12,4); + + console.log("Consistency secret/public shares:",dealer.Check_Shares()); + //erasing to prove Reed Solomon like recovery of missing shares + + + let rec_secret=dealer.Interpolate_group_seckey(dealer.secshares); + console.log("interpolating secret:", rec_secret==int_from_bytes(sk)); + + let rec_public=dealer.Interpolate_group_pubkey(dealer.pubshares, dealer.ids); + + console.log("interpolating public keys", Buffer.from(rec_public).equals(dealer.pubkey)); +} + + + + +(async () => { + test_randomInterpolate_secret(); + + + +})(); \ No newline at end of file