Now the bundle can be mangled. Multi-threaded uses all CPUs but 1. Readme improvements
This commit is contained in:
parent
e945922b8b
commit
d2a21a818f
195
README.md
195
README.md
|
@ -16,9 +16,9 @@ bigint-crypto-utils can be imported to your project with `npm`:
|
||||||
npm install bigint-crypto-utils
|
npm install bigint-crypto-utils
|
||||||
```
|
```
|
||||||
|
|
||||||
NPM installation defaults to the minified ES6 module for browsers and the CJS one for Node.js.
|
NPM installation defaults to the ES6 module for browsers and the CJS one for Node.js.
|
||||||
|
|
||||||
For web browsers, you can also directly download the [IIFE file](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.mod.js) from GitHub.
|
For web browsers, you can also directly download the [IIFE bundle](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.js) or the [ES6 bundle module](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.mod.js) from GitHub.
|
||||||
|
|
||||||
## Usage examples
|
## Usage examples
|
||||||
|
|
||||||
|
@ -29,26 +29,25 @@ Import your module as :
|
||||||
const bigintCryptoUtils = require('bigint-crypto-utils')
|
const bigintCryptoUtils = require('bigint-crypto-utils')
|
||||||
... // your code here
|
... // your code here
|
||||||
```
|
```
|
||||||
- Javascript native project
|
- JavaScript native project
|
||||||
```javascript
|
```javascript
|
||||||
import * as bigintCryptoUtils from 'bigint-crypto-utils'
|
import * as bigintCryptoUtils from 'bigint-crypto-utils'
|
||||||
... // your code here
|
... // your code here
|
||||||
```
|
```
|
||||||
- Javascript native browser ES6 mod
|
- JavaScript native browser ES6 mod
|
||||||
```html
|
```html
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import * as bigintCryptoUtils from 'lib/index.browser.bundle.mod.js' // Use you actual path to the broser mod bundle
|
import * as bigintCryptoUtils from 'lib/index.browser.bundle.mod.js' // Use you actual path to the broser mod bundle
|
||||||
... // your code here
|
... // your code here
|
||||||
</script>
|
</script>
|
||||||
import as bcu from 'bigint-crypto-utils'
|
|
||||||
... // your code here
|
|
||||||
```
|
```
|
||||||
- Javascript native browser IIFE
|
- JavaScript native browser IIFE
|
||||||
```html
|
```html
|
||||||
<script src="../../lib/index.browser.bundle.js"></script>
|
<script src="../../lib/index.browser.bundle.js"></script> <!-- Use you actual path to the browser bundle -->
|
||||||
<script>
|
<script>
|
||||||
... // your code here
|
... // your code here
|
||||||
</script>
|
</script>
|
||||||
|
```
|
||||||
- TypeScript
|
- TypeScript
|
||||||
```typescript
|
```typescript
|
||||||
import * as bigintCryptoUtils from 'bigint-crypto-utils'
|
import * as bigintCryptoUtils from 'bigint-crypto-utils'
|
||||||
|
@ -56,6 +55,8 @@ Import your module as :
|
||||||
```
|
```
|
||||||
> BigInt is [ES-2020](https://tc39.es/ecma262/#sec-bigint-objects). In order to use it with TypeScript you should set `lib` (and probably also `target` and `module`) to `esnext` in `tsconfig.json`.
|
> BigInt is [ES-2020](https://tc39.es/ecma262/#sec-bigint-objects). In order to use it with TypeScript you should set `lib` (and probably also `target` and `module`) to `esnext` in `tsconfig.json`.
|
||||||
|
|
||||||
|
And you could use it like in the following:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
/* Stage 3 BigInts with value 666 can be declared as BigInt('666')
|
/* Stage 3 BigInts with value 666 can be declared as BigInt('666')
|
||||||
or the shorter new no-so-linter-friendly syntax 666n.
|
or the shorter new no-so-linter-friendly syntax 666n.
|
||||||
|
@ -65,22 +66,22 @@ be raised.
|
||||||
*/
|
*/
|
||||||
const a = BigInt('5')
|
const a = BigInt('5')
|
||||||
const b = BigInt('2')
|
const b = BigInt('2')
|
||||||
const n = BigInt('19')
|
const n = 19n
|
||||||
|
|
||||||
console.log(bigintCryptoUtils.modPow(a, b, n)) // prints 6
|
console.log(bigintCryptoUtils.modPow(a, b, n)) // prints 6
|
||||||
|
|
||||||
console.log(bigintCryptoUtils.modInv(BigInt('2'), BigInt('5'))) // prints 3
|
console.log(bigintCryptoUtils.modInv(2n, 5n)) // prints 3
|
||||||
|
|
||||||
console.log(bigintCryptoUtils.modInv(BigInt('3'), BigInt('5'))) // prints 2
|
console.log(bigintCryptoUtils.modInv(BigInt('3'), BigInt('5'))) // prints 2
|
||||||
|
|
||||||
console.log(bigintCryptoUtils.randBetween(BigInt(2) ** BigInt(256))) // Prints a cryptographically secure random number between 1 and 2**256 bits.
|
console.log(bigintCryptoUtils.randBetween(2n ** 256n)) // Prints a cryptographically secure random number between 1 and 2**256 bits.
|
||||||
|
|
||||||
async function primeTesting () {
|
async function primeTesting () {
|
||||||
// Output of a probable prime of 2048 bits
|
// Output of a probable prime of 2048 bits
|
||||||
console.log(await bigintCryptoUtils.prime(2048))
|
console.log(await bigintCryptoUtils.prime(2048))
|
||||||
|
|
||||||
// Testing if a number is a probable prime (Miller-Rabin)
|
// Testing if a number is a probable prime (Miller-Rabin)
|
||||||
const number = 27
|
const number = 27n
|
||||||
const isPrime = await bigintCryptoUtils.isProbablyPrime(number)
|
const isPrime = await bigintCryptoUtils.isProbablyPrime(number)
|
||||||
if (isPrime) {
|
if (isPrime) {
|
||||||
console.log(`${number} is prime`)
|
console.log(`${number} is prime`)
|
||||||
|
@ -93,78 +94,7 @@ primeTesting()
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## bigint-crypto-utils JS Doc
|
## API reference documentation
|
||||||
|
|
||||||
### Functions
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt><a href="#abs">abs(a)</a> ⇒ <code>bigint</code></dt>
|
|
||||||
<dd><p>Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#bitLength">bitLength(a)</a> ⇒ <code>number</code></dt>
|
|
||||||
<dd><p>Returns the bitlength of a number</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#eGcd">eGcd(a, b)</a> ⇒ <code><a href="#egcdReturn">egcdReturn</a></code></dt>
|
|
||||||
<dd><p>An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm.
|
|
||||||
Take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#gcd">gcd(a, b)</a> ⇒ <code>bigint</code></dt>
|
|
||||||
<dd><p>Greatest-common divisor of two integers based on the iterative binary algorithm.</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#isProbablyPrime">isProbablyPrime(w, [iterations])</a> ⇒ <code>Promise</code></dt>
|
|
||||||
<dd><p>The test first tries if any of the first 250 small primes are a factor of the input number and then passes several
|
|
||||||
iterations of Miller-Rabin Probabilistic Primality Test (FIPS 186-4 C.3.1)</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#lcm">lcm(a, b)</a> ⇒ <code>bigint</code></dt>
|
|
||||||
<dd><p>The least common multiple computed as abs(a*b)/gcd(a,b)</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#max">max(a, b)</a> ⇒ <code>bigint</code></dt>
|
|
||||||
<dd><p>Maximum. max(a,b)==a if a>=b. max(a,b)==b if a<=b</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#min">min(a, b)</a> ⇒ <code>bigint</code></dt>
|
|
||||||
<dd><p>Minimum. min(a,b)==b if a>=b. min(a,b)==a if a<=b</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#modInv">modInv(a, n)</a> ⇒ <code>bigint</code></dt>
|
|
||||||
<dd><p>Modular inverse.</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#modPow">modPow(b, e, n)</a> ⇒ <code>bigint</code></dt>
|
|
||||||
<dd><p>Modular exponentiation b**e mod n. Currently using the right-to-left binary method</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#prime">prime(bitLength, [iterations])</a> ⇒ <code>Promise</code></dt>
|
|
||||||
<dd><p>A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
|
||||||
The browser version uses web workers to parallelise prime look up. Therefore, it does not lock the UI
|
|
||||||
main process, and it can be much faster (if several cores or cpu are available).
|
|
||||||
The node version can also use worker_threads if they are available (enabled by default with Node 11 and
|
|
||||||
and can be enabled at runtime executing node --experimental-worker with node >=10.5.0).</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#primeSync">primeSync(bitLength, [iterations])</a> ⇒ <code>bigint</code></dt>
|
|
||||||
<dd><p>A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
|
||||||
The sync version is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript. Please consider using prime() instead.</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#randBetween">randBetween(max, [min])</a> ⇒ <code>bigint</code></dt>
|
|
||||||
<dd><p>Returns a cryptographically secure random integer between [min,max]</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#randBits">randBits(bitLength, [forceLength])</a> ⇒ <code>Buffer</code> | <code>Uint8Array</code></dt>
|
|
||||||
<dd><p>Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#randBytes">randBytes(byteLength, [forceLength])</a> ⇒ <code>Promise</code></dt>
|
|
||||||
<dd><p>Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#randBytesSync">randBytesSync(byteLength, [forceLength])</a> ⇒ <code>Buffer</code> | <code>Uint8Array</code></dt>
|
|
||||||
<dd><p>Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()</p>
|
|
||||||
</dd>
|
|
||||||
<dt><a href="#toZn">toZn(a, n)</a> ⇒ <code>bigint</code></dt>
|
|
||||||
<dd><p>Finds the smallest positive element that is congruent to a in modulo n</p>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
### Typedefs
|
|
||||||
|
|
||||||
<dl>
|
|
||||||
<dt><a href="#egcdReturn">egcdReturn</a> : <code>Object</code></dt>
|
|
||||||
<dd><p>A triple (g, x, y), such that ax + by = g = gcd(a, b).</p>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<a name="abs"></a>
|
<a name="abs"></a>
|
||||||
|
|
||||||
|
@ -217,20 +147,6 @@ Greatest-common divisor of two integers based on the iterative binary algorithm.
|
||||||
| a | <code>number</code> \| <code>bigint</code> |
|
| a | <code>number</code> \| <code>bigint</code> |
|
||||||
| b | <code>number</code> \| <code>bigint</code> |
|
| b | <code>number</code> \| <code>bigint</code> |
|
||||||
|
|
||||||
<a name="isProbablyPrime"></a>
|
|
||||||
|
|
||||||
### isProbablyPrime(w, [iterations]) ⇒ <code>Promise</code>
|
|
||||||
The test first tries if any of the first 250 small primes are a factor of the input number and then passes several
|
|
||||||
iterations of Miller-Rabin Probabilistic Primality Test (FIPS 186-4 C.3.1)
|
|
||||||
|
|
||||||
**Kind**: global function
|
|
||||||
**Returns**: <code>Promise</code> - A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
|
|
||||||
|
|
||||||
| Param | Type | Default | Description |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| w | <code>number</code> \| <code>bigint</code> | | An integer to be tested for primality |
|
|
||||||
| [iterations] | <code>number</code> | <code>16</code> | The number of iterations for the primality test. The value shall be consistent with Table C.1, C.2 or C.3 |
|
|
||||||
|
|
||||||
<a name="lcm"></a>
|
<a name="lcm"></a>
|
||||||
|
|
||||||
### lcm(a, b) ⇒ <code>bigint</code>
|
### lcm(a, b) ⇒ <code>bigint</code>
|
||||||
|
@ -297,89 +213,6 @@ Modular exponentiation b**e mod n. Currently using the right-to-left binary meth
|
||||||
| e | <code>number</code> \| <code>bigint</code> | exponent |
|
| e | <code>number</code> \| <code>bigint</code> | exponent |
|
||||||
| n | <code>number</code> \| <code>bigint</code> | modulo |
|
| n | <code>number</code> \| <code>bigint</code> | modulo |
|
||||||
|
|
||||||
<a name="prime"></a>
|
|
||||||
|
|
||||||
### prime(bitLength, [iterations]) ⇒ <code>Promise</code>
|
|
||||||
A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
|
||||||
The browser version uses web workers to parallelise prime look up. Therefore, it does not lock the UI
|
|
||||||
main process, and it can be much faster (if several cores or cpu are available).
|
|
||||||
The node version can also use worker_threads if they are available (enabled by default with Node 11 and
|
|
||||||
and can be enabled at runtime executing node --experimental-worker with node >=10.5.0).
|
|
||||||
|
|
||||||
**Kind**: global function
|
|
||||||
**Returns**: <code>Promise</code> - A promise that resolves to a bigint probable prime of bitLength bits.
|
|
||||||
|
|
||||||
| Param | Type | Default | Description |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| bitLength | <code>number</code> | | The required bit length for the generated prime |
|
|
||||||
| [iterations] | <code>number</code> | <code>16</code> | The number of iterations for the Miller-Rabin Probabilistic Primality Test |
|
|
||||||
|
|
||||||
<a name="primeSync"></a>
|
|
||||||
|
|
||||||
### primeSync(bitLength, [iterations]) ⇒ <code>bigint</code>
|
|
||||||
A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
|
||||||
The sync version is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript. Please consider using prime() instead.
|
|
||||||
|
|
||||||
**Kind**: global function
|
|
||||||
**Returns**: <code>bigint</code> - A bigint probable prime of bitLength bits.
|
|
||||||
|
|
||||||
| Param | Type | Default | Description |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| bitLength | <code>number</code> | | The required bit length for the generated prime |
|
|
||||||
| [iterations] | <code>number</code> | <code>16</code> | The number of iterations for the Miller-Rabin Probabilistic Primality Test |
|
|
||||||
|
|
||||||
<a name="randBetween"></a>
|
|
||||||
|
|
||||||
### randBetween(max, [min]) ⇒ <code>bigint</code>
|
|
||||||
Returns a cryptographically secure random integer between [min,max]
|
|
||||||
|
|
||||||
**Kind**: global function
|
|
||||||
**Returns**: <code>bigint</code> - A cryptographically secure random bigint between [min,max]
|
|
||||||
|
|
||||||
| Param | Type | Default | Description |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| max | <code>bigint</code> | | Returned value will be <= max |
|
|
||||||
| [min] | <code>bigint</code> | <code>BigInt(1)</code> | Returned value will be >= min |
|
|
||||||
|
|
||||||
<a name="randBits"></a>
|
|
||||||
|
|
||||||
### randBits(bitLength, [forceLength]) ⇒ <code>Buffer</code> \| <code>Uint8Array</code>
|
|
||||||
Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
|
|
||||||
|
|
||||||
**Kind**: global function
|
|
||||||
**Returns**: <code>Buffer</code> \| <code>Uint8Array</code> - A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
|
|
||||||
|
|
||||||
| Param | Type | Default | Description |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| bitLength | <code>number</code> | | The desired number of random bits |
|
|
||||||
| [forceLength] | <code>boolean</code> | <code>false</code> | If we want to force the output to have a specific bit length. It basically forces the msb to be 1 |
|
|
||||||
|
|
||||||
<a name="randBytes"></a>
|
|
||||||
|
|
||||||
### randBytes(byteLength, [forceLength]) ⇒ <code>Promise</code>
|
|
||||||
Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
|
|
||||||
|
|
||||||
**Kind**: global function
|
|
||||||
**Returns**: <code>Promise</code> - A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
|
||||||
|
|
||||||
| Param | Type | Default | Description |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| byteLength | <code>number</code> | | The desired number of random bytes |
|
|
||||||
| [forceLength] | <code>boolean</code> | <code>false</code> | If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1 |
|
|
||||||
|
|
||||||
<a name="randBytesSync"></a>
|
|
||||||
|
|
||||||
### randBytesSync(byteLength, [forceLength]) ⇒ <code>Buffer</code> \| <code>Uint8Array</code>
|
|
||||||
Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
|
|
||||||
|
|
||||||
**Kind**: global function
|
|
||||||
**Returns**: <code>Buffer</code> \| <code>Uint8Array</code> - A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
|
||||||
|
|
||||||
| Param | Type | Default | Description |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| byteLength | <code>number</code> | | The desired number of random bytes |
|
|
||||||
| [forceLength] | <code>boolean</code> | <code>false</code> | If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1 |
|
|
||||||
|
|
||||||
<a name="toZn"></a>
|
<a name="toZn"></a>
|
||||||
|
|
||||||
### toZn(a, n) ⇒ <code>bigint</code>
|
### toZn(a, n) ⇒ <code>bigint</code>
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const fs = require('fs')
|
||||||
|
const jsdoc2md = require('jsdoc-to-markdown')
|
||||||
|
const path = require('path')
|
||||||
|
const pkgJson = require('../package.json')
|
||||||
|
|
||||||
|
const rootDir = path.join(__dirname, '..')
|
||||||
|
|
||||||
|
const template = path.join(rootDir, pkgJson.directories.src, 'doc', 'readme-template.md')
|
||||||
|
const input = path.join(rootDir, pkgJson.directories.lib, 'index.node.js')
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
source: fs.readFileSync(input, { encoding: 'UTF-8' }), // we need to use this instead of files in order to avoid issues with esnext features
|
||||||
|
template: fs.readFileSync(template, { encoding: 'UTF-8' }),
|
||||||
|
'heading-depth': 3, // The initial heading depth. For example, with a value of 2 the top-level markdown headings look like "## The heading"
|
||||||
|
'global-index-format': 'none' // none, grouped, table, dl.
|
||||||
|
}
|
||||||
|
|
||||||
|
const readmeContents = jsdoc2md.renderSync(options)
|
||||||
|
|
||||||
|
const readmeFile = path.join(rootDir, 'README.md')
|
||||||
|
|
||||||
|
fs.writeFileSync(readmeFile, readmeContents)
|
|
@ -37,8 +37,8 @@ module.exports = [
|
||||||
replace({
|
replace({
|
||||||
'process.browser': true
|
'process.browser': true
|
||||||
})
|
})
|
||||||
]
|
],
|
||||||
// external: ['bigint-crypto-utils']
|
external: ['bigint-mod-arith']
|
||||||
},
|
},
|
||||||
{ // Browser bundles
|
{ // Browser bundles
|
||||||
input: input,
|
input: input,
|
||||||
|
@ -61,8 +61,8 @@ module.exports = [
|
||||||
browser: true
|
browser: true
|
||||||
}),
|
}),
|
||||||
terser({
|
terser({
|
||||||
mangle: false,
|
// mangle: false,
|
||||||
compress: false
|
// compress: false
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -76,7 +76,7 @@ module.exports = [
|
||||||
output: {
|
output: {
|
||||||
file: path.join(dstDir, 'index.node.js'),
|
file: path.join(dstDir, 'index.node.js'),
|
||||||
format: 'cjs'
|
format: 'cjs'
|
||||||
}
|
},
|
||||||
// external: ['bigint-crypto-utils']
|
external: ['bigint-mod-arith']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,121 +1,14 @@
|
||||||
const _ZERO = BigInt(0)
|
import { bitLength, eGcd, modInv, modPow, toZn } from 'bigint-mod-arith'
|
||||||
const _ONE = BigInt(1)
|
export { abs, bitLength, eGcd, gcd, lcm, max, min, modInv, modPow, toZn } from 'bigint-mod-arith'
|
||||||
const _TWO = BigInt(2)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
*
|
|
||||||
* @returns {bigint} the absolute value of a
|
|
||||||
*/
|
|
||||||
function abs (a) {
|
|
||||||
a = BigInt(a)
|
|
||||||
return (a >= _ZERO) ? a : -a
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the bitlength of a number
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @returns {number} - the bit length
|
|
||||||
*/
|
|
||||||
function bitLength (a) {
|
|
||||||
a = BigInt(a)
|
|
||||||
if (a === _ONE) { return 1 }
|
|
||||||
let bits = 1
|
|
||||||
do {
|
|
||||||
bits++
|
|
||||||
} while ((a >>= _ONE) > _ONE)
|
|
||||||
return bits
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} egcdReturn A triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
* @property {bigint} g
|
|
||||||
* @property {bigint} x
|
|
||||||
* @property {bigint} y
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm.
|
|
||||||
* Take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {egcdReturn} A triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
*/
|
|
||||||
function eGcd (a, b) {
|
|
||||||
a = BigInt(a)
|
|
||||||
b = BigInt(b)
|
|
||||||
if (a <= _ZERO | b <= _ZERO) { return NaN } // a and b MUST be positive
|
|
||||||
|
|
||||||
let x = _ZERO
|
|
||||||
let y = _ONE
|
|
||||||
let u = _ONE
|
|
||||||
let v = _ZERO
|
|
||||||
|
|
||||||
while (a !== _ZERO) {
|
|
||||||
const q = b / a
|
|
||||||
const r = b % a
|
|
||||||
const m = x - (u * q)
|
|
||||||
const n = y - (v * q)
|
|
||||||
b = a
|
|
||||||
a = r
|
|
||||||
x = u
|
|
||||||
y = v
|
|
||||||
u = m
|
|
||||||
v = n
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
b: b,
|
|
||||||
x: x,
|
|
||||||
y: y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Greatest-common divisor of two integers based on the iterative binary algorithm.
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} The greatest common divisor of a and b
|
|
||||||
*/
|
|
||||||
function gcd (a, b) {
|
|
||||||
a = abs(a)
|
|
||||||
b = abs(b)
|
|
||||||
if (a === _ZERO) { return b } else if (b === _ZERO) { return a }
|
|
||||||
|
|
||||||
let shift = _ZERO
|
|
||||||
while (!((a | b) & _ONE)) {
|
|
||||||
a >>= _ONE
|
|
||||||
b >>= _ONE
|
|
||||||
shift++
|
|
||||||
}
|
|
||||||
while (!(a & _ONE)) a >>= _ONE
|
|
||||||
do {
|
|
||||||
while (!(b & _ONE)) b >>= _ONE
|
|
||||||
if (a > b) {
|
|
||||||
const x = a
|
|
||||||
a = b
|
|
||||||
b = x
|
|
||||||
}
|
|
||||||
b -= a
|
|
||||||
} while (b)
|
|
||||||
|
|
||||||
// rescale
|
|
||||||
return a << shift
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The test first tries if any of the first 250 small primes are a factor of the input number and then passes several
|
* The test first tries if any of the first 250 small primes are a factor of the input number and then passes several
|
||||||
* iterations of Miller-Rabin Probabilistic Primality Test (FIPS 186-4 C.3.1)
|
* iterations of Miller-Rabin Probabilistic Primality Test (FIPS 186-4 C.3.1)
|
||||||
*
|
*
|
||||||
* @param {number|bigint} w An integer to be tested for primality
|
* @param {number | bigint} w An integer to be tested for primality
|
||||||
* @param {number} [iterations = 16] The number of iterations for the primality test. The value shall be consistent with Table C.1, C.2 or C.3
|
* @param {number} [iterations = 16] The number of iterations for the primality test. The value shall be consistent with Table C.1, C.2 or C.3
|
||||||
*
|
*
|
||||||
* @return {Promise} A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
|
* @return {Promise<boolean>} A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
|
||||||
*/
|
*/
|
||||||
async function isProbablyPrime (w, iterations = 16) {
|
async function isProbablyPrime (w, iterations = 16) {
|
||||||
if (typeof w === 'number') {
|
if (typeof w === 'number') {
|
||||||
|
@ -145,96 +38,6 @@ async function isProbablyPrime (w, iterations = 16) {
|
||||||
/* eslint-enable no-lone-blocks */
|
/* eslint-enable no-lone-blocks */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The least common multiple computed as abs(a*b)/gcd(a,b)
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} The least common multiple of a and b
|
|
||||||
*/
|
|
||||||
function lcm (a, b) {
|
|
||||||
a = BigInt(a)
|
|
||||||
b = BigInt(b)
|
|
||||||
if (a === _ZERO && b === _ZERO) { return _ZERO }
|
|
||||||
return abs(a * b) / gcd(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum. max(a,b)==a if a>=b. max(a,b)==b if a<=b
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} maximum of numbers a and b
|
|
||||||
*/
|
|
||||||
function max (a, b) {
|
|
||||||
a = BigInt(a)
|
|
||||||
b = BigInt(b)
|
|
||||||
return (a >= b) ? a : b
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimum. min(a,b)==b if a>=b. min(a,b)==a if a<=b
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} minimum of numbers a and b
|
|
||||||
*/
|
|
||||||
function min (a, b) {
|
|
||||||
a = BigInt(a)
|
|
||||||
b = BigInt(b)
|
|
||||||
return (a >= b) ? b : a
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modular inverse.
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a The number to find an inverse for
|
|
||||||
* @param {number|bigint} n The modulo
|
|
||||||
*
|
|
||||||
* @returns {bigint} the inverse modulo n or NaN if it does not exist
|
|
||||||
*/
|
|
||||||
function modInv (a, n) {
|
|
||||||
const egcd = eGcd(toZn(a, n), n)
|
|
||||||
if (egcd.b !== _ONE) {
|
|
||||||
return NaN // modular inverse does not exist
|
|
||||||
} else {
|
|
||||||
return toZn(egcd.x, n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modular exponentiation b**e mod n. Currently using the right-to-left binary method
|
|
||||||
*
|
|
||||||
* @param {number|bigint} b base
|
|
||||||
* @param {number|bigint} e exponent
|
|
||||||
* @param {number|bigint} n modulo
|
|
||||||
*
|
|
||||||
* @returns {bigint} b**e mod n
|
|
||||||
*/
|
|
||||||
function modPow (b, e, n) {
|
|
||||||
n = BigInt(n)
|
|
||||||
if (n === _ZERO) { return NaN } else if (n === _ONE) { return _ZERO }
|
|
||||||
|
|
||||||
b = toZn(b, n)
|
|
||||||
|
|
||||||
e = BigInt(e)
|
|
||||||
if (e < _ZERO) {
|
|
||||||
return modInv(modPow(b, abs(e), n), n)
|
|
||||||
}
|
|
||||||
|
|
||||||
let r = _ONE
|
|
||||||
while (e > 0) {
|
|
||||||
if ((e % _TWO) === _ONE) {
|
|
||||||
r = (r * b) % n
|
|
||||||
}
|
|
||||||
e = e / _TWO
|
|
||||||
b = b ** _TWO % n
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
||||||
* The browser version uses web workers to parallelise prime look up. Therefore, it does not lock the UI
|
* The browser version uses web workers to parallelise prime look up. Therefore, it does not lock the UI
|
||||||
|
@ -245,7 +48,7 @@ function modPow (b, e, n) {
|
||||||
* @param {number} bitLength The required bit length for the generated prime
|
* @param {number} bitLength The required bit length for the generated prime
|
||||||
* @param {number} [iterations = 16] The number of iterations for the Miller-Rabin Probabilistic Primality Test
|
* @param {number} [iterations = 16] The number of iterations for the Miller-Rabin Probabilistic Primality Test
|
||||||
*
|
*
|
||||||
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits.
|
* @returns {Promise<bigint>} A promise that resolves to a bigint probable prime of bitLength bits.
|
||||||
*/
|
*/
|
||||||
function prime (bitLength, iterations = 16) {
|
function prime (bitLength, iterations = 16) {
|
||||||
if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) }
|
if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) }
|
||||||
|
@ -278,7 +81,7 @@ function prime (bitLength, iterations = 16) {
|
||||||
/* eslint-disable no-lone-blocks */
|
/* eslint-disable no-lone-blocks */
|
||||||
{ // browser
|
{ // browser
|
||||||
const workerURL = _isProbablyPrimeWorkerUrl()
|
const workerURL = _isProbablyPrimeWorkerUrl()
|
||||||
for (let i = 0; i < self.navigator.hardwareConcurrency; i++) {
|
for (let i = 0; i < self.navigator.hardwareConcurrency - 1; i++) {
|
||||||
const newWorker = new Worker(workerURL)
|
const newWorker = new Worker(workerURL)
|
||||||
newWorker.onmessage = (event) => _onmessage(event.data, newWorker)
|
newWorker.onmessage = (event) => _onmessage(event.data, newWorker)
|
||||||
workerList.push(newWorker)
|
workerList.push(newWorker)
|
||||||
|
@ -308,7 +111,7 @@ function prime (bitLength, iterations = 16) {
|
||||||
*/
|
*/
|
||||||
function primeSync (bitLength, iterations = 16) {
|
function primeSync (bitLength, iterations = 16) {
|
||||||
if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) }
|
if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) }
|
||||||
let rnd = _ZERO
|
let rnd = 0n
|
||||||
do {
|
do {
|
||||||
rnd = fromBuffer(randBytesSync(bitLength / 8, true))
|
rnd = fromBuffer(randBytesSync(bitLength / 8, true))
|
||||||
} while (!_isProbablyPrime(rnd, iterations))
|
} while (!_isProbablyPrime(rnd, iterations))
|
||||||
|
@ -322,7 +125,7 @@ function primeSync (bitLength, iterations = 16) {
|
||||||
*
|
*
|
||||||
* @returns {bigint} A cryptographically secure random bigint between [min,max]
|
* @returns {bigint} A cryptographically secure random bigint between [min,max]
|
||||||
*/
|
*/
|
||||||
function randBetween (max, min = _ONE) {
|
function randBetween (max, min = 1n) {
|
||||||
if (max <= min) throw new Error('max must be > min')
|
if (max <= min) throw new Error('max must be > min')
|
||||||
const interval = max - min
|
const interval = max - min
|
||||||
const bitLen = bitLength(interval)
|
const bitLen = bitLength(interval)
|
||||||
|
@ -340,7 +143,7 @@ function randBetween (max, min = _ONE) {
|
||||||
* @param {number} bitLength The desired number of random bits
|
* @param {number} bitLength The desired number of random bits
|
||||||
* @param {boolean} [forceLength = false] If we want to force the output to have a specific bit length. It basically forces the msb to be 1
|
* @param {boolean} [forceLength = false] If we want to force the output to have a specific bit length. It basically forces the msb to be 1
|
||||||
*
|
*
|
||||||
* @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
|
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
|
||||||
*/
|
*/
|
||||||
function randBits (bitLength, forceLength = false) {
|
function randBits (bitLength, forceLength = false) {
|
||||||
if (bitLength < 1) {
|
if (bitLength < 1) {
|
||||||
|
@ -367,7 +170,7 @@ function randBits (bitLength, forceLength = false) {
|
||||||
* @param {number} byteLength The desired number of random bytes
|
* @param {number} byteLength The desired number of random bytes
|
||||||
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
||||||
*
|
*
|
||||||
* @returns {Promise} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
* @returns {Promise<Buffer | Uint8Array>} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
||||||
*/
|
*/
|
||||||
function randBytes (byteLength, forceLength = false) {
|
function randBytes (byteLength, forceLength = false) {
|
||||||
if (byteLength < 1) { throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`) }
|
if (byteLength < 1) { throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`) }
|
||||||
|
@ -392,7 +195,7 @@ function randBytes (byteLength, forceLength = false) {
|
||||||
* @param {number} byteLength The desired number of random bytes
|
* @param {number} byteLength The desired number of random bytes
|
||||||
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
||||||
*
|
*
|
||||||
* @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
||||||
*/
|
*/
|
||||||
function randBytesSync (byteLength, forceLength = false) {
|
function randBytesSync (byteLength, forceLength = false) {
|
||||||
if (byteLength < 1) { throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`) }
|
if (byteLength < 1) { throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`) }
|
||||||
|
@ -407,25 +210,10 @@ function randBytesSync (byteLength, forceLength = false) {
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the smallest positive element that is congruent to a in modulo n
|
|
||||||
* @param {number|bigint} a An integer
|
|
||||||
* @param {number|bigint} n The modulo
|
|
||||||
*
|
|
||||||
* @returns {bigint} The smallest positive representation of a in modulo n
|
|
||||||
*/
|
|
||||||
function toZn (a, n) {
|
|
||||||
n = BigInt(n)
|
|
||||||
if (n <= 0) { return NaN }
|
|
||||||
|
|
||||||
a = BigInt(a) % n
|
|
||||||
return (a < 0) ? a + n : a
|
|
||||||
}
|
|
||||||
|
|
||||||
/* HELPER FUNCTIONS */
|
/* HELPER FUNCTIONS */
|
||||||
|
|
||||||
function fromBuffer (buf) {
|
function fromBuffer (buf) {
|
||||||
let ret = _ZERO
|
let ret = 0n
|
||||||
for (const i of buf.values()) {
|
for (const i of buf.values()) {
|
||||||
const bi = BigInt(i)
|
const bi = BigInt(i)
|
||||||
ret = (ret << BigInt(8)) + bi
|
ret = (ret << BigInt(8)) + bi
|
||||||
|
@ -435,7 +223,7 @@ function fromBuffer (buf) {
|
||||||
|
|
||||||
function _isProbablyPrimeWorkerUrl () {
|
function _isProbablyPrimeWorkerUrl () {
|
||||||
// Let's us first add all the required functions
|
// Let's us first add all the required functions
|
||||||
let workerCode = `'use strict';const _ZERO = BigInt(0);const _ONE = BigInt(1);const _TWO = BigInt(2);const eGcd = ${eGcd.toString()};const modInv = ${modInv.toString()};const modPow = ${modPow.toString()};const toZn = ${toZn.toString()};const randBits = ${randBits.toString()};const randBytesSync = ${randBytesSync.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`
|
let workerCode = `'use strict';const ${eGcd.name}=${eGcd.toString()};const ${modInv.name}=${modInv.toString()};const ${modPow.name}=${modPow.toString()};const ${toZn.name}=${toZn.toString()};const ${randBits.name}=${randBits.toString()};const ${randBytesSync.name}=${randBytesSync.toString()};const ${randBetween.name}=${randBetween.toString()};const ${isProbablyPrime.name}=${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`
|
||||||
|
|
||||||
const onmessage = async function (event) { // Let's start once we are called
|
const onmessage = async function (event) { // Let's start once we are called
|
||||||
// event.data = {rnd: <bigint>, iterations: <number>}
|
// event.data = {rnd: <bigint>, iterations: <number>}
|
||||||
|
@ -463,269 +251,269 @@ function _isProbablyPrime (w, iterations = 16) {
|
||||||
PREFILTERING. Even values but 2 are not primes, so don't test.
|
PREFILTERING. Even values but 2 are not primes, so don't test.
|
||||||
1 is not a prime and the M-R algorithm needs w>1.
|
1 is not a prime and the M-R algorithm needs w>1.
|
||||||
*/
|
*/
|
||||||
if (w === _TWO) { return true } else if ((w & _ONE) === _ZERO || w === _ONE) { return false }
|
if (w === 2n) { return true } else if ((w & 1n) === 0n || w === 1n) { return false }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test if any of the first 250 small primes are a factor of w. 2 is not tested because it was already tested above.
|
Test if any of the first 250 small primes are a factor of w. 2 is not tested because it was already tested above.
|
||||||
*/
|
*/
|
||||||
const firstPrimes = [
|
const firstPrimes = [
|
||||||
3,
|
3n,
|
||||||
5,
|
5n,
|
||||||
7,
|
7n,
|
||||||
11,
|
11n,
|
||||||
13,
|
13n,
|
||||||
17,
|
17n,
|
||||||
19,
|
19n,
|
||||||
23,
|
23n,
|
||||||
29,
|
29n,
|
||||||
31,
|
31n,
|
||||||
37,
|
37n,
|
||||||
41,
|
41n,
|
||||||
43,
|
43n,
|
||||||
47,
|
47n,
|
||||||
53,
|
53n,
|
||||||
59,
|
59n,
|
||||||
61,
|
61n,
|
||||||
67,
|
67n,
|
||||||
71,
|
71n,
|
||||||
73,
|
73n,
|
||||||
79,
|
79n,
|
||||||
83,
|
83n,
|
||||||
89,
|
89n,
|
||||||
97,
|
97n,
|
||||||
101,
|
101n,
|
||||||
103,
|
103n,
|
||||||
107,
|
107n,
|
||||||
109,
|
109n,
|
||||||
113,
|
113n,
|
||||||
127,
|
127n,
|
||||||
131,
|
131n,
|
||||||
137,
|
137n,
|
||||||
139,
|
139n,
|
||||||
149,
|
149n,
|
||||||
151,
|
151n,
|
||||||
157,
|
157n,
|
||||||
163,
|
163n,
|
||||||
167,
|
167n,
|
||||||
173,
|
173n,
|
||||||
179,
|
179n,
|
||||||
181,
|
181n,
|
||||||
191,
|
191n,
|
||||||
193,
|
193n,
|
||||||
197,
|
197n,
|
||||||
199,
|
199n,
|
||||||
211,
|
211n,
|
||||||
223,
|
223n,
|
||||||
227,
|
227n,
|
||||||
229,
|
229n,
|
||||||
233,
|
233n,
|
||||||
239,
|
239n,
|
||||||
241,
|
241n,
|
||||||
251,
|
251n,
|
||||||
257,
|
257n,
|
||||||
263,
|
263n,
|
||||||
269,
|
269n,
|
||||||
271,
|
271n,
|
||||||
277,
|
277n,
|
||||||
281,
|
281n,
|
||||||
283,
|
283n,
|
||||||
293,
|
293n,
|
||||||
307,
|
307n,
|
||||||
311,
|
311n,
|
||||||
313,
|
313n,
|
||||||
317,
|
317n,
|
||||||
331,
|
331n,
|
||||||
337,
|
337n,
|
||||||
347,
|
347n,
|
||||||
349,
|
349n,
|
||||||
353,
|
353n,
|
||||||
359,
|
359n,
|
||||||
367,
|
367n,
|
||||||
373,
|
373n,
|
||||||
379,
|
379n,
|
||||||
383,
|
383n,
|
||||||
389,
|
389n,
|
||||||
397,
|
397n,
|
||||||
401,
|
401n,
|
||||||
409,
|
409n,
|
||||||
419,
|
419n,
|
||||||
421,
|
421n,
|
||||||
431,
|
431n,
|
||||||
433,
|
433n,
|
||||||
439,
|
439n,
|
||||||
443,
|
443n,
|
||||||
449,
|
449n,
|
||||||
457,
|
457n,
|
||||||
461,
|
461n,
|
||||||
463,
|
463n,
|
||||||
467,
|
467n,
|
||||||
479,
|
479n,
|
||||||
487,
|
487n,
|
||||||
491,
|
491n,
|
||||||
499,
|
499n,
|
||||||
503,
|
503n,
|
||||||
509,
|
509n,
|
||||||
521,
|
521n,
|
||||||
523,
|
523n,
|
||||||
541,
|
541n,
|
||||||
547,
|
547n,
|
||||||
557,
|
557n,
|
||||||
563,
|
563n,
|
||||||
569,
|
569n,
|
||||||
571,
|
571n,
|
||||||
577,
|
577n,
|
||||||
587,
|
587n,
|
||||||
593,
|
593n,
|
||||||
599,
|
599n,
|
||||||
601,
|
601n,
|
||||||
607,
|
607n,
|
||||||
613,
|
613n,
|
||||||
617,
|
617n,
|
||||||
619,
|
619n,
|
||||||
631,
|
631n,
|
||||||
641,
|
641n,
|
||||||
643,
|
643n,
|
||||||
647,
|
647n,
|
||||||
653,
|
653n,
|
||||||
659,
|
659n,
|
||||||
661,
|
661n,
|
||||||
673,
|
673n,
|
||||||
677,
|
677n,
|
||||||
683,
|
683n,
|
||||||
691,
|
691n,
|
||||||
701,
|
701n,
|
||||||
709,
|
709n,
|
||||||
719,
|
719n,
|
||||||
727,
|
727n,
|
||||||
733,
|
733n,
|
||||||
739,
|
739n,
|
||||||
743,
|
743n,
|
||||||
751,
|
751n,
|
||||||
757,
|
757n,
|
||||||
761,
|
761n,
|
||||||
769,
|
769n,
|
||||||
773,
|
773n,
|
||||||
787,
|
787n,
|
||||||
797,
|
797n,
|
||||||
809,
|
809n,
|
||||||
811,
|
811n,
|
||||||
821,
|
821n,
|
||||||
823,
|
823n,
|
||||||
827,
|
827n,
|
||||||
829,
|
829n,
|
||||||
839,
|
839n,
|
||||||
853,
|
853n,
|
||||||
857,
|
857n,
|
||||||
859,
|
859n,
|
||||||
863,
|
863n,
|
||||||
877,
|
877n,
|
||||||
881,
|
881n,
|
||||||
883,
|
883n,
|
||||||
887,
|
887n,
|
||||||
907,
|
907n,
|
||||||
911,
|
911n,
|
||||||
919,
|
919n,
|
||||||
929,
|
929n,
|
||||||
937,
|
937n,
|
||||||
941,
|
941n,
|
||||||
947,
|
947n,
|
||||||
953,
|
953n,
|
||||||
967,
|
967n,
|
||||||
971,
|
971n,
|
||||||
977,
|
977n,
|
||||||
983,
|
983n,
|
||||||
991,
|
991n,
|
||||||
997,
|
997n,
|
||||||
1009,
|
1009n,
|
||||||
1013,
|
1013n,
|
||||||
1019,
|
1019n,
|
||||||
1021,
|
1021n,
|
||||||
1031,
|
1031n,
|
||||||
1033,
|
1033n,
|
||||||
1039,
|
1039n,
|
||||||
1049,
|
1049n,
|
||||||
1051,
|
1051n,
|
||||||
1061,
|
1061n,
|
||||||
1063,
|
1063n,
|
||||||
1069,
|
1069n,
|
||||||
1087,
|
1087n,
|
||||||
1091,
|
1091n,
|
||||||
1093,
|
1093n,
|
||||||
1097,
|
1097n,
|
||||||
1103,
|
1103n,
|
||||||
1109,
|
1109n,
|
||||||
1117,
|
1117n,
|
||||||
1123,
|
1123n,
|
||||||
1129,
|
1129n,
|
||||||
1151,
|
1151n,
|
||||||
1153,
|
1153n,
|
||||||
1163,
|
1163n,
|
||||||
1171,
|
1171n,
|
||||||
1181,
|
1181n,
|
||||||
1187,
|
1187n,
|
||||||
1193,
|
1193n,
|
||||||
1201,
|
1201n,
|
||||||
1213,
|
1213n,
|
||||||
1217,
|
1217n,
|
||||||
1223,
|
1223n,
|
||||||
1229,
|
1229n,
|
||||||
1231,
|
1231n,
|
||||||
1237,
|
1237n,
|
||||||
1249,
|
1249n,
|
||||||
1259,
|
1259n,
|
||||||
1277,
|
1277n,
|
||||||
1279,
|
1279n,
|
||||||
1283,
|
1283n,
|
||||||
1289,
|
1289n,
|
||||||
1291,
|
1291n,
|
||||||
1297,
|
1297n,
|
||||||
1301,
|
1301n,
|
||||||
1303,
|
1303n,
|
||||||
1307,
|
1307n,
|
||||||
1319,
|
1319n,
|
||||||
1321,
|
1321n,
|
||||||
1327,
|
1327n,
|
||||||
1361,
|
1361n,
|
||||||
1367,
|
1367n,
|
||||||
1373,
|
1373n,
|
||||||
1381,
|
1381n,
|
||||||
1399,
|
1399n,
|
||||||
1409,
|
1409n,
|
||||||
1423,
|
1423n,
|
||||||
1427,
|
1427n,
|
||||||
1429,
|
1429n,
|
||||||
1433,
|
1433n,
|
||||||
1439,
|
1439n,
|
||||||
1447,
|
1447n,
|
||||||
1451,
|
1451n,
|
||||||
1453,
|
1453n,
|
||||||
1459,
|
1459n,
|
||||||
1471,
|
1471n,
|
||||||
1481,
|
1481n,
|
||||||
1483,
|
1483n,
|
||||||
1487,
|
1487n,
|
||||||
1489,
|
1489n,
|
||||||
1493,
|
1493n,
|
||||||
1499,
|
1499n,
|
||||||
1511,
|
1511n,
|
||||||
1523,
|
1523n,
|
||||||
1531,
|
1531n,
|
||||||
1543,
|
1543n,
|
||||||
1549,
|
1549n,
|
||||||
1553,
|
1553n,
|
||||||
1559,
|
1559n,
|
||||||
1567,
|
1567n,
|
||||||
1571,
|
1571n,
|
||||||
1579,
|
1579n,
|
||||||
1583,
|
1583n,
|
||||||
1597
|
1597n
|
||||||
]
|
]
|
||||||
let p = _ZERO
|
|
||||||
for (let i = 0; i < firstPrimes.length && (p <= w); i++) {
|
for (let i = 0; i < firstPrimes.length && (firstPrimes[i] <= w); i++) {
|
||||||
p = BigInt(firstPrimes[i])
|
const p = firstPrimes[i]
|
||||||
if (w === p) {
|
if (w === p) {
|
||||||
return true
|
return true
|
||||||
} else if (w % p === _ZERO) {
|
} else if (w % p === 0n) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -749,30 +537,48 @@ function _isProbablyPrime (w, iterations = 16) {
|
||||||
Comment: Increment i for the do-loop in step 4.
|
Comment: Increment i for the do-loop in step 4.
|
||||||
5. Return PROBABLY PRIME.
|
5. Return PROBABLY PRIME.
|
||||||
*/
|
*/
|
||||||
let a = _ZERO; let d = w - _ONE
|
let a = 0n
|
||||||
while (d % _TWO === _ZERO) {
|
const d = w - 1n
|
||||||
d /= _TWO
|
let aux = d
|
||||||
|
while (aux % 2n === 0n) {
|
||||||
|
aux /= 2n
|
||||||
++a
|
++a
|
||||||
}
|
}
|
||||||
|
|
||||||
const m = (w - _ONE) / (_TWO ** a)
|
const m = d / (2n ** a)
|
||||||
|
|
||||||
/* eslint-disable no-labels */
|
// /* eslint-disable no-labels */
|
||||||
loop: do {
|
// loop: do {
|
||||||
const b = randBetween(w - _ONE, _TWO)
|
// const b = randBetween(w - 1n, 2n)
|
||||||
|
// let z = modPow(b, m, w)
|
||||||
|
// if (z === 1n || z === w - 1n) { continue }
|
||||||
|
// for (let j = 1; j < a; j++) {
|
||||||
|
// z = modPow(z, 2n, w)
|
||||||
|
// if (z === w - 1n) { continue loop }
|
||||||
|
// if (z === 1n) { break }
|
||||||
|
// }
|
||||||
|
// return false
|
||||||
|
// } while (--iterations)
|
||||||
|
// /* eslint-enable no-labels */
|
||||||
|
|
||||||
|
// return true
|
||||||
|
|
||||||
|
do {
|
||||||
|
const b = randBetween(d, 2n)
|
||||||
let z = modPow(b, m, w)
|
let z = modPow(b, m, w)
|
||||||
if (z === _ONE || z === w - _ONE) { continue }
|
if (z === 1n || z === d) { continue }
|
||||||
|
let j = 1
|
||||||
for (let j = 1; j < a; j++) {
|
while (j < a) {
|
||||||
z = modPow(z, _TWO, w)
|
z = modPow(z, 2n, w)
|
||||||
if (z === w - _ONE) { continue loop }
|
if (z === d) { break }
|
||||||
if (z === _ONE) { break }
|
if (z === 1n) { return false }
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
if (z !== d) {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
} while (--iterations)
|
} while (--iterations)
|
||||||
/* eslint-enable no-labels */
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
export { abs, bitLength, eGcd, gcd, isProbablyPrime, lcm, max, min, modInv, modPow, prime, primeSync, randBetween, randBits, randBytes, randBytesSync, toZn }
|
export { isProbablyPrime, prime, primeSync, randBetween, randBits, randBytes, randBytesSync }
|
||||||
|
|
|
@ -2,124 +2,16 @@
|
||||||
|
|
||||||
Object.defineProperty(exports, '__esModule', { value: true })
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
const _ZERO = BigInt(0)
|
var bigintModArith = require('bigint-mod-arith')
|
||||||
const _ONE = BigInt(1)
|
|
||||||
const _TWO = BigInt(2)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
*
|
|
||||||
* @returns {bigint} the absolute value of a
|
|
||||||
*/
|
|
||||||
function abs (a) {
|
|
||||||
a = BigInt(a)
|
|
||||||
return (a >= _ZERO) ? a : -a
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the bitlength of a number
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @returns {number} - the bit length
|
|
||||||
*/
|
|
||||||
function bitLength (a) {
|
|
||||||
a = BigInt(a)
|
|
||||||
if (a === _ONE) { return 1 }
|
|
||||||
let bits = 1
|
|
||||||
do {
|
|
||||||
bits++
|
|
||||||
} while ((a >>= _ONE) > _ONE)
|
|
||||||
return bits
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} egcdReturn A triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
* @property {bigint} g
|
|
||||||
* @property {bigint} x
|
|
||||||
* @property {bigint} y
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm.
|
|
||||||
* Take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {egcdReturn} A triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
*/
|
|
||||||
function eGcd (a, b) {
|
|
||||||
a = BigInt(a)
|
|
||||||
b = BigInt(b)
|
|
||||||
if (a <= _ZERO | b <= _ZERO) { return NaN } // a and b MUST be positive
|
|
||||||
|
|
||||||
let x = _ZERO
|
|
||||||
let y = _ONE
|
|
||||||
let u = _ONE
|
|
||||||
let v = _ZERO
|
|
||||||
|
|
||||||
while (a !== _ZERO) {
|
|
||||||
const q = b / a
|
|
||||||
const r = b % a
|
|
||||||
const m = x - (u * q)
|
|
||||||
const n = y - (v * q)
|
|
||||||
b = a
|
|
||||||
a = r
|
|
||||||
x = u
|
|
||||||
y = v
|
|
||||||
u = m
|
|
||||||
v = n
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
b: b,
|
|
||||||
x: x,
|
|
||||||
y: y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Greatest-common divisor of two integers based on the iterative binary algorithm.
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} The greatest common divisor of a and b
|
|
||||||
*/
|
|
||||||
function gcd (a, b) {
|
|
||||||
a = abs(a)
|
|
||||||
b = abs(b)
|
|
||||||
if (a === _ZERO) { return b } else if (b === _ZERO) { return a }
|
|
||||||
|
|
||||||
let shift = _ZERO
|
|
||||||
while (!((a | b) & _ONE)) {
|
|
||||||
a >>= _ONE
|
|
||||||
b >>= _ONE
|
|
||||||
shift++
|
|
||||||
}
|
|
||||||
while (!(a & _ONE)) a >>= _ONE
|
|
||||||
do {
|
|
||||||
while (!(b & _ONE)) b >>= _ONE
|
|
||||||
if (a > b) {
|
|
||||||
const x = a
|
|
||||||
a = b
|
|
||||||
b = x
|
|
||||||
}
|
|
||||||
b -= a
|
|
||||||
} while (b)
|
|
||||||
|
|
||||||
// rescale
|
|
||||||
return a << shift
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The test first tries if any of the first 250 small primes are a factor of the input number and then passes several
|
* The test first tries if any of the first 250 small primes are a factor of the input number and then passes several
|
||||||
* iterations of Miller-Rabin Probabilistic Primality Test (FIPS 186-4 C.3.1)
|
* iterations of Miller-Rabin Probabilistic Primality Test (FIPS 186-4 C.3.1)
|
||||||
*
|
*
|
||||||
* @param {number|bigint} w An integer to be tested for primality
|
* @param {number | bigint} w An integer to be tested for primality
|
||||||
* @param {number} [iterations = 16] The number of iterations for the primality test. The value shall be consistent with Table C.1, C.2 or C.3
|
* @param {number} [iterations = 16] The number of iterations for the primality test. The value shall be consistent with Table C.1, C.2 or C.3
|
||||||
*
|
*
|
||||||
* @return {Promise} A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
|
* @return {Promise<boolean>} A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
|
||||||
*/
|
*/
|
||||||
async function isProbablyPrime (w, iterations = 16) {
|
async function isProbablyPrime (w, iterations = 16) {
|
||||||
if (typeof w === 'number') {
|
if (typeof w === 'number') {
|
||||||
|
@ -155,96 +47,6 @@ async function isProbablyPrime (w, iterations = 16) {
|
||||||
/* eslint-enable no-lone-blocks */
|
/* eslint-enable no-lone-blocks */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The least common multiple computed as abs(a*b)/gcd(a,b)
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} The least common multiple of a and b
|
|
||||||
*/
|
|
||||||
function lcm (a, b) {
|
|
||||||
a = BigInt(a)
|
|
||||||
b = BigInt(b)
|
|
||||||
if (a === _ZERO && b === _ZERO) { return _ZERO }
|
|
||||||
return abs(a * b) / gcd(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum. max(a,b)==a if a>=b. max(a,b)==b if a<=b
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} maximum of numbers a and b
|
|
||||||
*/
|
|
||||||
function max (a, b) {
|
|
||||||
a = BigInt(a)
|
|
||||||
b = BigInt(b)
|
|
||||||
return (a >= b) ? a : b
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimum. min(a,b)==b if a>=b. min(a,b)==a if a<=b
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} minimum of numbers a and b
|
|
||||||
*/
|
|
||||||
function min (a, b) {
|
|
||||||
a = BigInt(a)
|
|
||||||
b = BigInt(b)
|
|
||||||
return (a >= b) ? b : a
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modular inverse.
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a The number to find an inverse for
|
|
||||||
* @param {number|bigint} n The modulo
|
|
||||||
*
|
|
||||||
* @returns {bigint} the inverse modulo n or NaN if it does not exist
|
|
||||||
*/
|
|
||||||
function modInv (a, n) {
|
|
||||||
const egcd = eGcd(toZn(a, n), n)
|
|
||||||
if (egcd.b !== _ONE) {
|
|
||||||
return NaN // modular inverse does not exist
|
|
||||||
} else {
|
|
||||||
return toZn(egcd.x, n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modular exponentiation b**e mod n. Currently using the right-to-left binary method
|
|
||||||
*
|
|
||||||
* @param {number|bigint} b base
|
|
||||||
* @param {number|bigint} e exponent
|
|
||||||
* @param {number|bigint} n modulo
|
|
||||||
*
|
|
||||||
* @returns {bigint} b**e mod n
|
|
||||||
*/
|
|
||||||
function modPow (b, e, n) {
|
|
||||||
n = BigInt(n)
|
|
||||||
if (n === _ZERO) { return NaN } else if (n === _ONE) { return _ZERO }
|
|
||||||
|
|
||||||
b = toZn(b, n)
|
|
||||||
|
|
||||||
e = BigInt(e)
|
|
||||||
if (e < _ZERO) {
|
|
||||||
return modInv(modPow(b, abs(e), n), n)
|
|
||||||
}
|
|
||||||
|
|
||||||
let r = _ONE
|
|
||||||
while (e > 0) {
|
|
||||||
if ((e % _TWO) === _ONE) {
|
|
||||||
r = (r * b) % n
|
|
||||||
}
|
|
||||||
e = e / _TWO
|
|
||||||
b = b ** _TWO % n
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
||||||
* The browser version uses web workers to parallelise prime look up. Therefore, it does not lock the UI
|
* The browser version uses web workers to parallelise prime look up. Therefore, it does not lock the UI
|
||||||
|
@ -255,13 +57,13 @@ function modPow (b, e, n) {
|
||||||
* @param {number} bitLength The required bit length for the generated prime
|
* @param {number} bitLength The required bit length for the generated prime
|
||||||
* @param {number} [iterations = 16] The number of iterations for the Miller-Rabin Probabilistic Primality Test
|
* @param {number} [iterations = 16] The number of iterations for the Miller-Rabin Probabilistic Primality Test
|
||||||
*
|
*
|
||||||
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits.
|
* @returns {Promise<bigint>} A promise that resolves to a bigint probable prime of bitLength bits.
|
||||||
*/
|
*/
|
||||||
function prime (bitLength, iterations = 16) {
|
function prime (bitLength, iterations = 16) {
|
||||||
if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) }
|
if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) }
|
||||||
|
|
||||||
if (!_useWorkers) {
|
if (!_useWorkers) {
|
||||||
let rnd = _ZERO
|
let rnd = 0n
|
||||||
do {
|
do {
|
||||||
rnd = fromBuffer(randBytesSync(bitLength / 8, true))
|
rnd = fromBuffer(randBytesSync(bitLength / 8, true))
|
||||||
} while (!_isProbablyPrime(rnd, iterations))
|
} while (!_isProbablyPrime(rnd, iterations))
|
||||||
|
@ -297,7 +99,7 @@ function prime (bitLength, iterations = 16) {
|
||||||
{ // Node.js
|
{ // Node.js
|
||||||
const { cpus } = require('os')
|
const { cpus } = require('os')
|
||||||
const { Worker } = require('worker_threads')
|
const { Worker } = require('worker_threads')
|
||||||
for (let i = 0; i < cpus().length; i++) {
|
for (let i = 0; i < cpus().length - 1; i++) {
|
||||||
const newWorker = new Worker(__filename)
|
const newWorker = new Worker(__filename)
|
||||||
newWorker.on('message', (msg) => _onmessage(msg, newWorker))
|
newWorker.on('message', (msg) => _onmessage(msg, newWorker))
|
||||||
workerList.push(newWorker)
|
workerList.push(newWorker)
|
||||||
|
@ -327,7 +129,7 @@ function prime (bitLength, iterations = 16) {
|
||||||
*/
|
*/
|
||||||
function primeSync (bitLength, iterations = 16) {
|
function primeSync (bitLength, iterations = 16) {
|
||||||
if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) }
|
if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) }
|
||||||
let rnd = _ZERO
|
let rnd = 0n
|
||||||
do {
|
do {
|
||||||
rnd = fromBuffer(randBytesSync(bitLength / 8, true))
|
rnd = fromBuffer(randBytesSync(bitLength / 8, true))
|
||||||
} while (!_isProbablyPrime(rnd, iterations))
|
} while (!_isProbablyPrime(rnd, iterations))
|
||||||
|
@ -341,10 +143,10 @@ function primeSync (bitLength, iterations = 16) {
|
||||||
*
|
*
|
||||||
* @returns {bigint} A cryptographically secure random bigint between [min,max]
|
* @returns {bigint} A cryptographically secure random bigint between [min,max]
|
||||||
*/
|
*/
|
||||||
function randBetween (max, min = _ONE) {
|
function randBetween (max, min = 1n) {
|
||||||
if (max <= min) throw new Error('max must be > min')
|
if (max <= min) throw new Error('max must be > min')
|
||||||
const interval = max - min
|
const interval = max - min
|
||||||
const bitLen = bitLength(interval)
|
const bitLen = bigintModArith.bitLength(interval)
|
||||||
let rnd
|
let rnd
|
||||||
do {
|
do {
|
||||||
const buf = randBits(bitLen)
|
const buf = randBits(bitLen)
|
||||||
|
@ -359,7 +161,7 @@ function randBetween (max, min = _ONE) {
|
||||||
* @param {number} bitLength The desired number of random bits
|
* @param {number} bitLength The desired number of random bits
|
||||||
* @param {boolean} [forceLength = false] If we want to force the output to have a specific bit length. It basically forces the msb to be 1
|
* @param {boolean} [forceLength = false] If we want to force the output to have a specific bit length. It basically forces the msb to be 1
|
||||||
*
|
*
|
||||||
* @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
|
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
|
||||||
*/
|
*/
|
||||||
function randBits (bitLength, forceLength = false) {
|
function randBits (bitLength, forceLength = false) {
|
||||||
if (bitLength < 1) {
|
if (bitLength < 1) {
|
||||||
|
@ -386,7 +188,7 @@ function randBits (bitLength, forceLength = false) {
|
||||||
* @param {number} byteLength The desired number of random bytes
|
* @param {number} byteLength The desired number of random bytes
|
||||||
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
||||||
*
|
*
|
||||||
* @returns {Promise} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
* @returns {Promise<Buffer | Uint8Array>} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
||||||
*/
|
*/
|
||||||
function randBytes (byteLength, forceLength = false) {
|
function randBytes (byteLength, forceLength = false) {
|
||||||
if (byteLength < 1) { throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`) }
|
if (byteLength < 1) { throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`) }
|
||||||
|
@ -411,7 +213,7 @@ function randBytes (byteLength, forceLength = false) {
|
||||||
* @param {number} byteLength The desired number of random bytes
|
* @param {number} byteLength The desired number of random bytes
|
||||||
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
||||||
*
|
*
|
||||||
* @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
||||||
*/
|
*/
|
||||||
function randBytesSync (byteLength, forceLength = false) {
|
function randBytesSync (byteLength, forceLength = false) {
|
||||||
if (byteLength < 1) { throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`) }
|
if (byteLength < 1) { throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`) }
|
||||||
|
@ -427,25 +229,10 @@ function randBytesSync (byteLength, forceLength = false) {
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the smallest positive element that is congruent to a in modulo n
|
|
||||||
* @param {number|bigint} a An integer
|
|
||||||
* @param {number|bigint} n The modulo
|
|
||||||
*
|
|
||||||
* @returns {bigint} The smallest positive representation of a in modulo n
|
|
||||||
*/
|
|
||||||
function toZn (a, n) {
|
|
||||||
n = BigInt(n)
|
|
||||||
if (n <= 0) { return NaN }
|
|
||||||
|
|
||||||
a = BigInt(a) % n
|
|
||||||
return (a < 0) ? a + n : a
|
|
||||||
}
|
|
||||||
|
|
||||||
/* HELPER FUNCTIONS */
|
/* HELPER FUNCTIONS */
|
||||||
|
|
||||||
function fromBuffer (buf) {
|
function fromBuffer (buf) {
|
||||||
let ret = _ZERO
|
let ret = 0n
|
||||||
for (const i of buf.values()) {
|
for (const i of buf.values()) {
|
||||||
const bi = BigInt(i)
|
const bi = BigInt(i)
|
||||||
ret = (ret << BigInt(8)) + bi
|
ret = (ret << BigInt(8)) + bi
|
||||||
|
@ -458,269 +245,269 @@ function _isProbablyPrime (w, iterations = 16) {
|
||||||
PREFILTERING. Even values but 2 are not primes, so don't test.
|
PREFILTERING. Even values but 2 are not primes, so don't test.
|
||||||
1 is not a prime and the M-R algorithm needs w>1.
|
1 is not a prime and the M-R algorithm needs w>1.
|
||||||
*/
|
*/
|
||||||
if (w === _TWO) { return true } else if ((w & _ONE) === _ZERO || w === _ONE) { return false }
|
if (w === 2n) { return true } else if ((w & 1n) === 0n || w === 1n) { return false }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test if any of the first 250 small primes are a factor of w. 2 is not tested because it was already tested above.
|
Test if any of the first 250 small primes are a factor of w. 2 is not tested because it was already tested above.
|
||||||
*/
|
*/
|
||||||
const firstPrimes = [
|
const firstPrimes = [
|
||||||
3,
|
3n,
|
||||||
5,
|
5n,
|
||||||
7,
|
7n,
|
||||||
11,
|
11n,
|
||||||
13,
|
13n,
|
||||||
17,
|
17n,
|
||||||
19,
|
19n,
|
||||||
23,
|
23n,
|
||||||
29,
|
29n,
|
||||||
31,
|
31n,
|
||||||
37,
|
37n,
|
||||||
41,
|
41n,
|
||||||
43,
|
43n,
|
||||||
47,
|
47n,
|
||||||
53,
|
53n,
|
||||||
59,
|
59n,
|
||||||
61,
|
61n,
|
||||||
67,
|
67n,
|
||||||
71,
|
71n,
|
||||||
73,
|
73n,
|
||||||
79,
|
79n,
|
||||||
83,
|
83n,
|
||||||
89,
|
89n,
|
||||||
97,
|
97n,
|
||||||
101,
|
101n,
|
||||||
103,
|
103n,
|
||||||
107,
|
107n,
|
||||||
109,
|
109n,
|
||||||
113,
|
113n,
|
||||||
127,
|
127n,
|
||||||
131,
|
131n,
|
||||||
137,
|
137n,
|
||||||
139,
|
139n,
|
||||||
149,
|
149n,
|
||||||
151,
|
151n,
|
||||||
157,
|
157n,
|
||||||
163,
|
163n,
|
||||||
167,
|
167n,
|
||||||
173,
|
173n,
|
||||||
179,
|
179n,
|
||||||
181,
|
181n,
|
||||||
191,
|
191n,
|
||||||
193,
|
193n,
|
||||||
197,
|
197n,
|
||||||
199,
|
199n,
|
||||||
211,
|
211n,
|
||||||
223,
|
223n,
|
||||||
227,
|
227n,
|
||||||
229,
|
229n,
|
||||||
233,
|
233n,
|
||||||
239,
|
239n,
|
||||||
241,
|
241n,
|
||||||
251,
|
251n,
|
||||||
257,
|
257n,
|
||||||
263,
|
263n,
|
||||||
269,
|
269n,
|
||||||
271,
|
271n,
|
||||||
277,
|
277n,
|
||||||
281,
|
281n,
|
||||||
283,
|
283n,
|
||||||
293,
|
293n,
|
||||||
307,
|
307n,
|
||||||
311,
|
311n,
|
||||||
313,
|
313n,
|
||||||
317,
|
317n,
|
||||||
331,
|
331n,
|
||||||
337,
|
337n,
|
||||||
347,
|
347n,
|
||||||
349,
|
349n,
|
||||||
353,
|
353n,
|
||||||
359,
|
359n,
|
||||||
367,
|
367n,
|
||||||
373,
|
373n,
|
||||||
379,
|
379n,
|
||||||
383,
|
383n,
|
||||||
389,
|
389n,
|
||||||
397,
|
397n,
|
||||||
401,
|
401n,
|
||||||
409,
|
409n,
|
||||||
419,
|
419n,
|
||||||
421,
|
421n,
|
||||||
431,
|
431n,
|
||||||
433,
|
433n,
|
||||||
439,
|
439n,
|
||||||
443,
|
443n,
|
||||||
449,
|
449n,
|
||||||
457,
|
457n,
|
||||||
461,
|
461n,
|
||||||
463,
|
463n,
|
||||||
467,
|
467n,
|
||||||
479,
|
479n,
|
||||||
487,
|
487n,
|
||||||
491,
|
491n,
|
||||||
499,
|
499n,
|
||||||
503,
|
503n,
|
||||||
509,
|
509n,
|
||||||
521,
|
521n,
|
||||||
523,
|
523n,
|
||||||
541,
|
541n,
|
||||||
547,
|
547n,
|
||||||
557,
|
557n,
|
||||||
563,
|
563n,
|
||||||
569,
|
569n,
|
||||||
571,
|
571n,
|
||||||
577,
|
577n,
|
||||||
587,
|
587n,
|
||||||
593,
|
593n,
|
||||||
599,
|
599n,
|
||||||
601,
|
601n,
|
||||||
607,
|
607n,
|
||||||
613,
|
613n,
|
||||||
617,
|
617n,
|
||||||
619,
|
619n,
|
||||||
631,
|
631n,
|
||||||
641,
|
641n,
|
||||||
643,
|
643n,
|
||||||
647,
|
647n,
|
||||||
653,
|
653n,
|
||||||
659,
|
659n,
|
||||||
661,
|
661n,
|
||||||
673,
|
673n,
|
||||||
677,
|
677n,
|
||||||
683,
|
683n,
|
||||||
691,
|
691n,
|
||||||
701,
|
701n,
|
||||||
709,
|
709n,
|
||||||
719,
|
719n,
|
||||||
727,
|
727n,
|
||||||
733,
|
733n,
|
||||||
739,
|
739n,
|
||||||
743,
|
743n,
|
||||||
751,
|
751n,
|
||||||
757,
|
757n,
|
||||||
761,
|
761n,
|
||||||
769,
|
769n,
|
||||||
773,
|
773n,
|
||||||
787,
|
787n,
|
||||||
797,
|
797n,
|
||||||
809,
|
809n,
|
||||||
811,
|
811n,
|
||||||
821,
|
821n,
|
||||||
823,
|
823n,
|
||||||
827,
|
827n,
|
||||||
829,
|
829n,
|
||||||
839,
|
839n,
|
||||||
853,
|
853n,
|
||||||
857,
|
857n,
|
||||||
859,
|
859n,
|
||||||
863,
|
863n,
|
||||||
877,
|
877n,
|
||||||
881,
|
881n,
|
||||||
883,
|
883n,
|
||||||
887,
|
887n,
|
||||||
907,
|
907n,
|
||||||
911,
|
911n,
|
||||||
919,
|
919n,
|
||||||
929,
|
929n,
|
||||||
937,
|
937n,
|
||||||
941,
|
941n,
|
||||||
947,
|
947n,
|
||||||
953,
|
953n,
|
||||||
967,
|
967n,
|
||||||
971,
|
971n,
|
||||||
977,
|
977n,
|
||||||
983,
|
983n,
|
||||||
991,
|
991n,
|
||||||
997,
|
997n,
|
||||||
1009,
|
1009n,
|
||||||
1013,
|
1013n,
|
||||||
1019,
|
1019n,
|
||||||
1021,
|
1021n,
|
||||||
1031,
|
1031n,
|
||||||
1033,
|
1033n,
|
||||||
1039,
|
1039n,
|
||||||
1049,
|
1049n,
|
||||||
1051,
|
1051n,
|
||||||
1061,
|
1061n,
|
||||||
1063,
|
1063n,
|
||||||
1069,
|
1069n,
|
||||||
1087,
|
1087n,
|
||||||
1091,
|
1091n,
|
||||||
1093,
|
1093n,
|
||||||
1097,
|
1097n,
|
||||||
1103,
|
1103n,
|
||||||
1109,
|
1109n,
|
||||||
1117,
|
1117n,
|
||||||
1123,
|
1123n,
|
||||||
1129,
|
1129n,
|
||||||
1151,
|
1151n,
|
||||||
1153,
|
1153n,
|
||||||
1163,
|
1163n,
|
||||||
1171,
|
1171n,
|
||||||
1181,
|
1181n,
|
||||||
1187,
|
1187n,
|
||||||
1193,
|
1193n,
|
||||||
1201,
|
1201n,
|
||||||
1213,
|
1213n,
|
||||||
1217,
|
1217n,
|
||||||
1223,
|
1223n,
|
||||||
1229,
|
1229n,
|
||||||
1231,
|
1231n,
|
||||||
1237,
|
1237n,
|
||||||
1249,
|
1249n,
|
||||||
1259,
|
1259n,
|
||||||
1277,
|
1277n,
|
||||||
1279,
|
1279n,
|
||||||
1283,
|
1283n,
|
||||||
1289,
|
1289n,
|
||||||
1291,
|
1291n,
|
||||||
1297,
|
1297n,
|
||||||
1301,
|
1301n,
|
||||||
1303,
|
1303n,
|
||||||
1307,
|
1307n,
|
||||||
1319,
|
1319n,
|
||||||
1321,
|
1321n,
|
||||||
1327,
|
1327n,
|
||||||
1361,
|
1361n,
|
||||||
1367,
|
1367n,
|
||||||
1373,
|
1373n,
|
||||||
1381,
|
1381n,
|
||||||
1399,
|
1399n,
|
||||||
1409,
|
1409n,
|
||||||
1423,
|
1423n,
|
||||||
1427,
|
1427n,
|
||||||
1429,
|
1429n,
|
||||||
1433,
|
1433n,
|
||||||
1439,
|
1439n,
|
||||||
1447,
|
1447n,
|
||||||
1451,
|
1451n,
|
||||||
1453,
|
1453n,
|
||||||
1459,
|
1459n,
|
||||||
1471,
|
1471n,
|
||||||
1481,
|
1481n,
|
||||||
1483,
|
1483n,
|
||||||
1487,
|
1487n,
|
||||||
1489,
|
1489n,
|
||||||
1493,
|
1493n,
|
||||||
1499,
|
1499n,
|
||||||
1511,
|
1511n,
|
||||||
1523,
|
1523n,
|
||||||
1531,
|
1531n,
|
||||||
1543,
|
1543n,
|
||||||
1549,
|
1549n,
|
||||||
1553,
|
1553n,
|
||||||
1559,
|
1559n,
|
||||||
1567,
|
1567n,
|
||||||
1571,
|
1571n,
|
||||||
1579,
|
1579n,
|
||||||
1583,
|
1583n,
|
||||||
1597
|
1597n
|
||||||
]
|
]
|
||||||
let p = _ZERO
|
|
||||||
for (let i = 0; i < firstPrimes.length && (p <= w); i++) {
|
for (let i = 0; i < firstPrimes.length && (firstPrimes[i] <= w); i++) {
|
||||||
p = BigInt(firstPrimes[i])
|
const p = firstPrimes[i]
|
||||||
if (w === p) {
|
if (w === p) {
|
||||||
return true
|
return true
|
||||||
} else if (w % p === _ZERO) {
|
} else if (w % p === 0n) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -744,29 +531,47 @@ function _isProbablyPrime (w, iterations = 16) {
|
||||||
Comment: Increment i for the do-loop in step 4.
|
Comment: Increment i for the do-loop in step 4.
|
||||||
5. Return PROBABLY PRIME.
|
5. Return PROBABLY PRIME.
|
||||||
*/
|
*/
|
||||||
let a = _ZERO; let d = w - _ONE
|
let a = 0n
|
||||||
while (d % _TWO === _ZERO) {
|
const d = w - 1n
|
||||||
d /= _TWO
|
let aux = d
|
||||||
|
while (aux % 2n === 0n) {
|
||||||
|
aux /= 2n
|
||||||
++a
|
++a
|
||||||
}
|
}
|
||||||
|
|
||||||
const m = (w - _ONE) / (_TWO ** a)
|
const m = d / (2n ** a)
|
||||||
|
|
||||||
/* eslint-disable no-labels */
|
// /* eslint-disable no-labels */
|
||||||
loop: do {
|
// loop: do {
|
||||||
const b = randBetween(w - _ONE, _TWO)
|
// const b = randBetween(w - 1n, 2n)
|
||||||
let z = modPow(b, m, w)
|
// let z = modPow(b, m, w)
|
||||||
if (z === _ONE || z === w - _ONE) { continue }
|
// if (z === 1n || z === w - 1n) { continue }
|
||||||
|
// for (let j = 1; j < a; j++) {
|
||||||
|
// z = modPow(z, 2n, w)
|
||||||
|
// if (z === w - 1n) { continue loop }
|
||||||
|
// if (z === 1n) { break }
|
||||||
|
// }
|
||||||
|
// return false
|
||||||
|
// } while (--iterations)
|
||||||
|
// /* eslint-enable no-labels */
|
||||||
|
|
||||||
for (let j = 1; j < a; j++) {
|
// return true
|
||||||
z = modPow(z, _TWO, w)
|
|
||||||
if (z === w - _ONE) { continue loop }
|
do {
|
||||||
if (z === _ONE) { break }
|
const b = randBetween(d, 2n)
|
||||||
|
let z = bigintModArith.modPow(b, m, w)
|
||||||
|
if (z === 1n || z === d) { continue }
|
||||||
|
let j = 1
|
||||||
|
while (j < a) {
|
||||||
|
z = bigintModArith.modPow(z, 2n, w)
|
||||||
|
if (z === d) { break }
|
||||||
|
if (z === 1n) { return false }
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
if (z !== d) {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
} while (--iterations)
|
} while (--iterations)
|
||||||
/* eslint-enable no-labels */
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -801,20 +606,70 @@ if (_useWorkers) { // node.js with support for workers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.abs = abs
|
Object.defineProperty(exports, 'abs', {
|
||||||
exports.bitLength = bitLength
|
enumerable: true,
|
||||||
exports.eGcd = eGcd
|
get: function () {
|
||||||
exports.gcd = gcd
|
return bigintModArith.abs
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.defineProperty(exports, 'bitLength', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return bigintModArith.bitLength
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.defineProperty(exports, 'eGcd', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return bigintModArith.eGcd
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.defineProperty(exports, 'gcd', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return bigintModArith.gcd
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.defineProperty(exports, 'lcm', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return bigintModArith.lcm
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.defineProperty(exports, 'max', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return bigintModArith.max
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.defineProperty(exports, 'min', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return bigintModArith.min
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.defineProperty(exports, 'modInv', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return bigintModArith.modInv
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.defineProperty(exports, 'modPow', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return bigintModArith.modPow
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Object.defineProperty(exports, 'toZn', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
return bigintModArith.toZn
|
||||||
|
}
|
||||||
|
})
|
||||||
exports.isProbablyPrime = isProbablyPrime
|
exports.isProbablyPrime = isProbablyPrime
|
||||||
exports.lcm = lcm
|
|
||||||
exports.max = max
|
|
||||||
exports.min = min
|
|
||||||
exports.modInv = modInv
|
|
||||||
exports.modPow = modPow
|
|
||||||
exports.prime = prime
|
exports.prime = prime
|
||||||
exports.primeSync = primeSync
|
exports.primeSync = primeSync
|
||||||
exports.randBetween = randBetween
|
exports.randBetween = randBetween
|
||||||
exports.randBits = randBits
|
exports.randBits = randBits
|
||||||
exports.randBytes = randBytes
|
exports.randBytes = randBytes
|
||||||
exports.randBytesSync = randBytesSync
|
exports.randBytesSync = randBytesSync
|
||||||
exports.toZn = toZn
|
|
||||||
|
|
|
@ -105,8 +105,7 @@
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "13.11.0",
|
"version": "13.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.0.tgz",
|
||||||
"integrity": "sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ==",
|
"integrity": "sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"@types/resolve": {
|
"@types/resolve": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
|
@ -262,6 +261,11 @@
|
||||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"bigint-mod-arith": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/bigint-mod-arith/-/bigint-mod-arith-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-sQyEj0XMU4hai3G/+uLwohrGjfUn8rGVWAYnnlFrQhw8YjilptTyJrx7NMimKwQvYr2eXGWGDlYVL3wfE4GIRg=="
|
||||||
|
},
|
||||||
"binary-extensions": {
|
"binary-extensions": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
"build:js": "rollup -c build/rollup.config.js",
|
"build:js": "rollup -c build/rollup.config.js",
|
||||||
"build:standard": "standard --fix",
|
"build:standard": "standard --fix",
|
||||||
"build:browserTests": "rollup -c build/rollup.tests.config.js",
|
"build:browserTests": "rollup -c build/rollup.tests.config.js",
|
||||||
"build:docs": "jsdoc2md --template=./src/doc/readme-template.md --files ./lib/index.browser.mod.js -d 3 > README.md",
|
"build:docs": "node build/build.docs.js",
|
||||||
"build:dts": "node build/build.dts.js",
|
"build:dts": "node build/build.dts.js",
|
||||||
"build": "run-s build:**",
|
"build": "run-s build:**",
|
||||||
"prepublishOnly": "npm run build"
|
"prepublishOnly": "npm run build"
|
||||||
|
@ -69,5 +69,9 @@
|
||||||
"rollup-plugin-terser": "^5.3.0",
|
"rollup-plugin-terser": "^5.3.0",
|
||||||
"standard": "^14.3.3",
|
"standard": "^14.3.3",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "^13.11.0",
|
||||||
|
"bigint-mod-arith": "^2.0.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@ bigint-crypto-utils can be imported to your project with `npm`:
|
||||||
npm install bigint-crypto-utils
|
npm install bigint-crypto-utils
|
||||||
```
|
```
|
||||||
|
|
||||||
NPM installation defaults to the minified ES6 module for browsers and the CJS one for Node.js.
|
NPM installation defaults to the ES6 module for browsers and the CJS one for Node.js.
|
||||||
|
|
||||||
For web browsers, you can also directly download the [IIFE file](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.mod.js) from GitHub.
|
For web browsers, you can also directly download the [IIFE bundle](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.js) or the [ES6 bundle module](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.mod.js) from GitHub.
|
||||||
|
|
||||||
## Usage examples
|
## Usage examples
|
||||||
|
|
||||||
|
@ -29,26 +29,25 @@ Import your module as :
|
||||||
const bigintCryptoUtils = require('bigint-crypto-utils')
|
const bigintCryptoUtils = require('bigint-crypto-utils')
|
||||||
... // your code here
|
... // your code here
|
||||||
```
|
```
|
||||||
- Javascript native project
|
- JavaScript native project
|
||||||
```javascript
|
```javascript
|
||||||
import * as bigintCryptoUtils from 'bigint-crypto-utils'
|
import * as bigintCryptoUtils from 'bigint-crypto-utils'
|
||||||
... // your code here
|
... // your code here
|
||||||
```
|
```
|
||||||
- Javascript native browser ES6 mod
|
- JavaScript native browser ES6 mod
|
||||||
```html
|
```html
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import * as bigintCryptoUtils from 'lib/index.browser.bundle.mod.js' // Use you actual path to the broser mod bundle
|
import * as bigintCryptoUtils from 'lib/index.browser.bundle.mod.js' // Use you actual path to the broser mod bundle
|
||||||
... // your code here
|
... // your code here
|
||||||
</script>
|
</script>
|
||||||
import as bcu from 'bigint-crypto-utils'
|
|
||||||
... // your code here
|
|
||||||
```
|
```
|
||||||
- Javascript native browser IIFE
|
- JavaScript native browser IIFE
|
||||||
```html
|
```html
|
||||||
<script src="../../lib/index.browser.bundle.js"></script>
|
<script src="../../lib/index.browser.bundle.js"></script> <!-- Use you actual path to the browser bundle -->
|
||||||
<script>
|
<script>
|
||||||
... // your code here
|
... // your code here
|
||||||
</script>
|
</script>
|
||||||
|
```
|
||||||
- TypeScript
|
- TypeScript
|
||||||
```typescript
|
```typescript
|
||||||
import * as bigintCryptoUtils from 'bigint-crypto-utils'
|
import * as bigintCryptoUtils from 'bigint-crypto-utils'
|
||||||
|
@ -56,6 +55,8 @@ Import your module as :
|
||||||
```
|
```
|
||||||
> BigInt is [ES-2020](https://tc39.es/ecma262/#sec-bigint-objects). In order to use it with TypeScript you should set `lib` (and probably also `target` and `module`) to `esnext` in `tsconfig.json`.
|
> BigInt is [ES-2020](https://tc39.es/ecma262/#sec-bigint-objects). In order to use it with TypeScript you should set `lib` (and probably also `target` and `module`) to `esnext` in `tsconfig.json`.
|
||||||
|
|
||||||
|
And you could use it like in the following:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
/* Stage 3 BigInts with value 666 can be declared as BigInt('666')
|
/* Stage 3 BigInts with value 666 can be declared as BigInt('666')
|
||||||
or the shorter new no-so-linter-friendly syntax 666n.
|
or the shorter new no-so-linter-friendly syntax 666n.
|
||||||
|
@ -65,22 +66,22 @@ be raised.
|
||||||
*/
|
*/
|
||||||
const a = BigInt('5')
|
const a = BigInt('5')
|
||||||
const b = BigInt('2')
|
const b = BigInt('2')
|
||||||
const n = BigInt('19')
|
const n = 19n
|
||||||
|
|
||||||
console.log(bigintCryptoUtils.modPow(a, b, n)) // prints 6
|
console.log(bigintCryptoUtils.modPow(a, b, n)) // prints 6
|
||||||
|
|
||||||
console.log(bigintCryptoUtils.modInv(BigInt('2'), BigInt('5'))) // prints 3
|
console.log(bigintCryptoUtils.modInv(2n, 5n)) // prints 3
|
||||||
|
|
||||||
console.log(bigintCryptoUtils.modInv(BigInt('3'), BigInt('5'))) // prints 2
|
console.log(bigintCryptoUtils.modInv(BigInt('3'), BigInt('5'))) // prints 2
|
||||||
|
|
||||||
console.log(bigintCryptoUtils.randBetween(BigInt(2) ** BigInt(256))) // Prints a cryptographically secure random number between 1 and 2**256 bits.
|
console.log(bigintCryptoUtils.randBetween(2n ** 256n)) // Prints a cryptographically secure random number between 1 and 2**256 bits.
|
||||||
|
|
||||||
async function primeTesting () {
|
async function primeTesting () {
|
||||||
// Output of a probable prime of 2048 bits
|
// Output of a probable prime of 2048 bits
|
||||||
console.log(await bigintCryptoUtils.prime(2048))
|
console.log(await bigintCryptoUtils.prime(2048))
|
||||||
|
|
||||||
// Testing if a number is a probable prime (Miller-Rabin)
|
// Testing if a number is a probable prime (Miller-Rabin)
|
||||||
const number = 27
|
const number = 27n
|
||||||
const isPrime = await bigintCryptoUtils.isProbablyPrime(number)
|
const isPrime = await bigintCryptoUtils.isProbablyPrime(number)
|
||||||
if (isPrime) {
|
if (isPrime) {
|
||||||
console.log(`${number} is prime`)
|
console.log(`${number} is prime`)
|
||||||
|
@ -93,6 +94,6 @@ primeTesting()
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## bigint-crypto-utils JS Doc
|
## API reference documentation
|
||||||
|
|
||||||
{{>main}}
|
{{>main}}
|
||||||
|
|
802
src/js/index.js
802
src/js/index.js
|
@ -1,121 +1,14 @@
|
||||||
const _ZERO = BigInt(0)
|
import { bitLength, eGcd, modInv, modPow, toZn } from 'bigint-mod-arith'
|
||||||
const _ONE = BigInt(1)
|
export { abs, bitLength, eGcd, gcd, lcm, max, min, modInv, modPow, toZn } from 'bigint-mod-arith'
|
||||||
const _TWO = BigInt(2)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
*
|
|
||||||
* @returns {bigint} the absolute value of a
|
|
||||||
*/
|
|
||||||
export function abs (a) {
|
|
||||||
a = BigInt(a)
|
|
||||||
return (a >= _ZERO) ? a : -a
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the bitlength of a number
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @returns {number} - the bit length
|
|
||||||
*/
|
|
||||||
export function bitLength (a) {
|
|
||||||
a = BigInt(a)
|
|
||||||
if (a === _ONE) { return 1 }
|
|
||||||
let bits = 1
|
|
||||||
do {
|
|
||||||
bits++
|
|
||||||
} while ((a >>= _ONE) > _ONE)
|
|
||||||
return bits
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} egcdReturn A triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
* @property {bigint} g
|
|
||||||
* @property {bigint} x
|
|
||||||
* @property {bigint} y
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm.
|
|
||||||
* Take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {egcdReturn} A triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
*/
|
|
||||||
export function eGcd (a, b) {
|
|
||||||
a = BigInt(a)
|
|
||||||
b = BigInt(b)
|
|
||||||
if (a <= _ZERO | b <= _ZERO) { return NaN } // a and b MUST be positive
|
|
||||||
|
|
||||||
let x = _ZERO
|
|
||||||
let y = _ONE
|
|
||||||
let u = _ONE
|
|
||||||
let v = _ZERO
|
|
||||||
|
|
||||||
while (a !== _ZERO) {
|
|
||||||
const q = b / a
|
|
||||||
const r = b % a
|
|
||||||
const m = x - (u * q)
|
|
||||||
const n = y - (v * q)
|
|
||||||
b = a
|
|
||||||
a = r
|
|
||||||
x = u
|
|
||||||
y = v
|
|
||||||
u = m
|
|
||||||
v = n
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
b: b,
|
|
||||||
x: x,
|
|
||||||
y: y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Greatest-common divisor of two integers based on the iterative binary algorithm.
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} The greatest common divisor of a and b
|
|
||||||
*/
|
|
||||||
export function gcd (a, b) {
|
|
||||||
a = abs(a)
|
|
||||||
b = abs(b)
|
|
||||||
if (a === _ZERO) { return b } else if (b === _ZERO) { return a }
|
|
||||||
|
|
||||||
let shift = _ZERO
|
|
||||||
while (!((a | b) & _ONE)) {
|
|
||||||
a >>= _ONE
|
|
||||||
b >>= _ONE
|
|
||||||
shift++
|
|
||||||
}
|
|
||||||
while (!(a & _ONE)) a >>= _ONE
|
|
||||||
do {
|
|
||||||
while (!(b & _ONE)) b >>= _ONE
|
|
||||||
if (a > b) {
|
|
||||||
const x = a
|
|
||||||
a = b
|
|
||||||
b = x
|
|
||||||
}
|
|
||||||
b -= a
|
|
||||||
} while (b)
|
|
||||||
|
|
||||||
// rescale
|
|
||||||
return a << shift
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The test first tries if any of the first 250 small primes are a factor of the input number and then passes several
|
* The test first tries if any of the first 250 small primes are a factor of the input number and then passes several
|
||||||
* iterations of Miller-Rabin Probabilistic Primality Test (FIPS 186-4 C.3.1)
|
* iterations of Miller-Rabin Probabilistic Primality Test (FIPS 186-4 C.3.1)
|
||||||
*
|
*
|
||||||
* @param {number|bigint} w An integer to be tested for primality
|
* @param {number | bigint} w An integer to be tested for primality
|
||||||
* @param {number} [iterations = 16] The number of iterations for the primality test. The value shall be consistent with Table C.1, C.2 or C.3
|
* @param {number} [iterations = 16] The number of iterations for the primality test. The value shall be consistent with Table C.1, C.2 or C.3
|
||||||
*
|
*
|
||||||
* @return {Promise} A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
|
* @return {Promise<boolean>} A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
|
||||||
*/
|
*/
|
||||||
export async function isProbablyPrime (w, iterations = 16) {
|
export async function isProbablyPrime (w, iterations = 16) {
|
||||||
if (typeof w === 'number') {
|
if (typeof w === 'number') {
|
||||||
|
@ -170,96 +63,6 @@ export async function isProbablyPrime (w, iterations = 16) {
|
||||||
/* eslint-enable no-lone-blocks */
|
/* eslint-enable no-lone-blocks */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The least common multiple computed as abs(a*b)/gcd(a,b)
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} The least common multiple of a and b
|
|
||||||
*/
|
|
||||||
export function lcm (a, b) {
|
|
||||||
a = BigInt(a)
|
|
||||||
b = BigInt(b)
|
|
||||||
if (a === _ZERO && b === _ZERO) { return _ZERO }
|
|
||||||
return abs(a * b) / gcd(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum. max(a,b)==a if a>=b. max(a,b)==b if a<=b
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} maximum of numbers a and b
|
|
||||||
*/
|
|
||||||
export function max (a, b) {
|
|
||||||
a = BigInt(a)
|
|
||||||
b = BigInt(b)
|
|
||||||
return (a >= b) ? a : b
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Minimum. min(a,b)==b if a>=b. min(a,b)==a if a<=b
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} minimum of numbers a and b
|
|
||||||
*/
|
|
||||||
export function min (a, b) {
|
|
||||||
a = BigInt(a)
|
|
||||||
b = BigInt(b)
|
|
||||||
return (a >= b) ? b : a
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modular inverse.
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a The number to find an inverse for
|
|
||||||
* @param {number|bigint} n The modulo
|
|
||||||
*
|
|
||||||
* @returns {bigint} the inverse modulo n or NaN if it does not exist
|
|
||||||
*/
|
|
||||||
export function modInv (a, n) {
|
|
||||||
const egcd = eGcd(toZn(a, n), n)
|
|
||||||
if (egcd.b !== _ONE) {
|
|
||||||
return NaN // modular inverse does not exist
|
|
||||||
} else {
|
|
||||||
return toZn(egcd.x, n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modular exponentiation b**e mod n. Currently using the right-to-left binary method
|
|
||||||
*
|
|
||||||
* @param {number|bigint} b base
|
|
||||||
* @param {number|bigint} e exponent
|
|
||||||
* @param {number|bigint} n modulo
|
|
||||||
*
|
|
||||||
* @returns {bigint} b**e mod n
|
|
||||||
*/
|
|
||||||
export function modPow (b, e, n) {
|
|
||||||
n = BigInt(n)
|
|
||||||
if (n === _ZERO) { return NaN } else if (n === _ONE) { return _ZERO }
|
|
||||||
|
|
||||||
b = toZn(b, n)
|
|
||||||
|
|
||||||
e = BigInt(e)
|
|
||||||
if (e < _ZERO) {
|
|
||||||
return modInv(modPow(b, abs(e), n), n)
|
|
||||||
}
|
|
||||||
|
|
||||||
let r = _ONE
|
|
||||||
while (e > 0) {
|
|
||||||
if ((e % _TWO) === _ONE) {
|
|
||||||
r = (r * b) % n
|
|
||||||
}
|
|
||||||
e = e / _TWO
|
|
||||||
b = b ** _TWO % n
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
||||||
* The browser version uses web workers to parallelise prime look up. Therefore, it does not lock the UI
|
* The browser version uses web workers to parallelise prime look up. Therefore, it does not lock the UI
|
||||||
|
@ -270,13 +73,13 @@ export function modPow (b, e, n) {
|
||||||
* @param {number} bitLength The required bit length for the generated prime
|
* @param {number} bitLength The required bit length for the generated prime
|
||||||
* @param {number} [iterations = 16] The number of iterations for the Miller-Rabin Probabilistic Primality Test
|
* @param {number} [iterations = 16] The number of iterations for the Miller-Rabin Probabilistic Primality Test
|
||||||
*
|
*
|
||||||
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits.
|
* @returns {Promise<bigint>} A promise that resolves to a bigint probable prime of bitLength bits.
|
||||||
*/
|
*/
|
||||||
export function prime (bitLength, iterations = 16) {
|
export function prime (bitLength, iterations = 16) {
|
||||||
if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) }
|
if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) }
|
||||||
|
|
||||||
if (!process.browser && !_useWorkers) {
|
if (!process.browser && !_useWorkers) {
|
||||||
let rnd = _ZERO
|
let rnd = 0n
|
||||||
do {
|
do {
|
||||||
rnd = fromBuffer(randBytesSync(bitLength / 8, true))
|
rnd = fromBuffer(randBytesSync(bitLength / 8, true))
|
||||||
} while (!_isProbablyPrime(rnd, iterations))
|
} while (!_isProbablyPrime(rnd, iterations))
|
||||||
|
@ -311,7 +114,7 @@ export function prime (bitLength, iterations = 16) {
|
||||||
/* eslint-disable no-lone-blocks */
|
/* eslint-disable no-lone-blocks */
|
||||||
if (process.browser) { // browser
|
if (process.browser) { // browser
|
||||||
const workerURL = _isProbablyPrimeWorkerUrl()
|
const workerURL = _isProbablyPrimeWorkerUrl()
|
||||||
for (let i = 0; i < self.navigator.hardwareConcurrency; i++) {
|
for (let i = 0; i < self.navigator.hardwareConcurrency - 1; i++) {
|
||||||
const newWorker = new Worker(workerURL)
|
const newWorker = new Worker(workerURL)
|
||||||
newWorker.onmessage = (event) => _onmessage(event.data, newWorker)
|
newWorker.onmessage = (event) => _onmessage(event.data, newWorker)
|
||||||
workerList.push(newWorker)
|
workerList.push(newWorker)
|
||||||
|
@ -319,7 +122,7 @@ export function prime (bitLength, iterations = 16) {
|
||||||
} else { // Node.js
|
} else { // Node.js
|
||||||
const { cpus } = require('os')
|
const { cpus } = require('os')
|
||||||
const { Worker } = require('worker_threads')
|
const { Worker } = require('worker_threads')
|
||||||
for (let i = 0; i < cpus().length; i++) {
|
for (let i = 0; i < cpus().length - 1; i++) {
|
||||||
const newWorker = new Worker(__filename)
|
const newWorker = new Worker(__filename)
|
||||||
newWorker.on('message', (msg) => _onmessage(msg, newWorker))
|
newWorker.on('message', (msg) => _onmessage(msg, newWorker))
|
||||||
workerList.push(newWorker)
|
workerList.push(newWorker)
|
||||||
|
@ -349,7 +152,7 @@ export function prime (bitLength, iterations = 16) {
|
||||||
*/
|
*/
|
||||||
export function primeSync (bitLength, iterations = 16) {
|
export function primeSync (bitLength, iterations = 16) {
|
||||||
if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) }
|
if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) }
|
||||||
let rnd = _ZERO
|
let rnd = 0n
|
||||||
do {
|
do {
|
||||||
rnd = fromBuffer(randBytesSync(bitLength / 8, true))
|
rnd = fromBuffer(randBytesSync(bitLength / 8, true))
|
||||||
} while (!_isProbablyPrime(rnd, iterations))
|
} while (!_isProbablyPrime(rnd, iterations))
|
||||||
|
@ -363,7 +166,7 @@ export function primeSync (bitLength, iterations = 16) {
|
||||||
*
|
*
|
||||||
* @returns {bigint} A cryptographically secure random bigint between [min,max]
|
* @returns {bigint} A cryptographically secure random bigint between [min,max]
|
||||||
*/
|
*/
|
||||||
export function randBetween (max, min = _ONE) {
|
export function randBetween (max, min = 1n) {
|
||||||
if (max <= min) throw new Error('max must be > min')
|
if (max <= min) throw new Error('max must be > min')
|
||||||
const interval = max - min
|
const interval = max - min
|
||||||
const bitLen = bitLength(interval)
|
const bitLen = bitLength(interval)
|
||||||
|
@ -381,7 +184,7 @@ export function randBetween (max, min = _ONE) {
|
||||||
* @param {number} bitLength The desired number of random bits
|
* @param {number} bitLength The desired number of random bits
|
||||||
* @param {boolean} [forceLength = false] If we want to force the output to have a specific bit length. It basically forces the msb to be 1
|
* @param {boolean} [forceLength = false] If we want to force the output to have a specific bit length. It basically forces the msb to be 1
|
||||||
*
|
*
|
||||||
* @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
|
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
|
||||||
*/
|
*/
|
||||||
export function randBits (bitLength, forceLength = false) {
|
export function randBits (bitLength, forceLength = false) {
|
||||||
if (bitLength < 1) {
|
if (bitLength < 1) {
|
||||||
|
@ -408,7 +211,7 @@ export function randBits (bitLength, forceLength = false) {
|
||||||
* @param {number} byteLength The desired number of random bytes
|
* @param {number} byteLength The desired number of random bytes
|
||||||
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
||||||
*
|
*
|
||||||
* @returns {Promise} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
* @returns {Promise<Buffer | Uint8Array>} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
||||||
*/
|
*/
|
||||||
export function randBytes (byteLength, forceLength = false) {
|
export function randBytes (byteLength, forceLength = false) {
|
||||||
if (byteLength < 1) { throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`) }
|
if (byteLength < 1) { throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`) }
|
||||||
|
@ -441,7 +244,7 @@ export function randBytes (byteLength, forceLength = false) {
|
||||||
* @param {number} byteLength The desired number of random bytes
|
* @param {number} byteLength The desired number of random bytes
|
||||||
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
||||||
*
|
*
|
||||||
* @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
||||||
*/
|
*/
|
||||||
export function randBytesSync (byteLength, forceLength = false) {
|
export function randBytesSync (byteLength, forceLength = false) {
|
||||||
if (byteLength < 1) { throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`) }
|
if (byteLength < 1) { throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`) }
|
||||||
|
@ -460,25 +263,10 @@ export function randBytesSync (byteLength, forceLength = false) {
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the smallest positive element that is congruent to a in modulo n
|
|
||||||
* @param {number|bigint} a An integer
|
|
||||||
* @param {number|bigint} n The modulo
|
|
||||||
*
|
|
||||||
* @returns {bigint} The smallest positive representation of a in modulo n
|
|
||||||
*/
|
|
||||||
export function toZn (a, n) {
|
|
||||||
n = BigInt(n)
|
|
||||||
if (n <= 0) { return NaN }
|
|
||||||
|
|
||||||
a = BigInt(a) % n
|
|
||||||
return (a < 0) ? a + n : a
|
|
||||||
}
|
|
||||||
|
|
||||||
/* HELPER FUNCTIONS */
|
/* HELPER FUNCTIONS */
|
||||||
|
|
||||||
function fromBuffer (buf) {
|
function fromBuffer (buf) {
|
||||||
let ret = _ZERO
|
let ret = 0n
|
||||||
for (const i of buf.values()) {
|
for (const i of buf.values()) {
|
||||||
const bi = BigInt(i)
|
const bi = BigInt(i)
|
||||||
ret = (ret << BigInt(8)) + bi
|
ret = (ret << BigInt(8)) + bi
|
||||||
|
@ -488,7 +276,7 @@ function fromBuffer (buf) {
|
||||||
|
|
||||||
function _isProbablyPrimeWorkerUrl () {
|
function _isProbablyPrimeWorkerUrl () {
|
||||||
// Let's us first add all the required functions
|
// Let's us first add all the required functions
|
||||||
let workerCode = `'use strict';const _ZERO = BigInt(0);const _ONE = BigInt(1);const _TWO = BigInt(2);const eGcd = ${eGcd.toString()};const modInv = ${modInv.toString()};const modPow = ${modPow.toString()};const toZn = ${toZn.toString()};const randBits = ${randBits.toString()};const randBytesSync = ${randBytesSync.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`
|
let workerCode = `'use strict';const ${eGcd.name}=${eGcd.toString()};const ${modInv.name}=${modInv.toString()};const ${modPow.name}=${modPow.toString()};const ${toZn.name}=${toZn.toString()};const ${randBits.name}=${randBits.toString()};const ${randBytesSync.name}=${randBytesSync.toString()};const ${randBetween.name}=${randBetween.toString()};const ${isProbablyPrime.name}=${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`
|
||||||
|
|
||||||
const onmessage = async function (event) { // Let's start once we are called
|
const onmessage = async function (event) { // Let's start once we are called
|
||||||
// event.data = {rnd: <bigint>, iterations: <number>}
|
// event.data = {rnd: <bigint>, iterations: <number>}
|
||||||
|
@ -516,269 +304,269 @@ function _isProbablyPrime (w, iterations = 16) {
|
||||||
PREFILTERING. Even values but 2 are not primes, so don't test.
|
PREFILTERING. Even values but 2 are not primes, so don't test.
|
||||||
1 is not a prime and the M-R algorithm needs w>1.
|
1 is not a prime and the M-R algorithm needs w>1.
|
||||||
*/
|
*/
|
||||||
if (w === _TWO) { return true } else if ((w & _ONE) === _ZERO || w === _ONE) { return false }
|
if (w === 2n) { return true } else if ((w & 1n) === 0n || w === 1n) { return false }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test if any of the first 250 small primes are a factor of w. 2 is not tested because it was already tested above.
|
Test if any of the first 250 small primes are a factor of w. 2 is not tested because it was already tested above.
|
||||||
*/
|
*/
|
||||||
const firstPrimes = [
|
const firstPrimes = [
|
||||||
3,
|
3n,
|
||||||
5,
|
5n,
|
||||||
7,
|
7n,
|
||||||
11,
|
11n,
|
||||||
13,
|
13n,
|
||||||
17,
|
17n,
|
||||||
19,
|
19n,
|
||||||
23,
|
23n,
|
||||||
29,
|
29n,
|
||||||
31,
|
31n,
|
||||||
37,
|
37n,
|
||||||
41,
|
41n,
|
||||||
43,
|
43n,
|
||||||
47,
|
47n,
|
||||||
53,
|
53n,
|
||||||
59,
|
59n,
|
||||||
61,
|
61n,
|
||||||
67,
|
67n,
|
||||||
71,
|
71n,
|
||||||
73,
|
73n,
|
||||||
79,
|
79n,
|
||||||
83,
|
83n,
|
||||||
89,
|
89n,
|
||||||
97,
|
97n,
|
||||||
101,
|
101n,
|
||||||
103,
|
103n,
|
||||||
107,
|
107n,
|
||||||
109,
|
109n,
|
||||||
113,
|
113n,
|
||||||
127,
|
127n,
|
||||||
131,
|
131n,
|
||||||
137,
|
137n,
|
||||||
139,
|
139n,
|
||||||
149,
|
149n,
|
||||||
151,
|
151n,
|
||||||
157,
|
157n,
|
||||||
163,
|
163n,
|
||||||
167,
|
167n,
|
||||||
173,
|
173n,
|
||||||
179,
|
179n,
|
||||||
181,
|
181n,
|
||||||
191,
|
191n,
|
||||||
193,
|
193n,
|
||||||
197,
|
197n,
|
||||||
199,
|
199n,
|
||||||
211,
|
211n,
|
||||||
223,
|
223n,
|
||||||
227,
|
227n,
|
||||||
229,
|
229n,
|
||||||
233,
|
233n,
|
||||||
239,
|
239n,
|
||||||
241,
|
241n,
|
||||||
251,
|
251n,
|
||||||
257,
|
257n,
|
||||||
263,
|
263n,
|
||||||
269,
|
269n,
|
||||||
271,
|
271n,
|
||||||
277,
|
277n,
|
||||||
281,
|
281n,
|
||||||
283,
|
283n,
|
||||||
293,
|
293n,
|
||||||
307,
|
307n,
|
||||||
311,
|
311n,
|
||||||
313,
|
313n,
|
||||||
317,
|
317n,
|
||||||
331,
|
331n,
|
||||||
337,
|
337n,
|
||||||
347,
|
347n,
|
||||||
349,
|
349n,
|
||||||
353,
|
353n,
|
||||||
359,
|
359n,
|
||||||
367,
|
367n,
|
||||||
373,
|
373n,
|
||||||
379,
|
379n,
|
||||||
383,
|
383n,
|
||||||
389,
|
389n,
|
||||||
397,
|
397n,
|
||||||
401,
|
401n,
|
||||||
409,
|
409n,
|
||||||
419,
|
419n,
|
||||||
421,
|
421n,
|
||||||
431,
|
431n,
|
||||||
433,
|
433n,
|
||||||
439,
|
439n,
|
||||||
443,
|
443n,
|
||||||
449,
|
449n,
|
||||||
457,
|
457n,
|
||||||
461,
|
461n,
|
||||||
463,
|
463n,
|
||||||
467,
|
467n,
|
||||||
479,
|
479n,
|
||||||
487,
|
487n,
|
||||||
491,
|
491n,
|
||||||
499,
|
499n,
|
||||||
503,
|
503n,
|
||||||
509,
|
509n,
|
||||||
521,
|
521n,
|
||||||
523,
|
523n,
|
||||||
541,
|
541n,
|
||||||
547,
|
547n,
|
||||||
557,
|
557n,
|
||||||
563,
|
563n,
|
||||||
569,
|
569n,
|
||||||
571,
|
571n,
|
||||||
577,
|
577n,
|
||||||
587,
|
587n,
|
||||||
593,
|
593n,
|
||||||
599,
|
599n,
|
||||||
601,
|
601n,
|
||||||
607,
|
607n,
|
||||||
613,
|
613n,
|
||||||
617,
|
617n,
|
||||||
619,
|
619n,
|
||||||
631,
|
631n,
|
||||||
641,
|
641n,
|
||||||
643,
|
643n,
|
||||||
647,
|
647n,
|
||||||
653,
|
653n,
|
||||||
659,
|
659n,
|
||||||
661,
|
661n,
|
||||||
673,
|
673n,
|
||||||
677,
|
677n,
|
||||||
683,
|
683n,
|
||||||
691,
|
691n,
|
||||||
701,
|
701n,
|
||||||
709,
|
709n,
|
||||||
719,
|
719n,
|
||||||
727,
|
727n,
|
||||||
733,
|
733n,
|
||||||
739,
|
739n,
|
||||||
743,
|
743n,
|
||||||
751,
|
751n,
|
||||||
757,
|
757n,
|
||||||
761,
|
761n,
|
||||||
769,
|
769n,
|
||||||
773,
|
773n,
|
||||||
787,
|
787n,
|
||||||
797,
|
797n,
|
||||||
809,
|
809n,
|
||||||
811,
|
811n,
|
||||||
821,
|
821n,
|
||||||
823,
|
823n,
|
||||||
827,
|
827n,
|
||||||
829,
|
829n,
|
||||||
839,
|
839n,
|
||||||
853,
|
853n,
|
||||||
857,
|
857n,
|
||||||
859,
|
859n,
|
||||||
863,
|
863n,
|
||||||
877,
|
877n,
|
||||||
881,
|
881n,
|
||||||
883,
|
883n,
|
||||||
887,
|
887n,
|
||||||
907,
|
907n,
|
||||||
911,
|
911n,
|
||||||
919,
|
919n,
|
||||||
929,
|
929n,
|
||||||
937,
|
937n,
|
||||||
941,
|
941n,
|
||||||
947,
|
947n,
|
||||||
953,
|
953n,
|
||||||
967,
|
967n,
|
||||||
971,
|
971n,
|
||||||
977,
|
977n,
|
||||||
983,
|
983n,
|
||||||
991,
|
991n,
|
||||||
997,
|
997n,
|
||||||
1009,
|
1009n,
|
||||||
1013,
|
1013n,
|
||||||
1019,
|
1019n,
|
||||||
1021,
|
1021n,
|
||||||
1031,
|
1031n,
|
||||||
1033,
|
1033n,
|
||||||
1039,
|
1039n,
|
||||||
1049,
|
1049n,
|
||||||
1051,
|
1051n,
|
||||||
1061,
|
1061n,
|
||||||
1063,
|
1063n,
|
||||||
1069,
|
1069n,
|
||||||
1087,
|
1087n,
|
||||||
1091,
|
1091n,
|
||||||
1093,
|
1093n,
|
||||||
1097,
|
1097n,
|
||||||
1103,
|
1103n,
|
||||||
1109,
|
1109n,
|
||||||
1117,
|
1117n,
|
||||||
1123,
|
1123n,
|
||||||
1129,
|
1129n,
|
||||||
1151,
|
1151n,
|
||||||
1153,
|
1153n,
|
||||||
1163,
|
1163n,
|
||||||
1171,
|
1171n,
|
||||||
1181,
|
1181n,
|
||||||
1187,
|
1187n,
|
||||||
1193,
|
1193n,
|
||||||
1201,
|
1201n,
|
||||||
1213,
|
1213n,
|
||||||
1217,
|
1217n,
|
||||||
1223,
|
1223n,
|
||||||
1229,
|
1229n,
|
||||||
1231,
|
1231n,
|
||||||
1237,
|
1237n,
|
||||||
1249,
|
1249n,
|
||||||
1259,
|
1259n,
|
||||||
1277,
|
1277n,
|
||||||
1279,
|
1279n,
|
||||||
1283,
|
1283n,
|
||||||
1289,
|
1289n,
|
||||||
1291,
|
1291n,
|
||||||
1297,
|
1297n,
|
||||||
1301,
|
1301n,
|
||||||
1303,
|
1303n,
|
||||||
1307,
|
1307n,
|
||||||
1319,
|
1319n,
|
||||||
1321,
|
1321n,
|
||||||
1327,
|
1327n,
|
||||||
1361,
|
1361n,
|
||||||
1367,
|
1367n,
|
||||||
1373,
|
1373n,
|
||||||
1381,
|
1381n,
|
||||||
1399,
|
1399n,
|
||||||
1409,
|
1409n,
|
||||||
1423,
|
1423n,
|
||||||
1427,
|
1427n,
|
||||||
1429,
|
1429n,
|
||||||
1433,
|
1433n,
|
||||||
1439,
|
1439n,
|
||||||
1447,
|
1447n,
|
||||||
1451,
|
1451n,
|
||||||
1453,
|
1453n,
|
||||||
1459,
|
1459n,
|
||||||
1471,
|
1471n,
|
||||||
1481,
|
1481n,
|
||||||
1483,
|
1483n,
|
||||||
1487,
|
1487n,
|
||||||
1489,
|
1489n,
|
||||||
1493,
|
1493n,
|
||||||
1499,
|
1499n,
|
||||||
1511,
|
1511n,
|
||||||
1523,
|
1523n,
|
||||||
1531,
|
1531n,
|
||||||
1543,
|
1543n,
|
||||||
1549,
|
1549n,
|
||||||
1553,
|
1553n,
|
||||||
1559,
|
1559n,
|
||||||
1567,
|
1567n,
|
||||||
1571,
|
1571n,
|
||||||
1579,
|
1579n,
|
||||||
1583,
|
1583n,
|
||||||
1597
|
1597n
|
||||||
]
|
]
|
||||||
let p = _ZERO
|
|
||||||
for (let i = 0; i < firstPrimes.length && (p <= w); i++) {
|
for (let i = 0; i < firstPrimes.length && (firstPrimes[i] <= w); i++) {
|
||||||
p = BigInt(firstPrimes[i])
|
const p = firstPrimes[i]
|
||||||
if (w === p) {
|
if (w === p) {
|
||||||
return true
|
return true
|
||||||
} else if (w % p === _ZERO) {
|
} else if (w % p === 0n) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -802,29 +590,47 @@ function _isProbablyPrime (w, iterations = 16) {
|
||||||
Comment: Increment i for the do-loop in step 4.
|
Comment: Increment i for the do-loop in step 4.
|
||||||
5. Return PROBABLY PRIME.
|
5. Return PROBABLY PRIME.
|
||||||
*/
|
*/
|
||||||
let a = _ZERO; let d = w - _ONE
|
let a = 0n
|
||||||
while (d % _TWO === _ZERO) {
|
const d = w - 1n
|
||||||
d /= _TWO
|
let aux = d
|
||||||
|
while (aux % 2n === 0n) {
|
||||||
|
aux /= 2n
|
||||||
++a
|
++a
|
||||||
}
|
}
|
||||||
|
|
||||||
const m = (w - _ONE) / (_TWO ** a)
|
const m = d / (2n ** a)
|
||||||
|
|
||||||
/* eslint-disable no-labels */
|
// /* eslint-disable no-labels */
|
||||||
loop: do {
|
// loop: do {
|
||||||
const b = randBetween(w - _ONE, _TWO)
|
// const b = randBetween(w - 1n, 2n)
|
||||||
|
// let z = modPow(b, m, w)
|
||||||
|
// if (z === 1n || z === w - 1n) { continue }
|
||||||
|
// for (let j = 1; j < a; j++) {
|
||||||
|
// z = modPow(z, 2n, w)
|
||||||
|
// if (z === w - 1n) { continue loop }
|
||||||
|
// if (z === 1n) { break }
|
||||||
|
// }
|
||||||
|
// return false
|
||||||
|
// } while (--iterations)
|
||||||
|
// /* eslint-enable no-labels */
|
||||||
|
|
||||||
|
// return true
|
||||||
|
|
||||||
|
do {
|
||||||
|
const b = randBetween(d, 2n)
|
||||||
let z = modPow(b, m, w)
|
let z = modPow(b, m, w)
|
||||||
if (z === _ONE || z === w - _ONE) { continue }
|
if (z === 1n || z === d) { continue }
|
||||||
|
let j = 1
|
||||||
for (let j = 1; j < a; j++) {
|
while (j < a) {
|
||||||
z = modPow(z, _TWO, w)
|
z = modPow(z, 2n, w)
|
||||||
if (z === w - _ONE) { continue loop }
|
if (z === d) { break }
|
||||||
if (z === _ONE) { break }
|
if (z === 1n) { return false }
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
if (z !== d) {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
} while (--iterations)
|
} while (--iterations)
|
||||||
/* eslint-enable no-labels */
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,106 +1,13 @@
|
||||||
/**
|
|
||||||
* A triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
*/
|
|
||||||
export type egcdReturn = {
|
|
||||||
g: bigint;
|
|
||||||
x: bigint;
|
|
||||||
y: bigint;
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
*
|
|
||||||
* @returns {bigint} the absolute value of a
|
|
||||||
*/
|
|
||||||
export function abs(a: number | bigint): bigint;
|
|
||||||
/**
|
|
||||||
* Returns the bitlength of a number
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @returns {number} - the bit length
|
|
||||||
*/
|
|
||||||
export function bitLength(a: number | bigint): number;
|
|
||||||
/**
|
|
||||||
* @typedef {Object} egcdReturn A triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
* @property {bigint} g
|
|
||||||
* @property {bigint} x
|
|
||||||
* @property {bigint} y
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm.
|
|
||||||
* Take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {egcdReturn} A triple (g, x, y), such that ax + by = g = gcd(a, b).
|
|
||||||
*/
|
|
||||||
export function eGcd(a: number | bigint, b: number | bigint): egcdReturn;
|
|
||||||
/**
|
|
||||||
* Greatest-common divisor of two integers based on the iterative binary algorithm.
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} The greatest common divisor of a and b
|
|
||||||
*/
|
|
||||||
export function gcd(a: number | bigint, b: number | bigint): bigint;
|
|
||||||
/**
|
/**
|
||||||
* The test first tries if any of the first 250 small primes are a factor of the input number and then passes several
|
* The test first tries if any of the first 250 small primes are a factor of the input number and then passes several
|
||||||
* iterations of Miller-Rabin Probabilistic Primality Test (FIPS 186-4 C.3.1)
|
* iterations of Miller-Rabin Probabilistic Primality Test (FIPS 186-4 C.3.1)
|
||||||
*
|
*
|
||||||
* @param {number|bigint} w An integer to be tested for primality
|
* @param {number | bigint} w An integer to be tested for primality
|
||||||
* @param {number} [iterations = 16] The number of iterations for the primality test. The value shall be consistent with Table C.1, C.2 or C.3
|
* @param {number} [iterations = 16] The number of iterations for the primality test. The value shall be consistent with Table C.1, C.2 or C.3
|
||||||
*
|
*
|
||||||
* @return {Promise} A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
|
* @return {Promise<boolean>} A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
|
||||||
*/
|
*/
|
||||||
export function isProbablyPrime(w: number | bigint, iterations?: number): Promise<any>;
|
export function isProbablyPrime(w: number | bigint, iterations?: number): Promise<boolean>;
|
||||||
/**
|
|
||||||
* The least common multiple computed as abs(a*b)/gcd(a,b)
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} The least common multiple of a and b
|
|
||||||
*/
|
|
||||||
export function lcm(a: number | bigint, b: number | bigint): bigint;
|
|
||||||
/**
|
|
||||||
* Maximum. max(a,b)==a if a>=b. max(a,b)==b if a<=b
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} maximum of numbers a and b
|
|
||||||
*/
|
|
||||||
export function max(a: number | bigint, b: number | bigint): bigint;
|
|
||||||
/**
|
|
||||||
* Minimum. min(a,b)==b if a>=b. min(a,b)==a if a<=b
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a
|
|
||||||
* @param {number|bigint} b
|
|
||||||
*
|
|
||||||
* @returns {bigint} minimum of numbers a and b
|
|
||||||
*/
|
|
||||||
export function min(a: number | bigint, b: number | bigint): bigint;
|
|
||||||
/**
|
|
||||||
* Modular inverse.
|
|
||||||
*
|
|
||||||
* @param {number|bigint} a The number to find an inverse for
|
|
||||||
* @param {number|bigint} n The modulo
|
|
||||||
*
|
|
||||||
* @returns {bigint} the inverse modulo n or NaN if it does not exist
|
|
||||||
*/
|
|
||||||
export function modInv(a: number | bigint, n: number | bigint): bigint;
|
|
||||||
/**
|
|
||||||
* Modular exponentiation b**e mod n. Currently using the right-to-left binary method
|
|
||||||
*
|
|
||||||
* @param {number|bigint} b base
|
|
||||||
* @param {number|bigint} e exponent
|
|
||||||
* @param {number|bigint} n modulo
|
|
||||||
*
|
|
||||||
* @returns {bigint} b**e mod n
|
|
||||||
*/
|
|
||||||
export function modPow(b: number | bigint, e: number | bigint, n: number | bigint): bigint;
|
|
||||||
/**
|
/**
|
||||||
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
||||||
* The browser version uses web workers to parallelise prime look up. Therefore, it does not lock the UI
|
* The browser version uses web workers to parallelise prime look up. Therefore, it does not lock the UI
|
||||||
|
@ -111,9 +18,9 @@ export function modPow(b: number | bigint, e: number | bigint, n: number | bigin
|
||||||
* @param {number} bitLength The required bit length for the generated prime
|
* @param {number} bitLength The required bit length for the generated prime
|
||||||
* @param {number} [iterations = 16] The number of iterations for the Miller-Rabin Probabilistic Primality Test
|
* @param {number} [iterations = 16] The number of iterations for the Miller-Rabin Probabilistic Primality Test
|
||||||
*
|
*
|
||||||
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits.
|
* @returns {Promise<bigint>} A promise that resolves to a bigint probable prime of bitLength bits.
|
||||||
*/
|
*/
|
||||||
export function prime(bitLength: number, iterations?: number): Promise<any>;
|
export function prime(bitLength: number, iterations?: number): Promise<bigint>;
|
||||||
/**
|
/**
|
||||||
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
|
||||||
* The sync version is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript. Please consider using prime() instead.
|
* The sync version is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript. Please consider using prime() instead.
|
||||||
|
@ -138,7 +45,7 @@ export function randBetween(max: bigint, min?: bigint): bigint;
|
||||||
* @param {number} bitLength The desired number of random bits
|
* @param {number} bitLength The desired number of random bits
|
||||||
* @param {boolean} [forceLength = false] If we want to force the output to have a specific bit length. It basically forces the msb to be 1
|
* @param {boolean} [forceLength = false] If we want to force the output to have a specific bit length. It basically forces the msb to be 1
|
||||||
*
|
*
|
||||||
* @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
|
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
|
||||||
*/
|
*/
|
||||||
export function randBits(bitLength: number, forceLength?: boolean): Uint8Array | Buffer;
|
export function randBits(bitLength: number, forceLength?: boolean): Uint8Array | Buffer;
|
||||||
/**
|
/**
|
||||||
|
@ -147,23 +54,16 @@ export function randBits(bitLength: number, forceLength?: boolean): Uint8Array |
|
||||||
* @param {number} byteLength The desired number of random bytes
|
* @param {number} byteLength The desired number of random bytes
|
||||||
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
||||||
*
|
*
|
||||||
* @returns {Promise} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
* @returns {Promise<Buffer | Uint8Array>} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
||||||
*/
|
*/
|
||||||
export function randBytes(byteLength: number, forceLength?: boolean): Promise<any>;
|
export function randBytes(byteLength: number, forceLength?: boolean): Promise<Uint8Array | Buffer>;
|
||||||
/**
|
/**
|
||||||
* Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
|
* Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
|
||||||
*
|
*
|
||||||
* @param {number} byteLength The desired number of random bytes
|
* @param {number} byteLength The desired number of random bytes
|
||||||
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
* @param {boolean} [forceLength = false] If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
|
||||||
*
|
*
|
||||||
* @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
||||||
*/
|
*/
|
||||||
export function randBytesSync(byteLength: number, forceLength?: boolean): Uint8Array | Buffer;
|
export function randBytesSync(byteLength: number, forceLength?: boolean): Uint8Array | Buffer;
|
||||||
/**
|
export { abs, bitLength, eGcd, gcd, lcm, max, min, modInv, modPow, toZn } from "bigint-mod-arith";
|
||||||
* Finds the smallest positive element that is congruent to a in modulo n
|
|
||||||
* @param {number|bigint} a An integer
|
|
||||||
* @param {number|bigint} n The modulo
|
|
||||||
*
|
|
||||||
* @returns {bigint} The smallest positive representation of a in modulo n
|
|
||||||
*/
|
|
||||||
export function toZn(a: number | bigint, n: number | bigint): bigint;
|
|
||||||
|
|
Loading…
Reference in New Issue