Skip to content

Commit

Permalink
goo: use deterministic miller-rabin. see #1.
Browse files Browse the repository at this point in the history
  • Loading branch information
chjj committed Nov 1, 2018
1 parent 7fa1ddc commit 6f3bebd
Show file tree
Hide file tree
Showing 6 changed files with 331 additions and 88 deletions.
22 changes: 6 additions & 16 deletions lib/goo.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

const assert = require('bsert');
const SHA256 = require('bcrypto/lib/sha256');
const DRBG = require('bcrypto/lib/drbg');
const BigMath = require('./bigmath');
const constants = require('./constants');
const primes = require('./primes');
const RNG = require('./rng');
const PRNG = require('./prng');
const Signature = require('./signature');
const util = require('./util');

Expand Down Expand Up @@ -374,10 +373,10 @@ class Goo {

if (!verify) {
// For prover, call nextPrime on ell_r to get ell.
ell = primes.nextPrime(ell, BigInt(constants.ELLDIFF_MAX));
ell = primes.nextPrime(ell, key, BigInt(constants.ELLDIFF_MAX));
}

return [chal, ell];
return [chal, ell, key];
}

expandSprime(s_prime) {
Expand Down Expand Up @@ -639,7 +638,8 @@ class Goo {
D += ell;

// Step 2: recompute implicitly claimed V message, viz., chal and ell.
const [chal_out, ell_r_out] = this.fsChal(C1, C2, t, A, B, C, D, msg, true);
const [chal_out, ell_r_out, key] =
this.fsChal(C1, C2, t, A, B, C, D, msg, true);

// Final checks.
// chal has to match
Expand All @@ -650,7 +650,7 @@ class Goo {
if (chal !== chal_out
|| elldiff < 0n
|| elldiff > BigInt(constants.ELLDIFF_MAX)
|| !primes.isPrime(ell)) {
|| !primes.isPrime(ell, key)) {
return false;
}

Expand Down Expand Up @@ -896,16 +896,6 @@ class Comb {
}
}

/*
* PRNG
*/

class PRNG extends RNG {
constructor(key) {
super(new DRBG(SHA256, key, constants.DRBG_NONCE, constants.DRBG_PERS));
}
}

/*
* Helpers
*/
Expand Down
67 changes: 39 additions & 28 deletions lib/primes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const assert = require('bsert');
const random = require('bcrypto/lib/random');
const BigMath = require('./bigmath');
const PRNG = require('./prng');
const util = require('./util');

/*
Expand Down Expand Up @@ -217,46 +218,55 @@ const primes = {
return true;
},

isPrimeRM(n, reps) {
isPrimeRM(n, key, reps, force2) {
if (key == null)
key = random.randomBytes(32);

assert(typeof n === 'bigint');
assert(Buffer.isBuffer(key));
assert((reps >>> 0) === reps);
assert(typeof force2 === 'boolean');

if (n < 7n) {
if (n === 3n || n === 5n)
return true;
return false;
}

const [d, r] = util.factorTwos(n - 1n);
const nm1 = n - 1n;
const k = BigMath.zeroBits(nm1);
const q = nm1 >> BigInt(k);

for (let i = 0; i < reps; i++) {
const m = n - 2n;
const len = BigMath.byteLength(m);
const nm3 = nm1 - 2n;

let a = 0n;
const prng = new PRNG(key);

while (a < 2n || a >= m)
a = BigMath.decode(random.randomBytes(len));
next:
for (let i = 0; i < reps; i++) {
let x, y;

let x = BigMath.modPow(a, d, n);
if (i === reps - 1 && force2) {
x = 2n;
} else {
x = prng.randomInt(nm3);
x += 2n;
}

if (x === 1n || x === n - 1n)
y = BigMath.modPow(x, q, n);

if (y === 1n || y === nm1)
continue;

let cont = false;
for (let j = 1; j < k; j++) {
y = BigMath.modPow(y, 2n, n);

for (let j = 0n; j < r - 1n; j++) {
x = BigMath.modPow(x, 2n, n);
if (y === nm1)
continue next;

if (x === n - 1n) {
cont = true;
break;
}
if (y === 1n)
return false;
}

if (cont)
continue;

return false;
}

Expand All @@ -274,28 +284,29 @@ const primes = {
return true;
},

// Baillie-PSW primality test (default #reps is overkill)
isPrime(n, reps = 2) {
// Baillie-PSW primality test.
isPrime(n, key) {
assert(typeof n === 'bigint');
assert((reps >>> 0) === reps);
assert(key == null || Buffer.isBuffer(key));

if (this.testPrimes.indexOf(n) !== -1)
return true;

if (!this.isPrimeDiv(n))
return false;

if (!this.isPrimeRM(n, 16 * reps))
if (!this.isPrimeRM(n, key, 16 + 1, true))
return false;

if (!this.isPrimeLucas(n, reps))
return false;
// if (!this.isPrimeLucas(n, 2))
// return false;

return true;
},

nextPrime(p, max = null) {
nextPrime(p, key, max = null) {
assert(typeof p === 'bigint');
assert(Buffer.isBuffer(key));
assert(max == null || (typeof max === 'bigint'));

let inc = 0n;
Expand All @@ -305,7 +316,7 @@ const primes = {
p |= 1n;
}

while (!this.isPrime(p)) {
while (!this.isPrime(p, key)) {
if (max != null && inc > max)
break;
p += 2n;
Expand Down
24 changes: 24 additions & 0 deletions lib/prng.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict';

/* eslint camelcase: "off" */

const SHA256 = require('bcrypto/lib/sha256');
const DRBG = require('bcrypto/lib/drbg');
const constants = require('./constants');
const RNG = require('./rng');

/*
* PRNG
*/

class PRNG extends RNG {
constructor(key) {
super(new DRBG(SHA256, key, constants.DRBG_NONCE, constants.DRBG_PERS));
}
}

/*
* Expose
*/

module.exports = PRNG;
2 changes: 1 addition & 1 deletion lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ const util = {
let i = 0n;
let cont = false;

while (!this.isPrime(p)) {
while (!this.isPrime(p, null)) {
if (i > amax / 10n) {
// Did we choose a "bad" b?
cont = true;
Expand Down

0 comments on commit 6f3bebd

Please sign in to comment.