PHP WebShell
Текущая директория: /opt/BitGoJS/modules/sdk-lib-mpc/test/unit/tss/ecdsa
Просмотр файла: rangeproof.ts
import sinon from 'sinon';
import * as paillierBigint from 'paillier-bigint';
import { EcdsaRangeProof, EcdsaTypes } from '../../../../src/tss/ecdsa';
import {
randomPositiveCoPrimeTo,
Secp256k1Curve,
BaseCurve,
bigIntToBufferBE,
bigIntFromBufferBE,
} from '../../../../src';
import * as safePrimes from '../../../../src/safePrime';
import { DeserializedNtilde, RangeProof } from '../../../../src/tss/ecdsa/types';
import { modPow, randBetween } from 'bigint-crypto-utils';
import { createHash } from 'crypto';
import { loadWebAssembly } from '@bitgo/sdk-opensslbytes';
const openSSLBytes = loadWebAssembly().buffer;
describe('MtA range proof', function () {
const curve = new Secp256k1Curve();
let switchPrime = false;
let safePrimeMock: sinon.SinonStub;
let paillierKeyPair: paillierBigint.KeyPair;
let ntilde: EcdsaTypes.DeserializedNtilde;
before('set up paillier and ntile', async function () {
safePrimeMock = sinon.stub(safePrimes, 'generateSafePrime').callsFake(async (bitlength: number) => {
// Both primes below were generated using 'openssl prime -bits 256 -generate -safe'.
if (switchPrime) {
switchPrime = false;
return BigInt('105026459418240911050597781175405200114409463599422710187772697695413160518507');
} else {
switchPrime = true;
return BigInt('97740038048923029272833872518628089389073263932043585221445032564807403246907');
}
});
paillierKeyPair = await paillierBigint.generateRandomKeys(2048, true);
ntilde = await EcdsaRangeProof.generateNtilde(openSSLBytes, 512);
});
after(function () {
safePrimeMock.reset();
safePrimeMock.restore();
});
it('valid range proof', async function () {
const k = curve.scalarRandom();
const rk = await randomPositiveCoPrimeTo(paillierKeyPair.publicKey.n);
const ck = paillierKeyPair.publicKey.encrypt(k, rk);
const proof = await EcdsaRangeProof.prove(
curve,
2048,
paillierKeyPair.publicKey,
{
ntilde: ntilde.ntilde,
h1: ntilde.h1,
h2: ntilde.h2,
},
ck,
k,
rk
);
EcdsaRangeProof.verify(
curve,
2048,
paillierKeyPair.publicKey,
{
ntilde: ntilde.ntilde,
h1: ntilde.h1,
h2: ntilde.h2,
},
proof,
ck
).should.be.true();
});
it('encrypted value too big', async function () {
// Pick k based on attack described in https://eprint.iacr.org/2021/1621.pdf, where M = 2^29 is chosen.
const k = (BigInt(2) * (BigInt(2) ^ BigInt(29)) * paillierKeyPair.publicKey.n) / curve.order();
const rk = await randomPositiveCoPrimeTo(paillierKeyPair.publicKey.n);
const ck = paillierKeyPair.publicKey.encrypt(k, rk);
const proof = await EcdsaRangeProof.prove(
curve,
2048,
paillierKeyPair.publicKey,
{
ntilde: ntilde.ntilde,
h1: ntilde.h1,
h2: ntilde.h2,
},
ck,
k,
rk
);
EcdsaRangeProof.verify(
curve,
2048,
paillierKeyPair.publicKey,
{
ntilde: ntilde.ntilde,
h1: ntilde.h1,
h2: ntilde.h2,
},
proof,
ck
).should.be.false();
});
it('invalid range proof with 0 u and s', async function () {
const k = curve.scalarRandom();
const rk = await randomPositiveCoPrimeTo(paillierKeyPair.publicKey.n);
const ck = paillierKeyPair.publicKey.encrypt(k, rk);
const proof = await malicious_prove(
curve,
2048,
paillierKeyPair.publicKey,
{
ntilde: ntilde.ntilde,
h1: ntilde.h1,
h2: ntilde.h2,
},
ck,
k
);
EcdsaRangeProof.verify(
curve,
2048,
paillierKeyPair.publicKey,
{
ntilde: ntilde.ntilde,
h1: ntilde.h1,
h2: ntilde.h2,
},
proof,
ck
).should.be.false();
});
});
async function malicious_prove(
curve: BaseCurve,
modulusBits: number,
pk: paillierBigint.PublicKey,
ntilde: DeserializedNtilde,
c: bigint,
m: bigint
): Promise<RangeProof> {
const modulusBytes = Math.floor((modulusBits + 7) / 8);
const q = curve.order();
const q3 = q ** BigInt(3);
const qntilde = q * ntilde.ntilde;
const q3ntilde = q3 * ntilde.ntilde;
const alpha = randBetween(q3);
const gamma = randBetween(q3ntilde);
const rho = randBetween(qntilde);
const z = (modPow(ntilde.h1, m, ntilde.ntilde) * modPow(ntilde.h2, rho, ntilde.ntilde)) % ntilde.ntilde;
const u = BigInt(0);
const w = (modPow(ntilde.h1, alpha, ntilde.ntilde) * modPow(ntilde.h2, gamma, ntilde.ntilde)) % ntilde.ntilde;
const hash = createHash('sha256');
hash.update('\x06\x00\x00\x00\x00\x00\x00\x00');
hash.update(bigIntToBufferBE(pk.n, modulusBytes));
hash.update('$');
hash.update(bigIntToBufferBE(pk.g, modulusBytes));
hash.update('$');
hash.update(bigIntToBufferBE(c, 2 * modulusBytes));
hash.update('$');
hash.update(bigIntToBufferBE(z, modulusBytes));
hash.update('$');
hash.update(bigIntToBufferBE(u, 2 * modulusBytes));
hash.update('$');
hash.update(bigIntToBufferBE(w, modulusBytes));
hash.update('$');
const e = bigIntFromBufferBE(hash.digest()) % q;
const s = BigInt(0);
const s1 = e * m + alpha;
const s2 = e * rho + gamma;
return { z, u, w, s, s1, s2 };
}
Выполнить команду
Для локальной разработки. Не используйте в интернете!