New probabilistic random number generation algorithms; UNTESTED
This commit is contained in:
parent
3b912d2fae
commit
168a6b0bb8
135
src/crypto/public_key/prime.js
Normal file
135
src/crypto/public_key/prime.js
Normal file
|
@ -0,0 +1,135 @@
|
|||
// OpenPGP.js - An OpenPGP implementation in javascript
|
||||
// Copyright (C) 2018 Proton Technologies AG
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 3.0 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
// Algorithms for probabilistic primality testing
|
||||
|
||||
/**
|
||||
* @requires bn.js
|
||||
* @requires crypto/random
|
||||
* @module crypto/public_key/prime
|
||||
*/
|
||||
|
||||
import BN from 'bn.js';
|
||||
import random from '../random';
|
||||
|
||||
function randomProbablePrime(b) {
|
||||
let n;
|
||||
const min = new BN(1).shln(b-1);
|
||||
do {
|
||||
n = random.getRandomBN(min, min.shln(1));
|
||||
if (n.isEven()) {
|
||||
n.iaddn(1); // force odd
|
||||
}
|
||||
} while (!isProbablePrime(n));
|
||||
// this.dAddOffset(2, 0);
|
||||
// if (this.bitLength() > b)
|
||||
// this.subTo(BigInteger.ONE.shiftLeft(b - 1), this);
|
||||
}
|
||||
|
||||
function isProbablePrime(n) {
|
||||
if (!fermat(n)) {
|
||||
return false;
|
||||
}
|
||||
if (!millerRabin(n)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether n is probably prime or not using Fermat's test with b = 2.
|
||||
* Fails if b^(n-1) mod n === 1.
|
||||
*/
|
||||
export function fermat(n, b) {
|
||||
b = b || new BN(2);
|
||||
return b.toRed(BN.mont(n)).redPow(n.subn(1)).cmpn(1) === 0;
|
||||
}
|
||||
|
||||
|
||||
// Miller-Rabin - Miller Rabin algorithm for primality test
|
||||
// Copyright Fedor Indutny, 2014.
|
||||
//
|
||||
// This software is licensed under the MIT License.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// Adapted on Jan 2018 from version 4.0.1 at https://github.com/indutny/miller-rabin
|
||||
// TODO check this against jsbn's bnpMillerRabin
|
||||
// TODO implement fixed base Miller-Rabin; for instance by writing a function that
|
||||
// picks a number within the given range from a precomputed list of primes.
|
||||
|
||||
/**
|
||||
* Tests whether n is probably prime or not using the Miller-Rabin test.
|
||||
* See HAC Remark 4.28.
|
||||
*/
|
||||
export function millerRabin(n, k, cb) {
|
||||
var len = n.bitLength();
|
||||
var red = BN.mont(n);
|
||||
var rone = new BN(1).toRed(red);
|
||||
|
||||
if (!k)
|
||||
k = Math.max(1, (len / 48) | 0);
|
||||
|
||||
// Find d and s, (n - 1) = (2 ^ s) * d;
|
||||
var n1 = n.subn(1);
|
||||
for (var s = 0; !n1.testn(s); s++) {}
|
||||
var d = n.shrn(s);
|
||||
|
||||
var rn1 = n1.toRed(red);
|
||||
|
||||
var prime = true;
|
||||
for (; k > 0; k--) {
|
||||
var a = random.getRandomBN(new BN(2), n1);
|
||||
if (cb)
|
||||
cb(a);
|
||||
|
||||
var x = a.toRed(red).redPow(d);
|
||||
if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
|
||||
continue;
|
||||
|
||||
for (var i = 1; i < s; i++) {
|
||||
x = x.redSqr();
|
||||
|
||||
if (x.cmp(rone) === 0)
|
||||
return false;
|
||||
if (x.cmp(rn1) === 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i === s)
|
||||
return false;
|
||||
}
|
||||
|
||||
return prime;
|
||||
};
|
|
@ -20,6 +20,7 @@
|
|||
/**
|
||||
* @requires bn.js
|
||||
* @requires asmcrypto.js
|
||||
* @requires crypto/public_key/prime
|
||||
* @requires crypto/random
|
||||
* @requires config
|
||||
* @requires util
|
||||
|
@ -31,6 +32,7 @@ import BN from 'bn.js';
|
|||
import { RSA } from 'asmcrypto.js/src/rsa/exports-keygen';
|
||||
import { RSA_RAW } from 'asmcrypto.js/src/rsa/exports-raw';
|
||||
import { random as asmcrypto_random } from 'asmcrypto.js/src/random/exports';
|
||||
import prime from './prime';
|
||||
import random from '../random';
|
||||
import config from '../../config';
|
||||
import util from '../../util';
|
||||
|
|
|
@ -97,7 +97,7 @@ export default {
|
|||
},
|
||||
|
||||
/**
|
||||
* Create a secure random MPI in specified range
|
||||
* Create a secure random MPI that is greater than or equal to min and less than max.
|
||||
* @param {module:type/mpi} min Lower bound, included
|
||||
* @param {module:type/mpi} max Upper bound, excluded
|
||||
* @return {module:BN} Random MPI
|
||||
|
@ -107,18 +107,19 @@ export default {
|
|||
throw new Error('Illegal parameter value: max <= min');
|
||||
}
|
||||
|
||||
let r;
|
||||
const modulus = max.sub(min);
|
||||
const length = modulus.byteLength();
|
||||
let r = new BN(this.getRandomBytes(length));
|
||||
|
||||
// Using a while loop is necessary to avoid bias
|
||||
while (r.cmp(modulus) >= 0) {
|
||||
do {
|
||||
r = new BN(this.getRandomBytes(length));
|
||||
}
|
||||
} while (r.cmp(modulus) >= 0);
|
||||
|
||||
return r.iadd(min);
|
||||
},
|
||||
|
||||
randomBuffer: new RandomBuffer()
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,8 +21,7 @@
|
|||
// - MPI = c | d << 8 | e << ((MPI.length -2)*8) | f ((MPI.length -2)*8)
|
||||
|
||||
/**
|
||||
* Implementation of type MPI ({@link https://tools.ietf.org/html/rfc4880#section-3.2|RFC4880 3.2})<br/>
|
||||
* <br/>
|
||||
* Implementation of type MPI ({@link https://tools.ietf.org/html/rfc4880#section-3.2|RFC4880 3.2})
|
||||
* Multiprecision integers (also called MPIs) are unsigned integers used
|
||||
* to hold large integers such as the ones used in cryptographic
|
||||
* calculations.
|
||||
|
@ -67,7 +66,7 @@ MPI.prototype.read = function (bytes, endian='be') {
|
|||
}
|
||||
|
||||
const bits = (bytes[0] << 8) | bytes[1];
|
||||
const bytelen = Math.ceil(bits / 8);
|
||||
const bytelen = (bits + 7) >>> 3;
|
||||
const payload = bytes.subarray(2, 2 + bytelen);
|
||||
|
||||
if (endian === 'le') {
|
||||
|
|
Loading…
Reference in New Issue
Block a user