project migrated to typescript

This commit is contained in:
Juanra Dikal 2021-03-25 13:40:04 +01:00
parent 653fbd87fe
commit 8cf28b7587
80 changed files with 12817 additions and 6951 deletions

View File

@ -33,49 +33,49 @@ jobs:
- name: test
run: npm test
publication:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
# publication:
# needs: build
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v2
- uses: EndBug/version-check@v1
id: check
# - uses: EndBug/version-check@v1
# id: check
- name: check version changes
if: steps.check.outputs.changed == 'true'
run: 'echo "Version change found! New version: ${{ steps.check.outputs.version }} (${{ steps.check.outputs.type }})"'
# - name: check version changes
# if: steps.check.outputs.changed == 'true'
# run: 'echo "Version change found! New version: ${{ steps.check.outputs.version }} (${{ steps.check.outputs.type }})"'
- uses: actions/setup-node@v1
if: steps.check.outputs.changed == 'true'
with:
node-version: 12
registry-url: https://registry.npmjs.org/
# - uses: actions/setup-node@v1
# if: steps.check.outputs.changed == 'true'
# with:
# node-version: 14
# registry-url: https://registry.npmjs.org/
- name: install
if: steps.check.outputs.changed == 'true'
run: npm ci
# - name: install
# if: steps.check.outputs.changed == 'true'
# run: npm ci
- name: build
if: steps.check.outputs.changed == 'true'
run: npm run build
# - name: build
# if: steps.check.outputs.changed == 'true'
# run: npm run build
- name: test
if: steps.check.outputs.changed == 'true'
run: npm test
# - name: test
# if: steps.check.outputs.changed == 'true'
# run: npm test
- name: create code coverage report
if: steps.check.outputs.changed == 'true'
run: npm run coverage
# - name: create code coverage report
# if: steps.check.outputs.changed == 'true'
# run: npm run coverage
- name: send report to coveralls.io
if: steps.check.outputs.changed == 'true'
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
# - name: send report to coveralls.io
# if: steps.check.outputs.changed == 'true'
# uses: coverallsapp/github-action@master
# with:
# github-token: ${{ secrets.GITHUB_TOKEN }}
- name: publish to NPM
if: steps.check.outputs.changed == 'true'
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# - name: publish to NPM
# if: steps.check.outputs.changed == 'true'
# run: npm publish
# env:
# NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

13
.gitignore vendored
View File

@ -4,17 +4,14 @@ logs
npm-debug.log*
# Dependency directories
node_modules/
node_modules
# Output of 'npm pack'
*.tgz
# Visual Studio Code
.vscode
# IntelliJ
.idea
# MYC output
.nyc_output
coverage/*
coverage
# Test temporal files
.mocha-ts

View File

@ -1,14 +1,9 @@
# Build scripts
build/*
# Source files
src/*
build
# Test files
test/*
# Example files
examples/*
test
**/*.spec.ts
# Logs
logs
@ -26,10 +21,19 @@ npm-debug.log*
# MYC output
.nyc_output
coverage/*
# Travis
.travis.yml
coverage
# GitHub
.github
.github
# tsconfig
tsconfig.json
# SRC docs
src/docs
# Test temporal files
.mocha-ts
# Examples
examples

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}

480
README.md
View File

@ -1,6 +1,6 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
![Node CI](https://github.com/juanelas/bigint-crypto-utils/workflows/Node%20CI/badge.svg)
[![Node CI](https://github.com/juanelas/bigint-crypto-utils/workflows/Node%20CI/badge.svg)](https://github.com/juanelas/bigint-crypto-utils/actions?query=workflow%3A%22Node+CI%22)
[![Coverage Status](https://coveralls.io/repos/github/juanelas/bigint-crypto-utils/badge.svg?branch=master)](https://coveralls.io/github/juanelas/bigint-crypto-utils?branch=master)
# bigint-crypto-utils
@ -13,89 +13,61 @@ Secure random numbers are generated using the native crypto implementation of th
> The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html).** Many platforms provide native support for cryptography, such as [Web Cryptography API](https://w3c.github.io/webcrypto/) or [Node.js Crypto](https://nodejs.org/dist/latest/docs/api/crypto.html).
## Installation
## Usage
bigint-crypto-utils can be imported to your project with `npm`:
`bigint-crypto-utils` can be imported to your project with `npm`:
```bash
```console
npm install bigint-crypto-utils
```
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 bundle](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.iife.js) or the [ESM bundle](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.mod.js) from the repository.
Then either require (Node.js CJS):
## Usage examples
```javascript
const bigintCryptoUtils = require('bigint-crypto-utils')
```
Import your module as :
or import (JavaScript ES module):
- Node.js
```javascript
import * as bigintCryptoUtils from 'bigint-crypto-utils'
```
```javascript
const bigintCryptoUtils = require('bigint-crypto-utils')
... // your code here
```
The appropriate version for browser or node is automatically exported.
- JavaScript native or TypeScript project (including React and Angular JS)
`bigint-crypto-utils` **CANNOT BE POLYFILLED** to suport older JS version (\< ES2020). If you are using webpack/babel to create your production bundles, you should target only the most modern browsers. For instance, for **React** apps created with [`create-react-app`](https://create-react-app.dev/), you should edit your `package.json` and modify the `browserList` so that it only targets the latest browsers (play with the number of versions that do not need polyfilling):
```javascript
import * as bigintCryptoUtils from 'bigint-crypto-utils'
... // your code here
```
```json
"browserslist": {
"production": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
```
`bigint-crypto-utils` **CANNOT BE POLYFILLED** to suport older browsers. If you are using webpack/babel to create your production bundles, you should target only the most modern browsers. For instance, for **React** apps created with [`create-react-app`](https://create-react-app.dev/), you should edit your `package.json` and modify the `browserList` so that it only targets the latest browsers (play with the number of versions that do not need polyfilling):
Also, notice that [BigInt implementation is ES2020](https://tc39.es/ecma262/#sec-bigint-objects). In order to use it with TypeScript you need to set `target` to `ES2020` in your project's `tsconfig.json`.
```json
"browserslist": {
"production": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
```
If you are using Angular, since this library uses node typings, you should also add them to the `angularCompilerOptions` in your `tsconfig.json`:
Also, notice that [BigInt implementation is ES2020](https://tc39.es/ecma262/#sec-bigint-objects). In order to use it with TypeScript you will probably need to set `lib`, `target` and/or `module` to `es2020` in your project's `tsconfig.json`.
```json
"angularCompilerOptions": {
"types": ["node", ...]
...
}
```
If you are using Angular, since this library uses node typings, you should also add them to the `angularCompilerOptions` in your `tsconfig.json`:
```json
"angularCompilerOptions": {
"types": ["node"]
...
}
```
- JavaScript native browser ES module
```html
<script type="module">
import * as bigintCryptoUtils from 'index.browser.bundle.mod.js' // Use your actual path to the broser mod bundle that is in the lib directory
... // your code here
</script>
```
- JavaScript native browser IIFE
```html
<head>
...
<script src="index.browser.bundle.iife.js"></script> <!-- Use your actual path to the browser iife bundle that is in the lib directory -->
</head>
<body>
...
<script>
... // your code here
</script>
</body>
```
You can also download the [IIFE bundle](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/dist/bundles/bigint-crypto-utils.iife.js), the [ESM bundle](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/dist/bundles/bigint-crypto-utils.esm.js) or the [UMD bundle](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/dist/bundles/bigint-crypto-utils.umd.js) and manually add it to your project, or, if you have already imported `bigint-crypto-utils` to your project, just get the bundles from `node_modules/bigint-crypto-utils/dist/bundles/`.
An example of usage could be:
```javascript
```typescript
/* A BigInt with value 666 can be declared calling the bigint constructor as
BigInt('666') or with the shorter 666n.
Notice that you can also pass a number to the constructor, e.g. BigInt(666).
@ -114,14 +86,14 @@ console.log(bigintCryptoUtils.modInv(BigInt('3'), BigInt('5'))) // prints 2
console.log(bigintCryptoUtils.randBetween(2n ** 256n)) // Prints a cryptographically secure random number between 1 and 2**256 bits.
async function primeTesting () {
async function primeTesting (): void {
// Output of a probable prime of 2048 bits
console.log(await bigintCryptoUtils.prime(2048))
// Testing if a number is a probable prime (Miller-Rabin)
const number = 27n
const isPrime = await bigintCryptoUtils.isProbablyPrime(number)
if (isPrime) {
if (isPrime === true) {
console.log(`${number} is prime`)
} else {
console.log(`${number} is composite`)
@ -132,376 +104,6 @@ primeTesting()
```
You can find examples in the [examples folder of the repository](https://github.com/juanelas/bigint-crypto-utils/tree/master/examples).
## 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&gt;=0. abs(a)==-a if a&lt;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], [disableWorkers])</a><code>Promise.&lt;boolean&gt;</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&gt;=b. max(a,b)==b if a&lt;=b</p>
</dd>
<dt><a href="#min">min(a, b)</a><code>bigint</code></dt>
<dd><p>Minimum. min(a,b)==b if a&gt;=b. min(a,b)==a if a&lt;=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.&lt;bigint&gt;</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 &gt;=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&#39;t use workers and thus it&#39;ll be slower and may freeze thw window in browser&#39;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]. Both numbers must be &gt;=0</p>
</dd>
<dt><a href="#randBits">randBits(bitLength, [forceLength])</a><code>Promise.&lt;(Buffer|Uint8Array)&gt;</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="#randBitsSync">randBitsSync(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.&lt;(Buffer|Uint8Array)&gt;</code></dt>
<dd><p>Secure random bytes for both node and browsers. Node version uses crypto.randomBytes() 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>
### abs(a) ⇒ <code>bigint</code>
Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
**Kind**: global function
**Returns**: <code>bigint</code> - the absolute value of a
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
<a name="bitLength"></a>
### bitLength(a) ⇒ <code>number</code>
Returns the bitlength of a number
**Kind**: global function
**Returns**: <code>number</code> - - the bit length
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
<a name="eGcd"></a>
### eGcd(a, b) ⇒ [<code>egcdReturn</code>](#egcdReturn)
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).
**Kind**: global function
**Returns**: [<code>egcdReturn</code>](#egcdReturn) - A triple (g, x, y), such that ax + by = g = gcd(a, b).
**Throws**:
- <code>RangeError</code> a and b MUST be > 0
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> |
<a name="egcdReturn"></a>
### egcdReturn : <code>Object</code>
A triple (g, x, y), such that ax + by = g = gcd(a, b).
**Kind**: global typedef
**Properties**
| Name | Type |
| --- | --- |
| g | <code>bigint</code> |
| x | <code>bigint</code> |
| y | <code>bigint</code> |
<a name="gcd"></a>
### gcd(a, b) ⇒ <code>bigint</code>
Greatest-common divisor of two integers based on the iterative binary algorithm.
**Kind**: global function
**Returns**: <code>bigint</code> - The greatest common divisor of a and b
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> |
<a name="isProbablyPrime"></a>
### isProbablyPrime(w, [iterations], [disableWorkers]) ⇒ <code>Promise.&lt;boolean&gt;</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.&lt;boolean&gt;</code> - A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
**Throws**:
- <code>RangeError</code> w MUST be >= 0
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| w | <code>number</code> \| <code>bigint</code> | | A positive 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 |
| [disableWorkers] | <code>boolean</code> | <code>false</code> | Disable the use of workers for the primality test |
<a name="lcm"></a>
### lcm(a, b) ⇒ <code>bigint</code>
The least common multiple computed as abs(a*b)/gcd(a,b)
**Kind**: global function
**Returns**: <code>bigint</code> - The least common multiple of a and b
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> |
<a name="max"></a>
### max(a, b) ⇒ <code>bigint</code>
Maximum. max(a,b)==a if a>=b. max(a,b)==b if a<=b
**Kind**: global function
**Returns**: <code>bigint</code> - maximum of numbers a and b
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> |
<a name="min"></a>
### min(a, b) ⇒ <code>bigint</code>
Minimum. min(a,b)==b if a>=b. min(a,b)==a if a<=b
**Kind**: global function
**Returns**: <code>bigint</code> - minimum of numbers a and b
| Param | Type |
| --- | --- |
| a | <code>number</code> \| <code>bigint</code> |
| b | <code>number</code> \| <code>bigint</code> |
<a name="modInv"></a>
### modInv(a, n) ⇒ <code>bigint</code>
Modular inverse.
**Kind**: global function
**Returns**: <code>bigint</code> - the inverse modulo n
**Throws**:
- <code>RangeError</code> a does not have inverse modulo n
| Param | Type | Description |
| --- | --- | --- |
| a | <code>number</code> \| <code>bigint</code> | The number to find an inverse for |
| n | <code>number</code> \| <code>bigint</code> | The modulo |
<a name="modPow"></a>
### modPow(b, e, n) ⇒ <code>bigint</code>
Modular exponentiation b**e mod n. Currently using the right-to-left binary method
**Kind**: global function
**Returns**: <code>bigint</code> - b**e mod n
| Param | Type | Description |
| --- | --- | --- |
| b | <code>number</code> \| <code>bigint</code> | base |
| e | <code>number</code> \| <code>bigint</code> | exponent |
| n | <code>number</code> \| <code>bigint</code> | modulo |
<a name="prime"></a>
### prime(bitLength, [iterations]) ⇒ <code>Promise.&lt;bigint&gt;</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.&lt;bigint&gt;</code> - A promise that resolves to a bigint probable prime of bitLength bits.
**Throws**:
- <code>RangeError</code> bitLength MUST be > 0
| 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.
**Throws**:
- <code>RangeError</code> bitLength MUST be > 0
| 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]. Both numbers must be >=0
**Kind**: global function
**Returns**: <code>bigint</code> - A cryptographically secure random bigint between [min,max]
**Throws**:
- <code>RangeError</code> Arguments MUST be: max > 0 && min >=0 && max > min
| 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>Promise.&lt;(Buffer\|Uint8Array)&gt;</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>Promise.&lt;(Buffer\|Uint8Array)&gt;</code> - A Promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
**Throws**:
- <code>RangeError</code> bitLength MUST be > 0
| 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="randBitsSync"></a>
### randBitsSync(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
**Throws**:
- <code>RangeError</code> bitLength MUST be > 0
| 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.&lt;(Buffer\|Uint8Array)&gt;</code>
Secure random bytes for both node and browsers. Node version uses crypto.randomBytes() and browser one self.crypto.getRandomValues()
**Kind**: global function
**Returns**: <code>Promise.&lt;(Buffer\|Uint8Array)&gt;</code> - A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
**Throws**:
- <code>RangeError</code> byteLength MUST be > 0
| 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
**Throws**:
- <code>RangeError</code> byteLength MUST be > 0
| 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>
### toZn(a, n) ⇒ <code>bigint</code>
Finds the smallest positive element that is congruent to a in modulo n
**Kind**: global function
**Returns**: <code>bigint</code> - The smallest positive representation of a in modulo n
| Param | Type | Description |
| --- | --- | --- |
| a | <code>number</code> \| <code>bigint</code> | An integer |
| n | <code>number</code> \| <code>bigint</code> | The modulo |
[Check the API](./docs/API.md)

73
build/bin/mocha-ts.js Normal file
View File

@ -0,0 +1,73 @@
#! /usr/bin/env node
const path = require('path')
const childProcess = require('child_process')
const rootDir = path.join(__dirname, '../..')
const mochaTsRelativeDir = '.mocha-ts'
const minimatch = require('minimatch')
const glob = require('glob')
// First let us prepare the args to pass to mocha.
// ts.files will be replaced by their js-transpiled counterparts
// a watch file to our semaphore will be added
const processedArgs = processArgs(process.argv.slice(2))
// Now we can run a script and invoke a callback when complete, e.g.
runScript(path.join(rootDir, 'node_modules/.bin/mocha'), processArgs(processedArgs))
function processArgs (args) {
args = process.argv.slice(2).map(arg => {
const filenames = glob.sync(arg, { cwd: rootDir, matchBase: true })
if (filenames.length > 0) {
return filenames.map(file => {
const isTsTestFile = minimatch(file, '{test/**/*.ts,src/**/*.spec.ts}', { matchBase: true })
if (isTsTestFile) {
return `${mochaTsRelativeDir}/${file.slice(0, -3)}.js`
}
return file
})
}
return arg
})
const processedArgs = []
let addSemaphore = false
let semaphoreAdded = false
for (const arg of args) {
if (Array.isArray(arg)) {
processedArgs.push(...arg)
} else {
processedArgs.push(arg)
if (arg === '--watch' || arg === '-w') {
addSemaphore = true
} else if (arg === '--watch-files') {
processedArgs.push(`${mochaTsRelativeDir}/semaphore`)
semaphoreAdded = true
}
}
}
if (addSemaphore === true || semaphoreAdded === false) {
processedArgs.push('--watch-files')
processedArgs.push(`${mochaTsRelativeDir}/semaphore`)
}
return processedArgs
}
function runScript (scriptPath, args) {
const mochaCmd = childProcess.fork(path.join(rootDir, 'node_modules/.bin/mocha'), processedArgs, {
cwd: rootDir
})
mochaCmd.on('error', (error) => {
throw error
})
// execute the callback once the process has finished running
mochaCmd.on('exit', function (code) {
if (code !== 0) {
throw new Error('exit code ' + code)
}
})
}

View File

@ -1,7 +1,7 @@
'use strict'
const fs = require('fs')
const jsdoc2md = require('jsdoc-to-markdown')
const TypeDoc = require('typedoc')
const path = require('path')
const pkgJson = require('../package.json')
@ -14,6 +14,33 @@ function camelise (str) {
})
}
async function typedoc () {
const app = new TypeDoc.Application()
// If you want TypeDoc to load tsconfig.json / typedoc.json files
app.options.addReader(new TypeDoc.TSConfigReader())
app.options.addReader(new TypeDoc.TypeDocReader())
app.bootstrap({
// typedoc options here
entryPoints: ['src/index.ts'],
plugin: ['typedoc-plugin-markdown'],
includeVersion: true,
entryDocument: 'API.md',
readme: 'none'
})
const project = app.convert()
if (project) {
// Project may not have converted correctly
const output = path.join(rootDir, './docs')
// Rendered docs
await app.generateDocs(project, output)
}
}
function getRepositoryData () {
if (typeof pkgJson.repository === 'string') {
const repodata = pkgJson.repository.split(/[:/]/)
@ -30,40 +57,45 @@ function getRepositoryData () {
const { repoProvider, repoUsername, repoName } = getRepositoryData() || { repoProvider: null, repoUsername: null, repoName: null }
let iifeBundle, esmBundle, workflowBadget, coverallsBadge
if (repoProvider && repoProvider === 'github') {
iifeBundle = `[IIFE bundle](https://raw.githubusercontent.com/${repoUsername}/${repoName}/master/lib/index.browser.bundle.iife.js)`
esmBundle = `[ESM bundle](https://raw.githubusercontent.com/${repoUsername}/${repoName}/master/lib/index.browser.bundle.mod.js)`
workflowBadget = `![Node CI](https://github.com/${repoUsername}/${repoName}/workflows/Node%20CI/badge.svg)`
coverallsBadge = `[![Coverage Status](https://coveralls.io/repos/github/${repoUsername}/${repoName}/badge.svg?branch=master)](https://coveralls.io/github/${repoUsername}/${repoName}?branch=master)`
const regex = /^(?:(?<scope>@.*?)\/)?(?<name>.*)/ // We are going to take only the package name part if there is a scope, e.g. @my-org/package-name
const { name } = pkgJson.name.match(regex).groups
const camelCaseName = camelise(name)
let iifeBundle, esmBundle, umdBundle, workflowBadget, coverallsBadge
if (repoProvider) {
switch (repoProvider) {
case 'github':
iifeBundle = `[IIFE bundle](https://raw.githubusercontent.com/${repoUsername}/${repoName}/master/dist/bundles/${name}.iife.js)`
esmBundle = `[ESM bundle](https://raw.githubusercontent.com/${repoUsername}/${repoName}/master/dist/bundles/${name}.esm.js)`
umdBundle = `[UMD bundle](https://raw.githubusercontent.com/${repoUsername}/${repoName}/master/dist/bundles/${name}.umd.js)`
workflowBadget = `[![Node CI](https://github.com/${repoUsername}/${repoName}/workflows/Node%20CI/badge.svg)](https://github.com/${repoUsername}/${repoName}/actions?query=workflow%3A%22Node+CI%22)`
coverallsBadge = `[![Coverage Status](https://coveralls.io/repos/github/${repoUsername}/${repoName}/badge.svg?branch=master)](https://coveralls.io/github/${repoUsername}/${repoName}?branch=master)`
break
case 'gitlab':
iifeBundle = `[IIFE bundle](https://gitlab.com/${repoUsername}/${repoName}/-/raw/master/dist/bundles/${name}.iife.js?inline=false)`
esmBundle = `[ESM bundle](https://gitlab.com/${repoUsername}/${repoName}/-/raw/master/dist/bundles/${name}.esm.js?inline=false)`
umdBundle = `[IIFE bundle](https://gitlab.com/${repoUsername}/${repoName}/-/raw/master/dist/bundles/${name}.umd.js?inline=false)`
break
default:
break
}
}
const templateFile = path.join(rootDir, pkgJson.directories.src, 'doc', 'readme-template.md')
const templateFile = path.join(rootDir, pkgJson.directories.src, 'docs/index.md')
let template = fs.readFileSync(templateFile, { encoding: 'UTF-8' })
.replace(/\{\{PKG_NAME\}\}/g, pkgJson.name)
.replace(/\{\{PKG_CAMELCASE\}\}/g, camelise(pkgJson.name))
.replace(/\{\{PKG_CAMELCASE\}\}/g, camelCaseName)
.replace(/\{\{IIFE_BUNDLE\}\}/g, iifeBundle || 'IIFE bundle')
.replace(/\{\{ESM_BUNDLE\}\}/g, esmBundle || 'ESM bundle')
.replace(/\{\{UMD_BUNDLE\}\}/g, umdBundle || 'UMD bundle')
if (repoProvider && repoProvider === 'github') {
template = template.replace(/\{\{GITHUB_ACTIONS_BADGES\}\}/g, workflowBadget + '\n' + coverallsBadge)
}
const input = path.join(rootDir, pkgJson.browser)
// Let us replace bigint literals by standard numbers to avoid issues with bigint
const source = fs.readFileSync(input, { encoding: 'UTF-8' }).replace(/([0-9]+)n([,\s\n)])/g, '$1$2')
const readmeFile = path.join(rootDir, 'README.md')
fs.writeFileSync(readmeFile, template)
jsdoc2md.clear().then(() => {
const data = jsdoc2md.getTemplateDataSync({ source })
data.sort((fn1, fn2) => (fn1.id > fn2.id) ? 1 : -1) // sort functions alphabetically
const options = {
data,
template,
'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)
})
typedoc()

View File

@ -1,25 +0,0 @@
const fs = require('fs')
const ts = require('typescript')
const path = require('path')
const pkgJson = require('../package.json')
const rootDir = path.join(__dirname, '..')
const jsFile = path.join(rootDir, pkgJson.browser)
const dtsFile = path.join(rootDir, pkgJson.types)
const compilerOptions = {
declaration: true,
noEmit: false,
emitDeclarationOnly: true,
allowJs: true
}
const host = ts.createCompilerHost(compilerOptions)
host.writeFile = (fileName, contents) => {
fs.writeFileSync(dtsFile, contents)
}
// Prepare and emit the d.ts files
const program = ts.createProgram([jsFile], compilerOptions, host)
program.emit()

View File

@ -3,13 +3,16 @@
const resolve = require('@rollup/plugin-node-resolve').nodeResolve
const replace = require('@rollup/plugin-replace')
const { terser } = require('rollup-plugin-terser')
const typescriptPlugin = require('@rollup/plugin-typescript')
const commonjs = require('@rollup/plugin-commonjs')
const path = require('path')
const fs = require('fs')
const pkgJson = require('../package.json')
const rootDir = path.join(__dirname, '..')
const srcDir = path.join(rootDir, pkgJson.directories.src)
const dstDir = path.join(rootDir, pkgJson.directories.lib)
const dstDir = path.join(rootDir, pkgJson.directories.dist)
const srcDir = path.join(rootDir, 'src')
function camelise (str) {
return str.replace(/-([a-z])/g,
@ -18,61 +21,113 @@ function camelise (str) {
})
}
const pkgName = pkgJson.name
const pkgCamelisedName = camelise(pkgName)
const regex = /^(?:(?<scope>@.*?)\/)?(?<name>.*)/ // We are going to take only the package name part if there is a scope, e.g. @my-org/package-name
const { name } = pkgJson.name.match(regex).groups
const pkgCamelisedName = camelise(name)
const input = path.join(srcDir, 'js', 'index.js')
const input = path.join(srcDir, 'index.ts')
if (fs.existsSync(input) !== true) throw new Error('The entry point should be index.ts')
const tsBundleOptions = {
exclude: ['test/**/*', 'src/**/*.spec.ts', './build/typings/global-this-pkg.d.ts']
}
const external = [...Object.keys(pkgJson.dependencies || {}), ...Object.keys(pkgJson.peerDependencies || {})]
const sourcemapOutputOptions = {
sourcemap: 'inline',
sourcemapExcludeSources: true
}
module.exports = [
{ // Native JS
{ // ESM for browsers
input: input,
output: [
{
file: path.join(rootDir, pkgJson.browser),
file: path.join(rootDir, pkgJson.exports['.'].default),
...sourcemapOutputOptions,
format: 'es'
}
],
plugins: [
replace({
'process.browser': true
})
]
IS_BROWSER: true,
preventAssignment: true
}),
typescriptPlugin(tsBundleOptions)
],
external
},
{ // Browser bundles
input: input,
output: [
{
file: path.join(dstDir, 'index.browser.bundle.iife.js'),
file: path.join(dstDir, `bundles/${name}.iife.js`),
format: 'iife',
name: pkgCamelisedName
},
{
file: path.join(dstDir, 'index.browser.bundle.mod.js'),
file: path.join(dstDir, `bundles/${name}.esm.js`),
format: 'es'
},
{
file: path.join(dstDir, `bundles/${name}.umd.js`),
format: 'umd',
name: pkgCamelisedName
}
],
plugins: [
replace({
'process.browser': true
IS_BROWSER: true,
preventAssignment: true
}),
typescriptPlugin(tsBundleOptions),
resolve({
browser: true
browser: true,
exportConditions: ['browser', 'module', 'import', 'default']
}),
terser()
]
},
{ // Node
{ // Node ESM with declaration files
input: input,
output: {
file: path.join(rootDir, pkgJson.main),
format: 'cjs',
esModule: false,
externalLiveBindings: false
dir: path.join(rootDir, path.dirname(pkgJson.exports['.'].node.import)),
entryFileNames: path.basename(pkgJson.exports['.'].node.import),
...sourcemapOutputOptions,
format: 'es'
},
plugins: [
replace({
'process.browser': false
})
IS_BROWSER: false,
preventAssignment: true
}),
typescriptPlugin({
...tsBundleOptions,
declaration: true,
outDir: path.join(rootDir, path.dirname(pkgJson.exports['.'].node.import)),
declarationDir: path.join(rootDir, path.dirname(pkgJson.exports['.'].node.import), 'types'),
declarationMap: true
}),
commonjs({ extensions: ['.js', '.ts'] }) // the ".ts" extension is required
],
external
},
{ // Node CJS
input: input,
output: {
dir: path.join(rootDir, path.dirname(pkgJson.exports['.'].node.require)),
entryFileNames: path.basename(pkgJson.exports['.'].node.require),
...sourcemapOutputOptions,
format: 'cjs'
},
plugins: [
replace({
IS_BROWSER: false,
preventAssignment: true
}),
typescriptPlugin(tsBundleOptions),
commonjs({ extensions: ['.js', '.ts'] }) // the ".ts" extension is required
]
}
]

View File

@ -1,62 +0,0 @@
'use strict'
const resolve = require('@rollup/plugin-node-resolve').nodeResolve
const replace = require('@rollup/plugin-replace')
const commonjs = require('@rollup/plugin-commonjs')
const multi = require('@rollup/plugin-multi-entry')
const fs = require('fs')
const path = require('path')
const pkgJson = require('../package.json')
const pkgJsonLock = require('../package-lock.json')
const mochaVersion = pkgJsonLock.dependencies.mocha.version
const chaiVersion = pkgJsonLock.dependencies.chai.version
const pkgName = pkgJson.name
const rootDir = path.join(__dirname, '..')
// Let's first create the appropriate html file loading mocha, chai and a bundle of the tests
const templatePath = path.join(rootDir, pkgJson.directories.src, 'browser', 'tests-template.html')
const dstDir = path.join(rootDir, pkgJson.directories.test, 'browser')
const dstFileName = path.join(dstDir, 'index.html')
const template = fs.readFileSync(templatePath, 'utf-8')
const bundleFile = path.join(rootDir, pkgJson.directories.lib, 'index.browser.bundle.mod.js')
const testsJs = `
<script type="module">
import * as _pkg from '${path.relative(templatePath, bundleFile)}'
window._pkg = _pkg
import './tests.js'
mocha.run()
</script>`
fs.writeFileSync(dstFileName,
template.replace(/{{TESTS}}/g, testsJs).replace(/{{PKG_NAME}}/g, pkgName).replace(/{{MOCHA_VERSION}}/g, mochaVersion).replace(/{{CHAI_VERSION}}/g, chaiVersion)
)
const input = path.join(rootDir, pkgJson.directories.test, '*.js')
console.log(input)
module.exports = [
{
input: input,
plugins: [
multi({ exports: false }),
replace({
'const _pkg = require(\'../lib/index.node\')': '',
'const chai = require(\'chai\')': '',
delimiters: ['', ''],
'process.browser': true
}),
resolve({
browser: true
}),
commonjs()
],
output: {
file: path.join(rootDir, pkgJson.directories.test, 'browser', 'tests.js'),
format: 'esm'
},
external: [pkgName]
}
]

View File

@ -0,0 +1,66 @@
const puppeteer = require('puppeteer')
const browserTests = async ({ logWarnings = false, serverPort = 38000, keepServerRunning = false, puppeteerOptions = {} }) => {
const server = require('./server.js').server
await server.init()
await server.listen(serverPort)
const browser = await puppeteer.launch(puppeteerOptions)
const page = await browser.newPage()
page.on('console', function (message) {
let ignore = message.type() === 'warning' && !logWarnings
if (message.type() === 'error' && message.location()) {
if (message.location().url.includes('favicon.ico')) {
ignore = true
}
}
if (ignore) return
let text = (message.args().length > 0) ? message.args()[0]._remoteObject.value : message.text()
const args = []
if (message.args() !== undefined && message.args().length > 1) {
for (let i = 1; i < message.args().length; i++) {
args.push(message.args()[i]._remoteObject.value)
}
}
if (message.type() === 'error' && message.location()) {
text = `${message.location().url} : ${text}`
}
let consoleType = 'log'
switch (message.type()) {
case 'error':
consoleType = 'error'
break
case 'warning':
consoleType = 'warn'
break
default:
break
}
console[consoleType](text, ...args)
})
page.on('error', function (err) { page.emit(new Error(err)) })
await page.goto('http://localhost:38000/')
const watchDog = page.waitForFunction('_mocha.state === \'stopped\'')
await watchDog
if (keepServerRunning === false) {
await page.close()
await browser.close()
await server.close()
}
}
const opts = {
// puppeteer options
puppeteerOptions: {
headless: true
// slowMo: 100,
// timeout: 10000
},
doNotLogWarnings: true,
keepServerRunning: false, // keep server running until manually closed with ctrl-c. In combination with puppeteerOptions.headless (or just connecting any browser to the test page) allows debugging in browser
serverPort: 38000
}
browserTests(opts)

View File

@ -0,0 +1,141 @@
'use strict'
const fs = require('fs')
const http = require('http')
const path = require('path')
const pkgJson = require('../../../package.json')
const rollup = require('rollup')
const resolve = require('@rollup/plugin-node-resolve').nodeResolve
const replace = require('@rollup/plugin-replace')
const multi = require('@rollup/plugin-multi-entry')
const typescript = require('@rollup/plugin-typescript')
const commonjs = require('@rollup/plugin-commonjs')
const rootDir = path.join(__dirname, '..', '..', '..')
const regex = /^(?:(?<scope>@.*?)\/)?(?<name>.*)/ // We are going to take only the package name part if there is a scope, e.g. @my-org/package-name
const { name } = pkgJson.name.match(regex).groups
const indexHtml = `<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>${name}</title>
<script src="/mocha.js"></script>
<script src="/chai.js"></script>
</head>
<body>
</body>
<div id="mocha"></div>
<script>
mocha.setup({
ui: 'bdd',
reporter: 'spec',
color: 'true',
timeout: 90000
})
</script>
<script type="module">
import * as _pkg from './${name}.esm.js'
self._pkg = _pkg
import './tests.js'
window._mocha = mocha.run()
</script>
</html>`
async function buildTests () {
// create a bundle
const inputOptions = {
input: [path.join(rootDir, pkgJson.directories.test, '**/*.ts'), path.join(rootDir, pkgJson.directories.src, '**/*.spec.ts')],
plugins: [
multi({ exports: true }),
replace({
IS_BROWSER: true,
preventAssignment: true
}),
typescript(),
resolve({
browser: true,
exportConditions: ['browser', 'module', 'import', 'default']
}),
commonjs()
]
}
const bundle = await rollup.rollup(inputOptions)
const { output } = await bundle.generate({ format: 'esm' })
await bundle.close()
return output[0].code
}
class TestServer {
constructor () {
this.server = http.createServer()
}
async init () {
const tests = await buildTests()
this.server.on('request', function (req, res) {
if (req.url === `/${name}.esm.js`) {
fs.readFile(path.join(rootDir, pkgJson.directories.dist, `bundles/${name}.esm.js`), function (err, data) {
if (err) {
res.writeHead(404)
res.end(JSON.stringify(err))
return
}
res.writeHead(200, { 'Content-Type': 'text/javascript' })
res.end(data)
})
} else if (req.url === '/index.html' || req.url === '/') {
res.writeHead(200)
res.end(indexHtml)
} else if (req.url === '/tests.js') {
res.writeHead(200, { 'Content-Type': 'text/javascript' })
res.end(tests)
} else if (req.url === '/mocha.js') {
fs.readFile(path.join(rootDir, 'node_modules/mocha/mocha.js'), function (err, data) {
if (err) {
res.writeHead(404)
res.end(JSON.stringify(err))
return
}
res.writeHead(200, { 'Content-Type': 'text/javascript' })
res.end(data)
})
} else if (req.url === '/chai.js' || req.url === '/chai') {
fs.readFile(path.join(rootDir, 'node_modules/chai/chai.js'), function (err, data) {
if (err) {
res.writeHead(404)
res.end(JSON.stringify(err))
return
}
res.writeHead(200, { 'Content-Type': 'text/javascript' })
res.end(data)
})
} else {
res.writeHead(404)
res.end()
}
})
}
listen (port = 38080) {
return new Promise((resolve, reject) => {
this.server.listen(port, error => {
if (error) return reject(error)
console.log(`Testing server listenning at http://localhost:${port}`)
return resolve()
})
})
}
close () {
return new Promise((resolve, reject) => {
this.server.close(error => (error) ? reject(error) : resolve())
})
}
}
exports.server = new TestServer()

View File

@ -0,0 +1,59 @@
const EventEmitter = require('events')
const fs = require('fs')
const path = require('path')
module.exports = class Builder extends EventEmitter {
constructor (semaphoreFile, name = 'builder') {
super()
this.name = name
this.firstBuild = true
fs.mkdirSync(path.dirname(semaphoreFile), { recursive: true })
this.semaphoreFile = semaphoreFile
this._ready = false
this.on('message', (...message) => {
if (message !== undefined) {
console.log(`\x1b[33m [${this.name}]`, ...message, '\x1b[0m')
}
})
this.on('error', (...error) => {
if (error !== undefined) {
console.error(`\x1b[31m❗ [${this.name}]`, ...error, '\x1b[0m')
}
})
this.on('ready', () => {
if (this.firstBuild === false) {
fs.writeFileSync(this.semaphoreFile, '', 'utf-8')
} else {
this.firstBuild = false
}
this._ready = true
})
this.on('busy', () => {
this._ready = false
})
}
ready () {
return new Promise(resolve => {
if (this._ready === true) return resolve()
this.once('ready', () => {
resolve()
})
})
}
async start () {
}
async close () {}
clean () {
fs.rmSync(this.semaphoreFile, { force: true })
}
}

View File

@ -0,0 +1,122 @@
const EventEmitter = require('events')
const fs = require('fs')
const path = require('path')
const rollup = require('rollup')
const loadAndParseConfigFile = require('rollup/dist/loadConfigFile')
const Builder = require('./Builder.js')
const rootDir = path.join(__dirname, '../../../../')
const pkgJson = require(path.join(rootDir, 'package.json'))
module.exports = class RollupBuilder extends Builder {
constructor ({ name = 'rollup', configPath = path.join(rootDir, 'rollup.config.js'), tempDir = path.join(rootDir, '.mocha-ts'), watch = false }) {
super(path.join(tempDir, 'semaphore'), name)
this.configPath = configPath
this.watch = watch
}
async start () {
await super.start()
const { options } = await loadAndParseConfigFile(this.configPath)
// Watch only the Node CJS module, that is the one we are going to use with mocha
const rollupOptions = options.filter(bundle => {
const file = (bundle.output[0].dir !== undefined)
? path.join(bundle.output[0].dir, bundle.output[0].entryFileNames)
: bundle.output[0].file
return file === path.join(rootDir, pkgJson.main)
})[0]
this.builder = new RollupBundler(rollupOptions, this.watch)
this.builder.on('event', event => {
switch (event.code) {
case 'START':
this.emit('busy')
if (this.firstBuild === true) {
this.emit('message', 'building your module...')
} else {
this.emit('message', 'file changes detected. Rebuilding module files...')
}
break
case 'BUNDLE_END':
if (event.result) event.result.close()
break
case 'END':
if (event.result) event.result.close()
this.emit('ready')
break
case 'ERROR':
if (event.result) event.result.close()
this.emit('error', event.error)
fs.writeFileSync(path.join(rootDir, pkgJson.main), '', 'utf8')
this.emit('ready')
break
default:
this.emit('busy')
break
}
})
this.builder.start()
return await this.ready()
}
async close () {
await super.close()
this.builder.close()
}
}
class RollupBundler extends EventEmitter {
constructor (rollupOptions, watch = false) {
super()
this.rollupOptions = rollupOptions
this.watch = watch
}
async start () {
if (this.watch === true) {
this.watcher = rollup.watch(this.rollupOptions)
this.watcher.on('event', event => {
this.emit('event', event)
})
} else {
if (fs.existsSync(path.join(rootDir, pkgJson.main)) === false) {
await this._bundle()
} else {
this.emit('event', { code: 'END', noBuild: true })
}
}
}
async _bundle () {
this.emit('event', { code: 'START' })
for (const optionsObj of [].concat(this.rollupOptions)) {
try {
const bundle = await rollup.rollup(optionsObj)
try {
await Promise.all(optionsObj.output.map(bundle.write))
this.emit('event', { code: 'BUNDLE_END' })
} catch (error) {
this.emit('event', { code: 'ERROR', error })
}
} catch (error) {
this.emit('event', { code: 'ERROR', error })
}
}
this.emit('event', { code: 'END' })
}
close () {
if (this.watcher !== undefined) this.watcher.close()
}
}

View File

@ -0,0 +1,95 @@
const path = require('path')
const fs = require('fs')
const ts = require('typescript')
const JSON5 = require('json5')
const Builder = require('./Builder.js')
const rootDir = path.join(__dirname, '../../../../')
const mochaTsRelativeDir = '.mocha-ts'
const mochaTsDir = path.join(rootDir, mochaTsRelativeDir)
const formatHost = {
getCanonicalFileName: path => path,
getCurrentDirectory: ts.sys.getCurrentDirectory,
getNewLine: () => ts.sys.newLine
}
module.exports = class TestsBuilder extends Builder {
constructor ({ name = 'tsc', configPath = path.join(rootDir, 'tsconfig.json'), tempDir = mochaTsDir }) {
super(path.join(tempDir, 'semaphore'), name)
if (fs.existsSync(configPath) !== true) throw new Error(`Couldn't find a tsconfig file at ${configPath}`)
this.tempDir = tempDir
const readFileAndMangle = (path) => { // We need to change the include or file in the original file to only compile the tests
const fileStr = fs.readFileSync(path, 'utf8')
const config = JSON5.parse(fileStr)
if (config.file) delete config.file
config.include = ['build/typings/**/*.ts', 'test/**/*.ts', 'src/**/*.spec.ts', 'node_modules/@types/**/*']
return JSON.stringify(config)
}
const configFile = ts.readJsonConfigFile(configPath, readFileAndMangle)
const parsedTsConfig = ts.parseJsonSourceFileConfigFileContent(configFile, ts.sys, path.dirname(configPath))
const createProgram = ts.createSemanticDiagnosticsBuilderProgram
const reportDiagnostic = (diagnostic) => {
const filePath = path.relative(rootDir, diagnostic.file.fileName)
const tranpiledJsPath = `${path.join(tempDir, filePath).slice(0, -3)}.js`
const errorLine = diagnostic.file.text.slice(0, diagnostic.start).split(/\r\n|\r|\n/).length
if (fs.existsSync(tranpiledJsPath)) {
fs.writeFileSync(tranpiledJsPath, '', 'utf8')
}
this.emit('error', `[Error ${diagnostic.code}]`, `${filePath}:${errorLine}`, ':', ts.flattenDiagnosticMessageText(diagnostic.messageText, formatHost.getNewLine()))
}
const reportWatchStatusChanged = (diagnostic, newLine, options, errorCount) => {
if (errorCount !== undefined) {
this.emit('ready')
} else {
this.emit('busy')
if (diagnostic.code === 6031) {
this.emit('message', 'transpiling your tests...')
} else if (diagnostic.code === 6032) {
this.emit('message', 'file changes detected. Transpiling your tests...')
}
}
}
// Note that there is another overload for `createWatchCompilerHost` that takes
// a set of root files.
this.host = ts.createWatchCompilerHost(
parsedTsConfig.fileNames,
{
...parsedTsConfig.options,
rootDir,
outDir: this.tempDir,
module: 'commonjs',
noEmit: false,
noResolve: true,
sourceMap: true
},
ts.sys,
createProgram,
reportDiagnostic,
reportWatchStatusChanged
)
}
async start () {
await super.start()
// `createWatchProgram` creates an initial program, watches files, and updates
// the program over time.
this.watcher = ts.createWatchProgram(this.host)
return await this.ready()
}
async close () {
await super.close()
this.watcher.close()
}
}

View File

@ -0,0 +1,52 @@
'use strict'
const path = require('path')
const chai = require('chai')
const rimraf = require('rimraf')
const RollupBuilder = require('./builders/RollupBuilder.js')
const TestsBuilder = require('./builders/TestsBuilder.js')
const rootDir = path.join(__dirname, '../../../')
global.chai = chai
const watch = process.argv.includes('--watch') || process.argv.includes('-w')
const tempDir = path.join(rootDir, '.mocha-ts')
const rollupBuilder = new RollupBuilder({ name: 'rollup', configPath: path.join(rootDir, 'build/rollup.config.js'), tempDir, watch })
const testBuilder = new TestsBuilder({ name: 'tsc', tempDir })
rollupBuilder.start() // This should be in exports.mochaGlobalSetup but mocha fails when not in watch mode (DIRT...)
testBuilder.start() // This should be in exports.mochaGlobalSetup but mocha fails when not in watch mode (DIRT...)
exports.mochaHooks = {
beforeAll: [
async function () {
// Just in case our module had been modified. Reload it when the tests are repeated (for mocha watch mode).
delete require.cache[require.resolve(rootDir)]
global._pkg = require(rootDir)
},
async function () {
this.timeout('120000')
await Promise.all([rollupBuilder.ready(), testBuilder.ready()])
}
]
}
// exports.mochaGlobalSetup = async function () {
// await rollupBuilder.start()
// await testBuilder.start()
// }
exports.mochaGlobalTeardown = async function () {
await testBuilder.close()
await rollupBuilder.close()
// I use the sync version of rimraf precisely because it blocks the
// main thread and thus the mocha watcher, which otherwise would complain
// about files being deleted
rimraf.sync(tempDir, { disableGlob: true })
}

5
build/typings/global-this-pkg.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import * as _pkgModule from '../..'
export as namespace _pkg
export = _pkgModule

1
build/typings/is-browser.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare const IS_BROWSER: boolean

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

712
dist/cjs/index.node.cjs vendored Normal file

File diff suppressed because one or more lines are too long

626
dist/esm/index.browser.js vendored Normal file

File diff suppressed because one or more lines are too long

642
dist/esm/index.node.js vendored Normal file

File diff suppressed because one or more lines are too long

7
dist/esm/types/index.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
export { abs, bitLength, eGcd, gcd, lcm, max, min, modInv, modPow, toZn } from 'bigint-mod-arith';
export { isProbablyPrime } from './ts/isProbablyPrime';
export { prime, primeSync } from './ts/prime';
export { randBetween } from './ts/randBetween';
export { randBits, randBitsSync } from './ts/randBits';
export { randBytes, randBytesSync } from './ts/randBytes';
//# sourceMappingURL=index.d.ts.map

1
dist/esm/types/index.d.ts.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AAEjG,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA"}

3
dist/esm/types/ts/fromBuffer.d.ts vendored Normal file
View File

@ -0,0 +1,3 @@
/// <reference types="node" />
export declare function fromBuffer(buf: Uint8Array | Buffer): bigint;
//# sourceMappingURL=fromBuffer.d.ts.map

1
dist/esm/types/ts/fromBuffer.d.ts.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"fromBuffer.d.ts","sourceRoot":"","sources":["../../../../src/ts/fromBuffer.ts"],"names":[],"mappings":";AAAA,wBAAgB,UAAU,CAAE,GAAG,EAAE,UAAU,GAAC,MAAM,GAAG,MAAM,CAO1D"}

17
dist/esm/types/ts/isProbablyPrime.d.ts vendored Normal file
View File

@ -0,0 +1,17 @@
/**
* 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)
*
* @param w - A positive integer to be tested for primality
* @param iterations - The number of iterations for the primality test. The value shall be consistent with Table C.1, C.2 or C.3
* @param disableWorkers - Disable the use of workers for the primality test
*
* @throws {RangeError}
* w MUST be >= 0
*
* @returns A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
*/
export declare function isProbablyPrime(w: number | bigint, iterations?: number, disableWorkers?: boolean): Promise<boolean>;
export declare function _isProbablyPrime(w: bigint, iterations?: number): boolean;
export declare function _isProbablyPrimeWorkerUrl(): string;
//# sourceMappingURL=isProbablyPrime.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"isProbablyPrime.d.ts","sourceRoot":"","sources":["../../../../src/ts/isProbablyPrime.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAE,CAAC,EAAE,MAAM,GAAC,MAAM,EAAE,UAAU,GAAE,MAAW,EAAE,cAAc,GAAE,OAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAqD7H;AAED,wBAAgB,gBAAgB,CAAE,CAAC,EAAE,MAAM,EAAE,UAAU,GAAE,MAAW,GAAG,OAAO,CA0T7E;AAED,wBAAgB,yBAAyB,IAAK,MAAM,CAkBnD"}

30
dist/esm/types/ts/prime.d.ts vendored Normal file
View File

@ -0,0 +1,30 @@
/**
* 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).
*
* @param bitLength - The required bit length for the generated prime
* @param iterations - The number of iterations for the Miller-Rabin Probabilistic Primality Test
*
* @throws {RangeError}
* bitLength MUST be > 0
*
* @returns A promise that resolves to a bigint probable prime of bitLength bits.
*/
export declare function prime(bitLength: number, iterations?: number): Promise<bigint>;
/**
* 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.
*
* @param bitLength - The required bit length for the generated prime
* @param iterations - The number of iterations for the Miller-Rabin Probabilistic Primality Test
*
* @throws {RangeError}
* bitLength MUST be > 0
*
* @returns A bigint probable prime of bitLength bits.
*/
export declare function primeSync(bitLength: number, iterations?: number): bigint;
//# sourceMappingURL=prime.d.ts.map

1
dist/esm/types/ts/prime.d.ts.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"prime.d.ts","sourceRoot":"","sources":["../../../../src/ts/prime.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,KAAK,CAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAE,MAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAiElF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAE,MAAW,GAAG,MAAM,CAO7E"}

12
dist/esm/types/ts/randBetween.d.ts vendored Normal file
View File

@ -0,0 +1,12 @@
/**
* Returns a cryptographically secure random integer between [min,max]. Both numbers must be >=0
* @param max Returned value will be <= max
* @param min Returned value will be >= min
*
* @throws {RangeError}
* Arguments MUST be: max > 0 && min >=0 && max > min
*
* @returns A cryptographically secure random bigint between [min,max]
*/
export declare function randBetween(max: bigint, min?: bigint): bigint;
//# sourceMappingURL=randBetween.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"randBetween.d.ts","sourceRoot":"","sources":["../../../../src/ts/randBetween.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAW,GAAG,MAAM,CAUlE"}

25
dist/esm/types/ts/randBits.d.ts vendored Normal file
View File

@ -0,0 +1,25 @@
/// <reference types="node" />
/**
* Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
*
* @param bitLength - The desired number of random bits
* @param forceLength - If we want to force the output to have a specific bit length. It basically forces the msb to be 1
*
* @throws {RangeError}
* bitLength MUST be > 0
*
* @returns A Promise that resolves to a UInt8Array/Buffer (Browser/Node.js) filled with cryptographically secure random bits
*/
export declare function randBits(bitLength: number, forceLength?: boolean): Promise<Uint8Array | Buffer>;
/**
* Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
* @param bitLength - The desired number of random bits
* @param forceLength - If we want to force the output to have a specific bit length. It basically forces the msb to be 1
*
* @throws {RangeError}
* bitLength MUST be > 0
*
* @returns A Uint8Array/Buffer (Browser/Node.js) filled with cryptographically secure random bits
*/
export declare function randBitsSync(bitLength: number, forceLength?: boolean): Uint8Array | Buffer;
//# sourceMappingURL=randBits.d.ts.map

1
dist/esm/types/ts/randBits.d.ts.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"randBits.d.ts","sourceRoot":"","sources":["../../../../src/ts/randBits.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAE,SAAS,EAAE,MAAM,EAAE,WAAW,GAAE,OAAe,GAAG,OAAO,CAAC,UAAU,GAAC,MAAM,CAAC,CAmBrG;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAE,SAAS,EAAE,MAAM,EAAE,WAAW,GAAE,OAAe,GAAG,UAAU,GAAC,MAAM,CAehG"}

26
dist/esm/types/ts/randBytes.d.ts vendored Normal file
View File

@ -0,0 +1,26 @@
/// <reference types="node" />
/**
* Secure random bytes for both node and browsers. Node version uses crypto.randomBytes() and browser one self.crypto.getRandomValues()
*
* @param byteLength - The desired number of random bytes
* @param forceLength - If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
*
* @throws {RangeError}
* byteLength MUST be > 0
*
* @returns A promise that resolves to a UInt8Array/Buffer (Browser/Node.js) filled with cryptographically secure random bytes
*/
export declare 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()
*
* @param byteLength - The desired number of random bytes
* @param forceLength - If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
*
* @throws {RangeError}
* byteLength MUST be > 0
*
* @returns A UInt8Array/Buffer (Browser/Node.js) filled with cryptographically secure random bytes
*/
export declare function randBytesSync(byteLength: number, forceLength?: boolean): Uint8Array | Buffer;
//# sourceMappingURL=randBytes.d.ts.map

1
dist/esm/types/ts/randBytes.d.ts.map vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"randBytes.d.ts","sourceRoot":"","sources":["../../../../src/ts/randBytes.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAE,UAAU,EAAE,MAAM,EAAE,WAAW,UAAQ,GAAG,OAAO,CAAC,UAAU,GAAC,MAAM,CAAC,CAqB9F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAE,OAAe,GAAG,UAAU,GAAC,MAAM,CAkBlG"}

14
dist/esm/types/ts/workerUtils.d.ts vendored Normal file
View File

@ -0,0 +1,14 @@
export declare function _workerUrl(workerCode: string): string;
declare let _useWorkers: boolean;
export { _useWorkers };
export interface WorkerToMainMsg {
isPrime: boolean;
value: bigint;
id: number;
}
export interface MainToWorkerMsg {
rnd: bigint;
iterations: number;
id: number;
}
//# sourceMappingURL=workerUtils.d.ts.map

View File

@ -0,0 +1 @@
{"version":3,"file":"workerUtils.d.ts","sourceRoot":"","sources":["../../../../src/ts/workerUtils.ts"],"names":[],"mappings":"AAAA,wBAAgB,UAAU,CAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,QAAA,IAAI,WAAW,SAAQ,CAAA;AAiBvB,OAAO,EAAE,WAAW,EAAE,CAAA;AAEtB,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,EAAE,EAAE,MAAM,CAAA;CACX;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,MAAM,CAAA;IAClB,EAAE,EAAE,MAAM,CAAA;CACX"}

450
docs/API.md Normal file
View File

@ -0,0 +1,450 @@
bigint-crypto-utils - v3.0.9
# bigint-crypto-utils - v3.0.9
## Table of contents
### Functions
- [abs](API.md#abs)
- [bitLength](API.md#bitlength)
- [eGcd](API.md#egcd)
- [gcd](API.md#gcd)
- [isProbablyPrime](API.md#isprobablyprime)
- [lcm](API.md#lcm)
- [max](API.md#max)
- [min](API.md#min)
- [modInv](API.md#modinv)
- [modPow](API.md#modpow)
- [prime](API.md#prime)
- [primeSync](API.md#primesync)
- [randBetween](API.md#randbetween)
- [randBits](API.md#randbits)
- [randBitsSync](API.md#randbitssync)
- [randBytes](API.md#randbytes)
- [randBytesSync](API.md#randbytessync)
- [toZn](API.md#tozn)
## Functions
### abs
**abs**(`a`: *number* \| *bigint*): *number* \| *bigint*
Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* \| *bigint* |
**Returns:** *number* \| *bigint*
The absolute value of a
Defined in: node_modules/bigint-mod-arith/dist/esm/types/ts/abs.d.ts:8
___
### bitLength
**bitLength**(`a`: *number* \| *bigint*): *number*
Returns the bitlength of a number
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* \| *bigint* |
**Returns:** *number*
The bit length
Defined in: node_modules/bigint-mod-arith/dist/esm/types/ts/bitLength.d.ts:7
___
### eGcd
**eGcd**(`a`: *number* \| *bigint*, `b`: *number* \| *bigint*): Egcd
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).
**`throws`** {RangeError}
This excepction is thrown if a or b are less than 0
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* \| *bigint* |
`b` | *number* \| *bigint* |
**Returns:** Egcd
A triple (g, x, y), such that ax + by = g = gcd(a, b).
Defined in: node_modules/bigint-mod-arith/dist/esm/types/ts/egcd.d.ts:18
___
### gcd
**gcd**(`a`: *number* \| *bigint*, `b`: *number* \| *bigint*): *bigint*
Greatest-common divisor of two integers based on the iterative binary algorithm.
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* \| *bigint* |
`b` | *number* \| *bigint* |
**Returns:** *bigint*
The greatest common divisor of a and b
Defined in: node_modules/bigint-mod-arith/dist/esm/types/ts/gcd.d.ts:9
___
### isProbablyPrime
**isProbablyPrime**(`w`: *number* \| *bigint*, `iterations?`: *number*, `disableWorkers?`: *boolean*): *Promise*<boolean\>
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)
**`throws`** {RangeError}
w MUST be >= 0
#### Parameters:
Name | Type | Default value | Description |
:------ | :------ | :------ | :------ |
`w` | *number* \| *bigint* | - | A positive integer to be tested for primality |
`iterations` | *number* | 16 | The number of iterations for the primality test. The value shall be consistent with Table C.1, C.2 or C.3 |
`disableWorkers` | *boolean* | false | Disable the use of workers for the primality test |
**Returns:** *Promise*<boolean\>
A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
Defined in: src/ts/isProbablyPrime.ts:21
___
### lcm
**lcm**(`a`: *number* \| *bigint*, `b`: *number* \| *bigint*): *bigint*
The least common multiple computed as abs(a*b)/gcd(a,b)
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* \| *bigint* |
`b` | *number* \| *bigint* |
**Returns:** *bigint*
The least common multiple of a and b
Defined in: node_modules/bigint-mod-arith/dist/esm/types/ts/lcm.d.ts:8
___
### max
**max**(`a`: *number* \| *bigint*, `b`: *number* \| *bigint*): *number* \| *bigint*
Maximum. max(a,b)==a if a>=b. max(a,b)==b if a<=b
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* \| *bigint* |
`b` | *number* \| *bigint* |
**Returns:** *number* \| *bigint*
Maximum of numbers a and b
Defined in: node_modules/bigint-mod-arith/dist/esm/types/ts/max.d.ts:9
___
### min
**min**(`a`: *number* \| *bigint*, `b`: *number* \| *bigint*): *number* \| *bigint*
Minimum. min(a,b)==b if a>=b. min(a,b)==a if a<=b
#### Parameters:
Name | Type |
:------ | :------ |
`a` | *number* \| *bigint* |
`b` | *number* \| *bigint* |
**Returns:** *number* \| *bigint*
Minimum of numbers a and b
Defined in: node_modules/bigint-mod-arith/dist/esm/types/ts/min.d.ts:9
___
### modInv
**modInv**(`a`: *number* \| *bigint*, `n`: *number* \| *bigint*): *bigint*
Modular inverse.
**`throws`** {RangeError}
Excpeption thorwn when a does not have inverse modulo n
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`a` | *number* \| *bigint* | The number to find an inverse for |
`n` | *number* \| *bigint* | The modulo |
**Returns:** *bigint*
The inverse modulo n
Defined in: node_modules/bigint-mod-arith/dist/esm/types/ts/modInv.d.ts:12
___
### modPow
**modPow**(`b`: *number* \| *bigint*, `e`: *number* \| *bigint*, `n`: *number* \| *bigint*): *bigint*
Modular exponentiation b**e mod n. Currently using the right-to-left binary method
**`throws`** {RangeError}
Excpeption thrown when n is not > 0
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`b` | *number* \| *bigint* | base |
`e` | *number* \| *bigint* | exponent |
`n` | *number* \| *bigint* | modulo |
**Returns:** *bigint*
b**e mod n
Defined in: node_modules/bigint-mod-arith/dist/esm/types/ts/modPow.d.ts:13
___
### prime
**prime**(`bitLength`: *number*, `iterations?`: *number*): *Promise*<bigint\>
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).
**`throws`** {RangeError}
bitLength MUST be > 0
#### Parameters:
Name | Type | Default value | Description |
:------ | :------ | :------ | :------ |
`bitLength` | *number* | - | The required bit length for the generated prime |
`iterations` | *number* | 16 | The number of iterations for the Miller-Rabin Probabilistic Primality Test |
**Returns:** *Promise*<bigint\>
A promise that resolves to a bigint probable prime of bitLength bits.
Defined in: src/ts/prime.ts:21
___
### primeSync
**primeSync**(`bitLength`: *number*, `iterations?`: *number*): *bigint*
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.
**`throws`** {RangeError}
bitLength MUST be > 0
#### Parameters:
Name | Type | Default value | Description |
:------ | :------ | :------ | :------ |
`bitLength` | *number* | - | The required bit length for the generated prime |
`iterations` | *number* | 16 | The number of iterations for the Miller-Rabin Probabilistic Primality Test |
**Returns:** *bigint*
A bigint probable prime of bitLength bits.
Defined in: src/ts/prime.ts:100
___
### randBetween
**randBetween**(`max`: *bigint*, `min?`: *bigint*): *bigint*
Returns a cryptographically secure random integer between [min,max]. Both numbers must be >=0
**`throws`** {RangeError}
Arguments MUST be: max > 0 && min >=0 && max > min
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`max` | *bigint* | Returned value will be <= max |
`min` | *bigint* | Returned value will be >= min |
**Returns:** *bigint*
A cryptographically secure random bigint between [min,max]
Defined in: src/ts/randBetween.ts:15
___
### randBits
**randBits**(`bitLength`: *number*, `forceLength?`: *boolean*): *Promise*<Uint8Array \| Buffer\>
Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
**`throws`** {RangeError}
bitLength MUST be > 0
#### Parameters:
Name | Type | Default value | Description |
:------ | :------ | :------ | :------ |
`bitLength` | *number* | - | The desired number of random bits |
`forceLength` | *boolean* | false | If we want to force the output to have a specific bit length. It basically forces the msb to be 1 |
**Returns:** *Promise*<Uint8Array \| Buffer\>
A Promise that resolves to a UInt8Array/Buffer (Browser/Node.js) filled with cryptographically secure random bits
Defined in: src/ts/randBits.ts:14
___
### randBitsSync
**randBitsSync**(`bitLength`: *number*, `forceLength?`: *boolean*): Uint8Array \| Buffer
Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
**`throws`** {RangeError}
bitLength MUST be > 0
#### Parameters:
Name | Type | Default value | Description |
:------ | :------ | :------ | :------ |
`bitLength` | *number* | - | The desired number of random bits |
`forceLength` | *boolean* | false | If we want to force the output to have a specific bit length. It basically forces the msb to be 1 |
**Returns:** Uint8Array \| Buffer
A Uint8Array/Buffer (Browser/Node.js) filled with cryptographically secure random bits
Defined in: src/ts/randBits.ts:45
___
### randBytes
**randBytes**(`byteLength`: *number*, `forceLength?`: *boolean*): *Promise*<Uint8Array \| Buffer\>
Secure random bytes for both node and browsers. Node version uses crypto.randomBytes() and browser one self.crypto.getRandomValues()
**`throws`** {RangeError}
byteLength MUST be > 0
#### Parameters:
Name | Type | Default value | Description |
:------ | :------ | :------ | :------ |
`byteLength` | *number* | - | The desired number of random bytes |
`forceLength` | *boolean* | 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*<Uint8Array \| Buffer\>
A promise that resolves to a UInt8Array/Buffer (Browser/Node.js) filled with cryptographically secure random bytes
Defined in: src/ts/randBytes.ts:12
___
### randBytesSync
**randBytesSync**(`byteLength`: *number*, `forceLength?`: *boolean*): Uint8Array \| Buffer
Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
**`throws`** {RangeError}
byteLength MUST be > 0
#### Parameters:
Name | Type | Default value | Description |
:------ | :------ | :------ | :------ |
`byteLength` | *number* | - | The desired number of random bytes |
`forceLength` | *boolean* | 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:** Uint8Array \| Buffer
A UInt8Array/Buffer (Browser/Node.js) filled with cryptographically secure random bytes
Defined in: src/ts/randBytes.ts:46
___
### toZn
**toZn**(`a`: *number* \| *bigint*, `n`: *number* \| *bigint*): *bigint*
Finds the smallest positive element that is congruent to a in modulo n
**`remarks`**
a and b must be the same type, either number or bigint
**`throws`** {RangeError}
Excpeption thrown when n is not > 0
#### Parameters:
Name | Type | Description |
:------ | :------ | :------ |
`a` | *number* \| *bigint* | An integer |
`n` | *number* \| *bigint* | The modulo |
**Returns:** *bigint*
A bigint with the smallest positive representation of a modulo n
Defined in: node_modules/bigint-mod-arith/dist/esm/types/ts/toZn.d.ts:15

View File

@ -10,7 +10,7 @@
<div id="status">Still computing in background...</div>
<p>Look for the results in the JS console (Developer Tools)</p>
<script type="module">
import * as bigintCryptoUtils from '../lib/index.browser.bundle.mod.js'
import * as bigintCryptoUtils from '../dist/bundles/bigint-crypto-utils.esm.js'
/* A BigInt with value 666 can be declared calling the bigint constructor as
BigInt('666') or with the shorter 666n.
Notice that you can also pass a number to the constructor, e.g. BigInt(666).

View File

@ -4,7 +4,7 @@
<head>
<title>bigint-crypto-utils</title>
<meta charset="UTF-8" />
<script src="../lib/index.browser.bundle.iife.js"></script>
<script src="../dist/bundles/bigint-crypto-utils.iife.js"></script>
</head>
<body>

View File

@ -1,4 +1,4 @@
const bigintCryptoUtils = require('../lib/index.node')
const bigintCryptoUtils = require('../')
// const bigintCryptoUtils = require('bigint-crypto-utils')
/* A BigInt with value 666 can be declared calling the bigint constructor as

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,837 +0,0 @@
/**
* 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 >= 0n) ? 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 === 1n) { return 1 }
let bits = 1
do {
bits++
} while ((a >>= 1n) > 1n)
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
*
* @throws {RangeError} a and b MUST be > 0
*
* @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 <= 0n | b <= 0n) throw new RangeError('a and b MUST be > 0') // a and b MUST be positive
let x = 0n
let y = 1n
let u = 1n
let v = 0n
while (a !== 0n) {
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 {
g: 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 === 0n) { return b } else if (b === 0n) { return a }
let shift = 0n
while (!((a | b) & 1n)) {
a >>= 1n
b >>= 1n
shift++
}
while (!(a & 1n)) a >>= 1n
do {
while (!(b & 1n)) b >>= 1n
if (a > b) {
const x = a
a = b
b = x
}
b -= a
} while (b)
// rescale
return a << shift
}
/**
* 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 === 0n && b === 0n) return BigInt(0)
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
*
* @throws {RangeError} a does not have inverse modulo n
*
* @returns {bigint} the inverse modulo n
*/
function modInv (a, n) {
const egcd = eGcd(toZn(a, n), n)
if (egcd.g !== 1n) {
throw new RangeError(`${a.toString()} does not have inverse modulo ${n.toString()}`) // 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 === 0n) { throw new RangeError('n must be > 0') } else if (n === 1n) { return BigInt(0) }
b = toZn(b, n)
e = BigInt(e)
if (e < 0n) {
return modInv(modPow(b, abs(e), n), n)
}
let r = 1n
while (e > 0) {
if ((e % 2n) === 1n) {
r = (r * b) % n
}
e = e / 2n
b = b ** 2n % n
}
return r
}
/**
* 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
}
/**
* 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)
*
* @param {number | bigint} w A positive 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 {boolean} [disableWorkers = false] Disable the use of workers for the primality test
*
* @throws {RangeError} w MUST be >= 0
*
* @returns {Promise<boolean>} A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
*/
function isProbablyPrime (w, iterations = 16, disableWorkers = false) {
if (typeof w === 'number') {
w = BigInt(w)
}
if (w < 0) throw RangeError('w MUST be >= 0')
/* eslint-disable no-lone-blocks */
{ // browser
return new Promise((resolve, reject) => {
const worker = new Worker(_isProbablyPrimeWorkerUrl())
worker.onmessage = (event) => {
worker.terminate()
resolve(event.data.isPrime)
}
worker.onmessageerror = (event) => {
reject(event)
}
worker.postMessage({
rnd: w,
iterations: iterations,
id: 0
})
})
}
/* eslint-enable no-lone-blocks */
}
/**
* 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).
*
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {Promise<bigint>} A promise that resolves to a bigint probable prime of bitLength bits.
*/
function prime (bitLength, iterations = 16) {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
/* istanbul ignore if */
if (!_useWorkers) { // If there is no support for workers
let rnd = 0n
do {
rnd = fromBuffer(randBitsSync(bitLength, true))
} while (!_isProbablyPrime(rnd, iterations))
return new Promise((resolve) => { resolve(rnd) })
}
return new Promise((resolve) => {
const workerList = []
const _onmessage = (msg, newWorker) => {
if (msg.isPrime) {
// if a prime number has been found, stop all the workers, and return it
for (let j = 0; j < workerList.length; j++) {
workerList[j].terminate()
}
while (workerList.length) {
workerList.pop()
}
resolve(msg.value)
} else { // if a composite is found, make the worker test another random number
const buf = randBitsSync(bitLength, true)
const rnd = fromBuffer(buf)
try {
newWorker.postMessage({
rnd: rnd,
iterations: iterations,
id: msg.id
})
} catch (error) {
// The worker has already terminated. There is nothing to handle here
}
}
}
/* eslint-disable no-lone-blocks */
{ // browser
const workerURL = _isProbablyPrimeWorkerUrl()
for (let i = 0; i < self.navigator.hardwareConcurrency - 1; i++) {
const newWorker = new Worker(workerURL)
newWorker.onmessage = (event) => _onmessage(event.data, newWorker)
workerList.push(newWorker)
}
}
/* eslint-enable no-lone-blocks */
for (let i = 0; i < workerList.length; i++) {
randBits(bitLength, true).then(function (buf) {
const rnd = fromBuffer(buf)
workerList[i].postMessage({
rnd: rnd,
iterations: iterations,
id: i
})
})
}
})
}
/**
* 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.
*
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {bigint} A bigint probable prime of bitLength bits.
*/
function primeSync (bitLength, iterations = 16) {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
let rnd = 0n
do {
rnd = fromBuffer(randBitsSync(bitLength, true))
} while (!_isProbablyPrime(rnd, iterations))
return rnd
}
/**
* Returns a cryptographically secure random integer between [min,max]. Both numbers must be >=0
* @param {bigint} max Returned value will be <= max
* @param {bigint} [min = BigInt(1)] Returned value will be >= min
*
* @throws {RangeError} Arguments MUST be: max > 0 && min >=0 && max > min
*
* @returns {bigint} A cryptographically secure random bigint between [min,max]
*/
function randBetween (max, min = 1n) {
if (max <= 0n || min < 0n || max <= min) throw new RangeError('Arguments MUST be: max > 0 && min >=0 && max > min')
const interval = max - min
const bitLen = bitLength(interval)
let rnd
do {
const buf = randBitsSync(bitLen)
rnd = fromBuffer(buf)
} while (rnd > interval)
return rnd + min
}
/**
* Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
*
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {Promise<Buffer | Uint8Array>} A Promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
*/
function randBits (bitLength, forceLength = false) {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
const byteLength = Math.ceil(bitLength / 8)
const bitLengthMod8 = bitLength % 8
return new Promise((resolve) => {
randBytes(byteLength, false).then(function (rndBytes) {
if (bitLengthMod8) {
// Fill with 0's the extra bits
rndBytes[0] = rndBytes[0] & (2 ** bitLengthMod8 - 1)
}
if (forceLength) {
const mask = bitLengthMod8 ? 2 ** (bitLengthMod8 - 1) : 128
rndBytes[0] = rndBytes[0] | mask
}
resolve(rndBytes)
})
})
}
/**
* Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
*/
function randBitsSync (bitLength, forceLength = false) {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
const byteLength = Math.ceil(bitLength / 8)
const rndBytes = randBytesSync(byteLength, false)
const bitLengthMod8 = bitLength % 8
if (bitLengthMod8) {
// Fill with 0's the extra bits
rndBytes[0] = rndBytes[0] & (2 ** bitLengthMod8 - 1)
}
if (forceLength) {
const mask = bitLengthMod8 ? 2 ** (bitLengthMod8 - 1) : 128
rndBytes[0] = rndBytes[0] | mask
}
return rndBytes
}
/**
* Secure random bytes for both node and browsers. Node version uses crypto.randomBytes() and browser one self.crypto.getRandomValues()
*
* @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
*
* @throws {RangeError} byteLength MUST be > 0
*
* @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) {
if (byteLength < 1) throw new RangeError('byteLength MUST be > 0')
return new Promise(function (resolve, reject) {
/* eslint-disable no-lone-blocks */
{ // browser
const buf = new Uint8Array(byteLength)
self.crypto.getRandomValues(buf)
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if (forceLength) buf[0] = buf[0] | 128
resolve(buf)
}
/* eslint-enable no-lone-blocks */
})
}
/**
* 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 {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
*
* @throws {RangeError} byteLength MUST be > 0
*
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
*/
function randBytesSync (byteLength, forceLength = false) {
if (byteLength < 1) throw new RangeError('byteLength MUST be > 0')
/* eslint-disable no-lone-blocks */
{ // browser
const buf = new Uint8Array(byteLength)
self.crypto.getRandomValues(buf)
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if (forceLength) buf[0] = buf[0] | 128
return buf
}
/* eslint-enable no-lone-blocks */
}
/* HELPER FUNCTIONS */
function fromBuffer (buf) {
let ret = 0n
for (const i of buf.values()) {
const bi = BigInt(i)
ret = (ret << BigInt(8)) + bi
}
return ret
}
function _isProbablyPrimeWorkerUrl () {
// Let's us first add all the required functions
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 ${randBitsSync.name}=${randBitsSync.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
// event.data = {rnd: <bigint>, iterations: <number>}
const isPrime = await isProbablyPrime(event.data.rnd, event.data.iterations)
postMessage({
isPrime: isPrime,
value: event.data.rnd,
id: event.data.id
})
}
workerCode += `onmessage = ${onmessage.toString()};`
return _workerUrl(workerCode)
}
function _workerUrl (workerCode) {
workerCode = `(() => {${workerCode}})()` // encapsulate IIFE
const _blob = new Blob([workerCode], { type: 'text/javascript' })
return window.URL.createObjectURL(_blob)
}
function _isProbablyPrime (w, iterations = 16) {
/*
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.
*/
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.
*/
const firstPrimes = [
3n,
5n,
7n,
11n,
13n,
17n,
19n,
23n,
29n,
31n,
37n,
41n,
43n,
47n,
53n,
59n,
61n,
67n,
71n,
73n,
79n,
83n,
89n,
97n,
101n,
103n,
107n,
109n,
113n,
127n,
131n,
137n,
139n,
149n,
151n,
157n,
163n,
167n,
173n,
179n,
181n,
191n,
193n,
197n,
199n,
211n,
223n,
227n,
229n,
233n,
239n,
241n,
251n,
257n,
263n,
269n,
271n,
277n,
281n,
283n,
293n,
307n,
311n,
313n,
317n,
331n,
337n,
347n,
349n,
353n,
359n,
367n,
373n,
379n,
383n,
389n,
397n,
401n,
409n,
419n,
421n,
431n,
433n,
439n,
443n,
449n,
457n,
461n,
463n,
467n,
479n,
487n,
491n,
499n,
503n,
509n,
521n,
523n,
541n,
547n,
557n,
563n,
569n,
571n,
577n,
587n,
593n,
599n,
601n,
607n,
613n,
617n,
619n,
631n,
641n,
643n,
647n,
653n,
659n,
661n,
673n,
677n,
683n,
691n,
701n,
709n,
719n,
727n,
733n,
739n,
743n,
751n,
757n,
761n,
769n,
773n,
787n,
797n,
809n,
811n,
821n,
823n,
827n,
829n,
839n,
853n,
857n,
859n,
863n,
877n,
881n,
883n,
887n,
907n,
911n,
919n,
929n,
937n,
941n,
947n,
953n,
967n,
971n,
977n,
983n,
991n,
997n,
1009n,
1013n,
1019n,
1021n,
1031n,
1033n,
1039n,
1049n,
1051n,
1061n,
1063n,
1069n,
1087n,
1091n,
1093n,
1097n,
1103n,
1109n,
1117n,
1123n,
1129n,
1151n,
1153n,
1163n,
1171n,
1181n,
1187n,
1193n,
1201n,
1213n,
1217n,
1223n,
1229n,
1231n,
1237n,
1249n,
1259n,
1277n,
1279n,
1283n,
1289n,
1291n,
1297n,
1301n,
1303n,
1307n,
1319n,
1321n,
1327n,
1361n,
1367n,
1373n,
1381n,
1399n,
1409n,
1423n,
1427n,
1429n,
1433n,
1439n,
1447n,
1451n,
1453n,
1459n,
1471n,
1481n,
1483n,
1487n,
1489n,
1493n,
1499n,
1511n,
1523n,
1531n,
1543n,
1549n,
1553n,
1559n,
1567n,
1571n,
1579n,
1583n,
1597n
]
for (let i = 0; i < firstPrimes.length && (firstPrimes[i] <= w); i++) {
const p = firstPrimes[i]
if (w === p) return true
else if (w % p === 0n) return false
}
/*
1. Let a be the largest integer such that 2**a divides w1.
2. m = (w1) / 2**a.
3. wlen = len (w).
4. For i = 1 to iterations do
4.1 Obtain a string b of wlen bits from an RBG.
Comment: Ensure that 1 < b < w1.
4.2 If ((b 1) or (b w1)), then go to step 4.1.
4.3 z = b**m mod w.
4.4 If ((z = 1) or (z = w 1)), then go to step 4.7.
4.5 For j = 1 to a 1 do.
4.5.1 z = z**2 mod w.
4.5.2 If (z = w1), then go to step 4.7.
4.5.3 If (z = 1), then go to step 4.6.
4.6 Return COMPOSITE.
4.7 Continue.
Comment: Increment i for the do-loop in step 4.
5. Return PROBABLY PRIME.
*/
let a = 0n
const d = w - 1n
let aux = d
while (aux % 2n === 0n) {
aux /= 2n
++a
}
const m = d / (2n ** a)
do {
const b = randBetween(d, 2n)
let z = modPow(b, m, w)
if (z === 1n || z === d) continue
let j = 1
while (j < a) {
z = modPow(z, 2n, w)
if (z === d) break
if (z === 1n) return false
j++
}
if (z !== d) return false
} while (--iterations)
return true
}
let _useWorkers = false // The following is just to check whether we can use workers
/* eslint-disable no-lone-blocks */
{ // Native JS
if (self.Worker) _useWorkers = true
}
export { abs, bitLength, eGcd, gcd, isProbablyPrime, lcm, max, min, modInv, modPow, prime, primeSync, randBetween, randBits, randBitsSync, randBytes, randBytesSync, toZn }

View File

@ -1,867 +0,0 @@
'use strict'
/**
* 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 >= 0n) ? 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 === 1n) { return 1 }
let bits = 1
do {
bits++
} while ((a >>= 1n) > 1n)
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
*
* @throws {RangeError} a and b MUST be > 0
*
* @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 <= 0n | b <= 0n) throw new RangeError('a and b MUST be > 0') // a and b MUST be positive
let x = 0n
let y = 1n
let u = 1n
let v = 0n
while (a !== 0n) {
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 {
g: 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 === 0n) { return b } else if (b === 0n) { return a }
let shift = 0n
while (!((a | b) & 1n)) {
a >>= 1n
b >>= 1n
shift++
}
while (!(a & 1n)) a >>= 1n
do {
while (!(b & 1n)) b >>= 1n
if (a > b) {
const x = a
a = b
b = x
}
b -= a
} while (b)
// rescale
return a << shift
}
/**
* 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 === 0n && b === 0n) return BigInt(0)
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
*
* @throws {RangeError} a does not have inverse modulo n
*
* @returns {bigint} the inverse modulo n
*/
function modInv (a, n) {
const egcd = eGcd(toZn(a, n), n)
if (egcd.g !== 1n) {
throw new RangeError(`${a.toString()} does not have inverse modulo ${n.toString()}`) // 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 === 0n) { throw new RangeError('n must be > 0') } else if (n === 1n) { return BigInt(0) }
b = toZn(b, n)
e = BigInt(e)
if (e < 0n) {
return modInv(modPow(b, abs(e), n), n)
}
let r = 1n
while (e > 0) {
if ((e % 2n) === 1n) {
r = (r * b) % n
}
e = e / 2n
b = b ** 2n % n
}
return r
}
/**
* 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
}
/**
* 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)
*
* @param {number | bigint} w A positive 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 {boolean} [disableWorkers = false] Disable the use of workers for the primality test
*
* @throws {RangeError} w MUST be >= 0
*
* @returns {Promise<boolean>} A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite)
*/
function isProbablyPrime (w, iterations = 16, disableWorkers = false) {
if (typeof w === 'number') {
w = BigInt(w)
}
if (w < 0) throw RangeError('w MUST be >= 0')
/* eslint-disable no-lone-blocks */
{ // Node.js
/* istanbul ignore else */
if (!disableWorkers && _useWorkers) {
const { Worker } = require('worker_threads')
return new Promise((resolve, reject) => {
const worker = new Worker(__filename)
worker.on('message', (data) => {
worker.terminate()
resolve(data.isPrime)
})
worker.on('error', reject)
worker.postMessage({
rnd: w,
iterations: iterations,
id: 0
})
})
} else {
return new Promise((resolve) => {
resolve(_isProbablyPrime(w, iterations))
})
}
}
/* eslint-enable no-lone-blocks */
}
/**
* 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).
*
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {Promise<bigint>} A promise that resolves to a bigint probable prime of bitLength bits.
*/
function prime (bitLength, iterations = 16) {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
/* istanbul ignore if */
if (!_useWorkers) { // If there is no support for workers
let rnd = 0n
do {
rnd = fromBuffer(randBitsSync(bitLength, true))
} while (!_isProbablyPrime(rnd, iterations))
return new Promise((resolve) => { resolve(rnd) })
}
return new Promise((resolve) => {
const workerList = []
const _onmessage = (msg, newWorker) => {
if (msg.isPrime) {
// if a prime number has been found, stop all the workers, and return it
for (let j = 0; j < workerList.length; j++) {
workerList[j].terminate()
}
while (workerList.length) {
workerList.pop()
}
resolve(msg.value)
} else { // if a composite is found, make the worker test another random number
const buf = randBitsSync(bitLength, true)
const rnd = fromBuffer(buf)
try {
newWorker.postMessage({
rnd: rnd,
iterations: iterations,
id: msg.id
})
} catch (error) {
// The worker has already terminated. There is nothing to handle here
}
}
}
/* eslint-disable no-lone-blocks */
{ // Node.js
const { cpus } = require('os')
const { Worker } = require('worker_threads')
for (let i = 0; i < cpus().length - 1; i++) {
const newWorker = new Worker(__filename)
newWorker.on('message', (msg) => _onmessage(msg, newWorker))
workerList.push(newWorker)
}
}
/* eslint-enable no-lone-blocks */
for (let i = 0; i < workerList.length; i++) {
randBits(bitLength, true).then(function (buf) {
const rnd = fromBuffer(buf)
workerList[i].postMessage({
rnd: rnd,
iterations: iterations,
id: i
})
})
}
})
}
/**
* 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.
*
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {bigint} A bigint probable prime of bitLength bits.
*/
function primeSync (bitLength, iterations = 16) {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
let rnd = 0n
do {
rnd = fromBuffer(randBitsSync(bitLength, true))
} while (!_isProbablyPrime(rnd, iterations))
return rnd
}
/**
* Returns a cryptographically secure random integer between [min,max]. Both numbers must be >=0
* @param {bigint} max Returned value will be <= max
* @param {bigint} [min = BigInt(1)] Returned value will be >= min
*
* @throws {RangeError} Arguments MUST be: max > 0 && min >=0 && max > min
*
* @returns {bigint} A cryptographically secure random bigint between [min,max]
*/
function randBetween (max, min = 1n) {
if (max <= 0n || min < 0n || max <= min) throw new RangeError('Arguments MUST be: max > 0 && min >=0 && max > min')
const interval = max - min
const bitLen = bitLength(interval)
let rnd
do {
const buf = randBitsSync(bitLen)
rnd = fromBuffer(buf)
} while (rnd > interval)
return rnd + min
}
/**
* Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
*
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {Promise<Buffer | Uint8Array>} A Promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
*/
function randBits (bitLength, forceLength = false) {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
const byteLength = Math.ceil(bitLength / 8)
const bitLengthMod8 = bitLength % 8
return new Promise((resolve) => {
randBytes(byteLength, false).then(function (rndBytes) {
if (bitLengthMod8) {
// Fill with 0's the extra bits
rndBytes[0] = rndBytes[0] & (2 ** bitLengthMod8 - 1)
}
if (forceLength) {
const mask = bitLengthMod8 ? 2 ** (bitLengthMod8 - 1) : 128
rndBytes[0] = rndBytes[0] | mask
}
resolve(rndBytes)
})
})
}
/**
* Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
*/
function randBitsSync (bitLength, forceLength = false) {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
const byteLength = Math.ceil(bitLength / 8)
const rndBytes = randBytesSync(byteLength, false)
const bitLengthMod8 = bitLength % 8
if (bitLengthMod8) {
// Fill with 0's the extra bits
rndBytes[0] = rndBytes[0] & (2 ** bitLengthMod8 - 1)
}
if (forceLength) {
const mask = bitLengthMod8 ? 2 ** (bitLengthMod8 - 1) : 128
rndBytes[0] = rndBytes[0] | mask
}
return rndBytes
}
/**
* Secure random bytes for both node and browsers. Node version uses crypto.randomBytes() and browser one self.crypto.getRandomValues()
*
* @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
*
* @throws {RangeError} byteLength MUST be > 0
*
* @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) {
if (byteLength < 1) throw new RangeError('byteLength MUST be > 0')
return new Promise(function (resolve, reject) {
/* eslint-disable no-lone-blocks */
{
const crypto = require('crypto')
crypto.randomBytes(byteLength, function (err, buf) {
/* istanbul ignore if */
if (err) reject(err)
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if (forceLength) buf[0] = buf[0] | 128
resolve(buf)
})
}
/* eslint-enable no-lone-blocks */
})
}
/**
* 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 {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
*
* @throws {RangeError} byteLength MUST be > 0
*
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
*/
function randBytesSync (byteLength, forceLength = false) {
if (byteLength < 1) throw new RangeError('byteLength MUST be > 0')
/* eslint-disable no-lone-blocks */
{ // node
const crypto = require('crypto')
const buf = crypto.randomBytes(byteLength)
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if (forceLength) buf[0] = buf[0] | 128
return buf
}
/* eslint-enable no-lone-blocks */
}
/* HELPER FUNCTIONS */
function fromBuffer (buf) {
let ret = 0n
for (const i of buf.values()) {
const bi = BigInt(i)
ret = (ret << BigInt(8)) + bi
}
return ret
}
function _isProbablyPrime (w, iterations = 16) {
/*
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.
*/
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.
*/
const firstPrimes = [
3n,
5n,
7n,
11n,
13n,
17n,
19n,
23n,
29n,
31n,
37n,
41n,
43n,
47n,
53n,
59n,
61n,
67n,
71n,
73n,
79n,
83n,
89n,
97n,
101n,
103n,
107n,
109n,
113n,
127n,
131n,
137n,
139n,
149n,
151n,
157n,
163n,
167n,
173n,
179n,
181n,
191n,
193n,
197n,
199n,
211n,
223n,
227n,
229n,
233n,
239n,
241n,
251n,
257n,
263n,
269n,
271n,
277n,
281n,
283n,
293n,
307n,
311n,
313n,
317n,
331n,
337n,
347n,
349n,
353n,
359n,
367n,
373n,
379n,
383n,
389n,
397n,
401n,
409n,
419n,
421n,
431n,
433n,
439n,
443n,
449n,
457n,
461n,
463n,
467n,
479n,
487n,
491n,
499n,
503n,
509n,
521n,
523n,
541n,
547n,
557n,
563n,
569n,
571n,
577n,
587n,
593n,
599n,
601n,
607n,
613n,
617n,
619n,
631n,
641n,
643n,
647n,
653n,
659n,
661n,
673n,
677n,
683n,
691n,
701n,
709n,
719n,
727n,
733n,
739n,
743n,
751n,
757n,
761n,
769n,
773n,
787n,
797n,
809n,
811n,
821n,
823n,
827n,
829n,
839n,
853n,
857n,
859n,
863n,
877n,
881n,
883n,
887n,
907n,
911n,
919n,
929n,
937n,
941n,
947n,
953n,
967n,
971n,
977n,
983n,
991n,
997n,
1009n,
1013n,
1019n,
1021n,
1031n,
1033n,
1039n,
1049n,
1051n,
1061n,
1063n,
1069n,
1087n,
1091n,
1093n,
1097n,
1103n,
1109n,
1117n,
1123n,
1129n,
1151n,
1153n,
1163n,
1171n,
1181n,
1187n,
1193n,
1201n,
1213n,
1217n,
1223n,
1229n,
1231n,
1237n,
1249n,
1259n,
1277n,
1279n,
1283n,
1289n,
1291n,
1297n,
1301n,
1303n,
1307n,
1319n,
1321n,
1327n,
1361n,
1367n,
1373n,
1381n,
1399n,
1409n,
1423n,
1427n,
1429n,
1433n,
1439n,
1447n,
1451n,
1453n,
1459n,
1471n,
1481n,
1483n,
1487n,
1489n,
1493n,
1499n,
1511n,
1523n,
1531n,
1543n,
1549n,
1553n,
1559n,
1567n,
1571n,
1579n,
1583n,
1597n
]
for (let i = 0; i < firstPrimes.length && (firstPrimes[i] <= w); i++) {
const p = firstPrimes[i]
if (w === p) return true
else if (w % p === 0n) return false
}
/*
1. Let a be the largest integer such that 2**a divides w1.
2. m = (w1) / 2**a.
3. wlen = len (w).
4. For i = 1 to iterations do
4.1 Obtain a string b of wlen bits from an RBG.
Comment: Ensure that 1 < b < w1.
4.2 If ((b 1) or (b w1)), then go to step 4.1.
4.3 z = b**m mod w.
4.4 If ((z = 1) or (z = w 1)), then go to step 4.7.
4.5 For j = 1 to a 1 do.
4.5.1 z = z**2 mod w.
4.5.2 If (z = w1), then go to step 4.7.
4.5.3 If (z = 1), then go to step 4.6.
4.6 Return COMPOSITE.
4.7 Continue.
Comment: Increment i for the do-loop in step 4.
5. Return PROBABLY PRIME.
*/
let a = 0n
const d = w - 1n
let aux = d
while (aux % 2n === 0n) {
aux /= 2n
++a
}
const m = d / (2n ** a)
do {
const b = randBetween(d, 2n)
let z = modPow(b, m, w)
if (z === 1n || z === d) continue
let j = 1
while (j < a) {
z = modPow(z, 2n, w)
if (z === d) break
if (z === 1n) return false
j++
}
if (z !== d) return false
} while (--iterations)
return true
}
let _useWorkers = false // The following is just to check whether we can use workers
/* eslint-disable no-lone-blocks */
{ // Node.js
try {
require.resolve('worker_threads')
_useWorkers = true
} catch (e) {
/* istanbul ignore next */
console.log(`[bigint-crypto-utils] WARNING:
This node version doesn't support worker_threads. You should enable them in order to greatly speedup the generation of big prime numbers.
· With Node >=11 it is enabled by default (consider upgrading).
· With Node 10, starting with 10.5.0, you can enable worker_threads at runtime executing node --experimental-worker `)
}
}
/* eslint-enable no-lone-blocks */
if (_useWorkers) { // node.js with support for workers
const { parentPort, isMainThread } = require('worker_threads')
/* istanbul ignore if */
if (!isMainThread) { // worker
parentPort.on('message', function (data) { // Let's start once we are called
// data = {rnd: <bigint>, iterations: <number>}
const isPrime = _isProbablyPrime(data.rnd, data.iterations)
parentPort.postMessage({
isPrime: isPrime,
value: data.rnd,
id: data.id
})
})
}
}
exports.abs = abs
exports.bitLength = bitLength
exports.eGcd = eGcd
exports.gcd = gcd
exports.isProbablyPrime = isProbablyPrime
exports.lcm = lcm
exports.max = max
exports.min = min
exports.modInv = modInv
exports.modPow = modPow
exports.prime = prime
exports.primeSync = primeSync
exports.randBetween = randBetween
exports.randBits = randBits
exports.randBitsSync = randBitsSync
exports.randBytes = randBytes
exports.randBytesSync = randBytesSync
exports.toZn = toZn

10067
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -21,64 +21,98 @@
"url": "https://github.com/juanelas"
},
"repository": "github:juanelas/bigint-crypto-utils",
"main": "./lib/index.node.js",
"browser": "./lib/index.browser.mod.js",
"types": "./types/index.d.ts",
"directories": {
"build": "./build",
"lib": "./lib",
"src": "./src",
"test": "./test",
"types": "./types"
},
"engines": {
"node": ">=10.4.0"
},
"scripts": {
"test": "nyc mocha",
"coverage": "nyc report --reporter=lcov",
"build:js": "rollup -c build/rollup.config.js",
"build:standard": "standard --fix",
"build:browserTests": "rollup -c build/rollup.tests.config.js",
"build:docs": "node build/build.docs.js",
"build:dts": "node build/build.dts.js",
"build": "run-s build:**",
"preversion": "npm run build && npm run test",
"postversion": "git push"
"types": "./dist/esm/types/index.d.ts",
"main": "./dist/cjs/index.node.cjs",
"browser": "./dist/esm/index.browser.js",
"module": "./dist/esm/index.node.js",
"exports": {
".": {
"node": {
"require": "./dist/cjs/index.node.cjs",
"import": "./dist/esm/index.node.js"
},
"default": "./dist/esm/index.browser.js"
},
"./bundles/": "./dist/bundles/",
"./types/": "./dist/esm/types/"
},
"standard": {
"directories": {
"build": "./build",
"dist": "./dist",
"docs": "./docs",
"src": "./src",
"test": "./test"
},
"scripts": {
"build": "run-s lint build:js docs test:browser coverage",
"build:js": "rollup -c build/rollup.config.js",
"clean": "rimraf .nyc_output .mocha-ts coverage dist docs",
"coverage": "nyc --check-coverage --exclude build --exclude '{src/**/*.spec.ts,test/**/*.ts}' --reporter=text --reporter=lcov node ./build/bin/mocha-ts.js --require build/testing/mocha/mocha-init.js '{src/**/*.spec.ts,test/**/*.ts}'",
"docs": "node build/build.docs.js",
"lint": "ts-standard --fix",
"mocha": "node ./build/bin/mocha-ts.js --require build/testing/mocha/mocha-init.js ",
"preversion": "run-s lint build:js test:browser coverage",
"postversion": "npm run docs",
"test": "run-s test:browser test:node",
"test:browser": "node build/testing/browser/index.js",
"test:node": "npm run mocha -- '{src/**/*.spec.ts,test/**/*.ts}'",
"watch": "npm run mocha -- --watch '{src/**/*.spec.ts,test/**/*.ts}'"
},
"ts-standard": {
"env": [
"mocha"
],
"globals": [
"BigInt",
"Blob",
"postMessage",
"self",
"Worker"
"Worker",
"IS_BROWSER",
"browser",
"page",
"_pkg",
"chai"
],
"project": "./tsconfig.json",
"ignore": [
"/test/browser/",
"/lib/index.browser.bundle.iife.js",
"/lib/index.browser.bundle.mod.js"
"dist/**/*",
"examples/**/*"
]
},
"devDependencies": {
"@rollup/plugin-commonjs": "^16.0.0",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-multi-entry": "^4.0.0",
"@rollup/plugin-node-resolve": "^10.0.0",
"@rollup/plugin-replace": "^2.3.4",
"chai": "^4.2.0",
"jsdoc-to-markdown": "^6.0.1",
"mocha": "^8.2.1",
"@rollup/plugin-node-resolve": "^11.2.0",
"@rollup/plugin-replace": "^2.4.1",
"@rollup/plugin-typescript": "^8.2.0",
"@types/chai": "^4.2.14",
"@types/mocha": "^8.2.1",
"@types/node": ">=10.4",
"chai": "^4.3.3",
"glob": "^7.1.6",
"json5": "^2.2.0",
"minimatch": "^3.0.4",
"mocha": "^8.3.0",
"npm-run-all": "^4.1.5",
"nyc": "^15.1.0",
"rollup": "^2.33.1",
"pirates": "^4.0.1",
"puppeteer": "^8.0.0",
"rimraf": "^3.0.2",
"rollup": "^2.40.0",
"rollup-plugin-terser": "^7.0.2",
"standard": "^16.0.2",
"typescript": "^3.9.7"
"ts-standard": "^10.0.0",
"tslib": "^2.1.0",
"typedoc": "^0.20.29",
"typedoc-plugin-markdown": "^3.6.0",
"typescript": "^4.2.2"
},
"dependencies": {
"@types/node": ">=10.4"
"bigint-mod-arith": "^3.0.0"
},
"peerDependencies": {
"@types/node": ">10.4"
}
}

View File

@ -1,17 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>{{PKG_NAME}} - Mocha Tests</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/{{MOCHA_VERSION}}/mocha.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/{{MOCHA_VERSION}}/mocha.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/{{CHAI_VERSION}}/chai.min.js"></script>
</head>
<body>
<div id="mocha"></div>
<script>mocha.setup('bdd'); mocha.setup({ timeout: 90000 });</script>
{{TESTS}}
</body>
</html>

View File

@ -12,89 +12,61 @@ Secure random numbers are generated using the native crypto implementation of th
> The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html).** Many platforms provide native support for cryptography, such as [Web Cryptography API](https://w3c.github.io/webcrypto/) or [Node.js Crypto](https://nodejs.org/dist/latest/docs/api/crypto.html).
## Installation
## Usage
{{PKG_NAME}} can be imported to your project with `npm`:
`{{PKG_NAME}}` can be imported to your project with `npm`:
```bash
```console
npm install {{PKG_NAME}}
```
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_BUNDLE}} or the {{ESM_BUNDLE}} from the repository.
Then either require (Node.js CJS):
## Usage examples
```javascript
const {{PKG_CAMELCASE}} = require('{{PKG_NAME}}')
```
Import your module as :
or import (JavaScript ES module):
- Node.js
```javascript
import * as {{PKG_CAMELCASE}} from '{{PKG_NAME}}'
```
```javascript
const bigintCryptoUtils = require('bigint-crypto-utils')
... // your code here
```
The appropriate version for browser or node is automatically exported.
- JavaScript native or TypeScript project (including React and Angular JS)
`{{PKG_NAME}}` **CANNOT BE POLYFILLED** to suport older JS version (\< ES2020). If you are using webpack/babel to create your production bundles, you should target only the most modern browsers. For instance, for **React** apps created with [`create-react-app`](https://create-react-app.dev/), you should edit your `package.json` and modify the `browserList` so that it only targets the latest browsers (play with the number of versions that do not need polyfilling):
```javascript
import * as bigintCryptoUtils from 'bigint-crypto-utils'
... // your code here
```
```json
"browserslist": {
"production": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
```
`{{PKG_NAME}}` **CANNOT BE POLYFILLED** to suport older browsers. If you are using webpack/babel to create your production bundles, you should target only the most modern browsers. For instance, for **React** apps created with [`create-react-app`](https://create-react-app.dev/), you should edit your `package.json` and modify the `browserList` so that it only targets the latest browsers (play with the number of versions that do not need polyfilling):
Also, notice that [BigInt implementation is ES2020](https://tc39.es/ecma262/#sec-bigint-objects). In order to use it with TypeScript you need to set `target` to `ES2020` in your project's `tsconfig.json`.
```json
"browserslist": {
"production": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
```
If you are using Angular, since this library uses node typings, you should also add them to the `angularCompilerOptions` in your `tsconfig.json`:
Also, notice that [BigInt implementation is ES2020](https://tc39.es/ecma262/#sec-bigint-objects). In order to use it with TypeScript you will probably need to set `lib`, `target` and/or `module` to `es2020` in your project's `tsconfig.json`.
```json
"angularCompilerOptions": {
"types": ["node", ...]
...
}
```
If you are using Angular, since this library uses node typings, you should also add them to the `angularCompilerOptions` in your `tsconfig.json`:
```json
"angularCompilerOptions": {
"types": ["node"]
...
}
```
- JavaScript native browser ES module
```html
<script type="module">
import * as bigintCryptoUtils from 'index.browser.bundle.mod.js' // Use your actual path to the broser mod bundle that is in the lib directory
... // your code here
</script>
```
- JavaScript native browser IIFE
```html
<head>
...
<script src="index.browser.bundle.iife.js"></script> <!-- Use your actual path to the browser iife bundle that is in the lib directory -->
</head>
<body>
...
<script>
... // your code here
</script>
</body>
```
You can also download the {{IIFE_BUNDLE}}, the {{ESM_BUNDLE}} or the {{UMD_BUNDLE}} and manually add it to your project, or, if you have already imported `{{PKG_NAME}}` to your project, just get the bundles from `node_modules/{{PKG_NAME}}/dist/bundles/`.
An example of usage could be:
```javascript
```typescript
/* A BigInt with value 666 can be declared calling the bigint constructor as
BigInt('666') or with the shorter 666n.
Notice that you can also pass a number to the constructor, e.g. BigInt(666).
@ -113,14 +85,14 @@ console.log(bigintCryptoUtils.modInv(BigInt('3'), BigInt('5'))) // prints 2
console.log(bigintCryptoUtils.randBetween(2n ** 256n)) // Prints a cryptographically secure random number between 1 and 2**256 bits.
async function primeTesting () {
async function primeTesting (): void {
// Output of a probable prime of 2048 bits
console.log(await bigintCryptoUtils.prime(2048))
// Testing if a number is a probable prime (Miller-Rabin)
const number = 27n
const isPrime = await bigintCryptoUtils.isProbablyPrime(number)
if (isPrime) {
if (isPrime === true) {
console.log(`${number} is prime`)
} else {
console.log(`${number} is composite`)
@ -131,8 +103,6 @@ primeTesting()
```
You can find examples in the [examples folder of the repository](https://github.com/juanelas/bigint-crypto-utils/tree/master/examples).
## API reference documentation
{{>main}}
[Check the API](./docs/API.md)

7
src/index.ts Normal file
View File

@ -0,0 +1,7 @@
export { abs, bitLength, eGcd, gcd, lcm, max, min, modInv, modPow, toZn } from 'bigint-mod-arith'
export { isProbablyPrime } from './ts/isProbablyPrime'
export { prime, primeSync } from './ts/prime'
export { randBetween } from './ts/randBetween'
export { randBits, randBitsSync } from './ts/randBits'
export { randBytes, randBytesSync } from './ts/randBytes'

View File

@ -1,214 +0,0 @@
/**
* 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 >= 0n) ? 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 === 1n) { return 1 }
let bits = 1
do {
bits++
} while ((a >>= 1n) > 1n)
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
*
* @throws {RangeError} a and b MUST be > 0
*
* @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 <= 0n | b <= 0n) throw new RangeError('a and b MUST be > 0') // a and b MUST be positive
let x = 0n
let y = 1n
let u = 1n
let v = 0n
while (a !== 0n) {
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 {
g: 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 === 0n) { return b } else if (b === 0n) { return a }
let shift = 0n
while (!((a | b) & 1n)) {
a >>= 1n
b >>= 1n
shift++
}
while (!(a & 1n)) a >>= 1n
do {
while (!(b & 1n)) b >>= 1n
if (a > b) {
const x = a
a = b
b = x
}
b -= a
} while (b)
// rescale
return a << shift
}
/**
* 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 === 0n && b === 0n) return BigInt(0)
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
*
* @throws {RangeError} a does not have inverse modulo n
*
* @returns {bigint} the inverse modulo n
*/
export function modInv (a, n) {
const egcd = eGcd(toZn(a, n), n)
if (egcd.g !== 1n) {
throw new RangeError(`${a.toString()} does not have inverse modulo ${n.toString()}`) // 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 === 0n) { throw new RangeError('n must be > 0') } else if (n === 1n) { return BigInt(0) }
b = toZn(b, n)
e = BigInt(e)
if (e < 0n) {
return modInv(modPow(b, abs(e), n), n)
}
let r = 1n
while (e > 0) {
if ((e % 2n) === 1n) {
r = (r * b) % n
}
e = e / 2n
b = b ** 2n % n
}
return r
}
/**
* 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
}

View File

@ -1,699 +0,0 @@
import { bitLength, eGcd, modInv, modPow, toZn } from './bigint-mod-arith'
export { abs, bitLength, eGcd, gcd, lcm, max, min, modInv, modPow, toZn } from './bigint-mod-arith'
/**
* 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)
*
* @param {number | bigint} w A positive 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 {boolean} [disableWorkers = false] Disable the use of workers for the primality test
*
* @throws {RangeError} w MUST be >= 0
*
* @returns {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, iterations = 16, disableWorkers = false) {
if (typeof w === 'number') {
w = BigInt(w)
}
if (w < 0) throw RangeError('w MUST be >= 0')
/* eslint-disable no-lone-blocks */
if (!process.browser) { // Node.js
/* istanbul ignore else */
if (!disableWorkers && _useWorkers) {
const { Worker } = require('worker_threads')
return new Promise((resolve, reject) => {
const worker = new Worker(__filename)
worker.on('message', (data) => {
worker.terminate()
resolve(data.isPrime)
})
worker.on('error', reject)
worker.postMessage({
rnd: w,
iterations: iterations,
id: 0
})
})
} else {
return new Promise((resolve) => {
resolve(_isProbablyPrime(w, iterations))
})
}
} else { // browser
return new Promise((resolve, reject) => {
const worker = new Worker(_isProbablyPrimeWorkerUrl())
worker.onmessage = (event) => {
worker.terminate()
resolve(event.data.isPrime)
}
worker.onmessageerror = (event) => {
reject(event)
}
worker.postMessage({
rnd: w,
iterations: iterations,
id: 0
})
})
}
/* eslint-enable no-lone-blocks */
}
/**
* 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).
*
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {Promise<bigint>} A promise that resolves to a bigint probable prime of bitLength bits.
*/
export function prime (bitLength, iterations = 16) {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
/* istanbul ignore if */
if (!_useWorkers) { // If there is no support for workers
let rnd = 0n
do {
rnd = fromBuffer(randBitsSync(bitLength, true))
} while (!_isProbablyPrime(rnd, iterations))
return new Promise((resolve) => { resolve(rnd) })
}
return new Promise((resolve) => {
const workerList = []
const _onmessage = (msg, newWorker) => {
if (msg.isPrime) {
// if a prime number has been found, stop all the workers, and return it
for (let j = 0; j < workerList.length; j++) {
workerList[j].terminate()
}
while (workerList.length) {
workerList.pop()
}
resolve(msg.value)
} else { // if a composite is found, make the worker test another random number
const buf = randBitsSync(bitLength, true)
const rnd = fromBuffer(buf)
try {
newWorker.postMessage({
rnd: rnd,
iterations: iterations,
id: msg.id
})
} catch (error) {
// The worker has already terminated. There is nothing to handle here
}
}
}
/* eslint-disable no-lone-blocks */
if (process.browser) { // browser
const workerURL = _isProbablyPrimeWorkerUrl()
for (let i = 0; i < self.navigator.hardwareConcurrency - 1; i++) {
const newWorker = new Worker(workerURL)
newWorker.onmessage = (event) => _onmessage(event.data, newWorker)
workerList.push(newWorker)
}
} else { // Node.js
const { cpus } = require('os')
const { Worker } = require('worker_threads')
for (let i = 0; i < cpus().length - 1; i++) {
const newWorker = new Worker(__filename)
newWorker.on('message', (msg) => _onmessage(msg, newWorker))
workerList.push(newWorker)
}
}
/* eslint-enable no-lone-blocks */
for (let i = 0; i < workerList.length; i++) {
randBits(bitLength, true).then(function (buf) {
const rnd = fromBuffer(buf)
workerList[i].postMessage({
rnd: rnd,
iterations: iterations,
id: i
})
})
}
})
}
/**
* 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.
*
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {bigint} A bigint probable prime of bitLength bits.
*/
export function primeSync (bitLength, iterations = 16) {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
let rnd = 0n
do {
rnd = fromBuffer(randBitsSync(bitLength, true))
} while (!_isProbablyPrime(rnd, iterations))
return rnd
}
/**
* Returns a cryptographically secure random integer between [min,max]. Both numbers must be >=0
* @param {bigint} max Returned value will be <= max
* @param {bigint} [min = BigInt(1)] Returned value will be >= min
*
* @throws {RangeError} Arguments MUST be: max > 0 && min >=0 && max > min
*
* @returns {bigint} A cryptographically secure random bigint between [min,max]
*/
export function randBetween (max, min = 1n) {
if (max <= 0n || min < 0n || max <= min) throw new RangeError('Arguments MUST be: max > 0 && min >=0 && max > min')
const interval = max - min
const bitLen = bitLength(interval)
let rnd
do {
const buf = randBitsSync(bitLen)
rnd = fromBuffer(buf)
} while (rnd > interval)
return rnd + min
}
/**
* Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
*
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {Promise<Buffer | Uint8Array>} A Promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
*/
export function randBits (bitLength, forceLength = false) {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
const byteLength = Math.ceil(bitLength / 8)
const bitLengthMod8 = bitLength % 8
return new Promise((resolve) => {
randBytes(byteLength, false).then(function (rndBytes) {
if (bitLengthMod8) {
// Fill with 0's the extra bits
rndBytes[0] = rndBytes[0] & (2 ** bitLengthMod8 - 1)
}
if (forceLength) {
const mask = bitLengthMod8 ? 2 ** (bitLengthMod8 - 1) : 128
rndBytes[0] = rndBytes[0] | mask
}
resolve(rndBytes)
})
})
}
/**
* Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
*/
export function randBitsSync (bitLength, forceLength = false) {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
const byteLength = Math.ceil(bitLength / 8)
const rndBytes = randBytesSync(byteLength, false)
const bitLengthMod8 = bitLength % 8
if (bitLengthMod8) {
// Fill with 0's the extra bits
rndBytes[0] = rndBytes[0] & (2 ** bitLengthMod8 - 1)
}
if (forceLength) {
const mask = bitLengthMod8 ? 2 ** (bitLengthMod8 - 1) : 128
rndBytes[0] = rndBytes[0] | mask
}
return rndBytes
}
/**
* Secure random bytes for both node and browsers. Node version uses crypto.randomBytes() and browser one self.crypto.getRandomValues()
*
* @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
*
* @throws {RangeError} byteLength MUST be > 0
*
* @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) {
if (byteLength < 1) throw new RangeError('byteLength MUST be > 0')
return new Promise(function (resolve, reject) {
/* eslint-disable no-lone-blocks */
if (!process.browser) {
const crypto = require('crypto')
crypto.randomBytes(byteLength, function (err, buf) {
/* istanbul ignore if */
if (err) reject(err)
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if (forceLength) buf[0] = buf[0] | 128
resolve(buf)
})
} else { // browser
const buf = new Uint8Array(byteLength)
self.crypto.getRandomValues(buf)
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if (forceLength) buf[0] = buf[0] | 128
resolve(buf)
}
/* eslint-enable no-lone-blocks */
})
}
/**
* 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 {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
*
* @throws {RangeError} byteLength MUST be > 0
*
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
*/
export function randBytesSync (byteLength, forceLength = false) {
if (byteLength < 1) throw new RangeError('byteLength MUST be > 0')
/* eslint-disable no-lone-blocks */
if (!process.browser) { // node
const crypto = require('crypto')
const buf = crypto.randomBytes(byteLength)
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if (forceLength) buf[0] = buf[0] | 128
return buf
} else { // browser
const buf = new Uint8Array(byteLength)
self.crypto.getRandomValues(buf)
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if (forceLength) buf[0] = buf[0] | 128
return buf
}
/* eslint-enable no-lone-blocks */
}
/* HELPER FUNCTIONS */
function fromBuffer (buf) {
let ret = 0n
for (const i of buf.values()) {
const bi = BigInt(i)
ret = (ret << BigInt(8)) + bi
}
return ret
}
function _isProbablyPrimeWorkerUrl () {
// Let's us first add all the required functions
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 ${randBitsSync.name}=${randBitsSync.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
// event.data = {rnd: <bigint>, iterations: <number>}
const isPrime = await isProbablyPrime(event.data.rnd, event.data.iterations)
postMessage({
isPrime: isPrime,
value: event.data.rnd,
id: event.data.id
})
}
workerCode += `onmessage = ${onmessage.toString()};`
return _workerUrl(workerCode)
}
function _workerUrl (workerCode) {
workerCode = `(() => {${workerCode}})()` // encapsulate IIFE
const _blob = new Blob([workerCode], { type: 'text/javascript' })
return window.URL.createObjectURL(_blob)
}
function _isProbablyPrime (w, iterations = 16) {
/*
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.
*/
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.
*/
const firstPrimes = [
3n,
5n,
7n,
11n,
13n,
17n,
19n,
23n,
29n,
31n,
37n,
41n,
43n,
47n,
53n,
59n,
61n,
67n,
71n,
73n,
79n,
83n,
89n,
97n,
101n,
103n,
107n,
109n,
113n,
127n,
131n,
137n,
139n,
149n,
151n,
157n,
163n,
167n,
173n,
179n,
181n,
191n,
193n,
197n,
199n,
211n,
223n,
227n,
229n,
233n,
239n,
241n,
251n,
257n,
263n,
269n,
271n,
277n,
281n,
283n,
293n,
307n,
311n,
313n,
317n,
331n,
337n,
347n,
349n,
353n,
359n,
367n,
373n,
379n,
383n,
389n,
397n,
401n,
409n,
419n,
421n,
431n,
433n,
439n,
443n,
449n,
457n,
461n,
463n,
467n,
479n,
487n,
491n,
499n,
503n,
509n,
521n,
523n,
541n,
547n,
557n,
563n,
569n,
571n,
577n,
587n,
593n,
599n,
601n,
607n,
613n,
617n,
619n,
631n,
641n,
643n,
647n,
653n,
659n,
661n,
673n,
677n,
683n,
691n,
701n,
709n,
719n,
727n,
733n,
739n,
743n,
751n,
757n,
761n,
769n,
773n,
787n,
797n,
809n,
811n,
821n,
823n,
827n,
829n,
839n,
853n,
857n,
859n,
863n,
877n,
881n,
883n,
887n,
907n,
911n,
919n,
929n,
937n,
941n,
947n,
953n,
967n,
971n,
977n,
983n,
991n,
997n,
1009n,
1013n,
1019n,
1021n,
1031n,
1033n,
1039n,
1049n,
1051n,
1061n,
1063n,
1069n,
1087n,
1091n,
1093n,
1097n,
1103n,
1109n,
1117n,
1123n,
1129n,
1151n,
1153n,
1163n,
1171n,
1181n,
1187n,
1193n,
1201n,
1213n,
1217n,
1223n,
1229n,
1231n,
1237n,
1249n,
1259n,
1277n,
1279n,
1283n,
1289n,
1291n,
1297n,
1301n,
1303n,
1307n,
1319n,
1321n,
1327n,
1361n,
1367n,
1373n,
1381n,
1399n,
1409n,
1423n,
1427n,
1429n,
1433n,
1439n,
1447n,
1451n,
1453n,
1459n,
1471n,
1481n,
1483n,
1487n,
1489n,
1493n,
1499n,
1511n,
1523n,
1531n,
1543n,
1549n,
1553n,
1559n,
1567n,
1571n,
1579n,
1583n,
1597n
]
for (let i = 0; i < firstPrimes.length && (firstPrimes[i] <= w); i++) {
const p = firstPrimes[i]
if (w === p) return true
else if (w % p === 0n) return false
}
/*
1. Let a be the largest integer such that 2**a divides w1.
2. m = (w1) / 2**a.
3. wlen = len (w).
4. For i = 1 to iterations do
4.1 Obtain a string b of wlen bits from an RBG.
Comment: Ensure that 1 < b < w1.
4.2 If ((b 1) or (b w1)), then go to step 4.1.
4.3 z = b**m mod w.
4.4 If ((z = 1) or (z = w 1)), then go to step 4.7.
4.5 For j = 1 to a 1 do.
4.5.1 z = z**2 mod w.
4.5.2 If (z = w1), then go to step 4.7.
4.5.3 If (z = 1), then go to step 4.6.
4.6 Return COMPOSITE.
4.7 Continue.
Comment: Increment i for the do-loop in step 4.
5. Return PROBABLY PRIME.
*/
let a = 0n
const d = w - 1n
let aux = d
while (aux % 2n === 0n) {
aux /= 2n
++a
}
const m = d / (2n ** a)
do {
const b = randBetween(d, 2n)
let z = modPow(b, m, w)
if (z === 1n || z === d) continue
let j = 1
while (j < a) {
z = modPow(z, 2n, w)
if (z === d) break
if (z === 1n) return false
j++
}
if (z !== d) return false
} while (--iterations)
return true
}
let _useWorkers = false // The following is just to check whether we can use workers
/* eslint-disable no-lone-blocks */
if (!process.browser) { // Node.js
try {
require.resolve('worker_threads')
_useWorkers = true
} catch (e) {
/* istanbul ignore next */
console.log(`[bigint-crypto-utils] WARNING:
This node version doesn't support worker_threads. You should enable them in order to greatly speedup the generation of big prime numbers.
· With Node >=11 it is enabled by default (consider upgrading).
· With Node 10, starting with 10.5.0, you can enable worker_threads at runtime executing node --experimental-worker `)
}
} else { // Native JS
if (self.Worker) _useWorkers = true
}
/* eslint-enable no-lone-blocks */
if (!process.browser && _useWorkers) { // node.js with support for workers
const { parentPort, isMainThread } = require('worker_threads')
/* istanbul ignore if */
if (!isMainThread) { // worker
parentPort.on('message', function (data) { // Let's start once we are called
// data = {rnd: <bigint>, iterations: <number>}
const isPrime = _isProbablyPrime(data.rnd, data.iterations)
parentPort.postMessage({
isPrime: isPrime,
value: data.rnd,
id: data.id
})
})
}
}

8
src/ts/fromBuffer.ts Normal file
View File

@ -0,0 +1,8 @@
export function fromBuffer (buf: Uint8Array|Buffer): bigint {
let ret = 0n
for (const i of buf.values()) {
const bi = BigInt(i)
ret = (ret << BigInt(8)) + bi
}
return ret
}

427
src/ts/isProbablyPrime.ts Normal file
View File

@ -0,0 +1,427 @@
import { eGcd, modInv, modPow, toZn, bitLength } from 'bigint-mod-arith'
import { fromBuffer } from './fromBuffer'
import { randBetween } from './randBetween'
import { randBitsSync } from './randBits'
import { randBytesSync } from './randBytes'
import { _useWorkers, _workerUrl, WorkerToMainMsg, MainToWorkerMsg } from './workerUtils'
/**
* 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)
*
* @param w - A positive integer to be tested for primality
* @param iterations - The number of iterations for the primality test. The value shall be consistent with Table C.1, C.2 or C.3
* @param disableWorkers - Disable the use of workers for the primality test
*
* @throws {RangeError}
* w MUST be >= 0
*
* @returns 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 = 16, disableWorkers: boolean = false): Promise<boolean> { // eslint-disable-line
if (typeof w === 'number') {
w = BigInt(w)
}
if (w < 0n) throw RangeError('w MUST be >= 0')
if (!IS_BROWSER) { // Node.js
/* istanbul ignore else */
if (!disableWorkers && _useWorkers) {
const { Worker } = require('worker_threads') // eslint-disable-line
return new Promise((resolve, reject) => {
const worker = new Worker(__filename)
worker.on('message', (data: WorkerToMainMsg) => {
worker.terminate()
resolve(data.isPrime)
})
worker.on('error', reject)
const msg: MainToWorkerMsg = {
rnd: w as bigint,
iterations: iterations,
id: 0
}
worker.postMessage(msg)
})
} else {
return new Promise((resolve) => {
resolve(_isProbablyPrime(w as bigint, iterations))
})
}
} else { // browser
return new Promise((resolve, reject) => {
const worker = new Worker(_isProbablyPrimeWorkerUrl())
worker.onmessage = (event) => {
worker.terminate()
resolve(event.data.isPrime)
}
worker.onmessageerror = (event) => {
reject(event)
}
const msg: MainToWorkerMsg = {
rnd: w as bigint,
iterations: iterations,
id: 0
}
worker.postMessage(msg)
})
}
}
export function _isProbablyPrime (w: bigint, iterations: number = 16): boolean {
/*
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.
*/
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.
*/
const firstPrimes = [
3n,
5n,
7n,
11n,
13n,
17n,
19n,
23n,
29n,
31n,
37n,
41n,
43n,
47n,
53n,
59n,
61n,
67n,
71n,
73n,
79n,
83n,
89n,
97n,
101n,
103n,
107n,
109n,
113n,
127n,
131n,
137n,
139n,
149n,
151n,
157n,
163n,
167n,
173n,
179n,
181n,
191n,
193n,
197n,
199n,
211n,
223n,
227n,
229n,
233n,
239n,
241n,
251n,
257n,
263n,
269n,
271n,
277n,
281n,
283n,
293n,
307n,
311n,
313n,
317n,
331n,
337n,
347n,
349n,
353n,
359n,
367n,
373n,
379n,
383n,
389n,
397n,
401n,
409n,
419n,
421n,
431n,
433n,
439n,
443n,
449n,
457n,
461n,
463n,
467n,
479n,
487n,
491n,
499n,
503n,
509n,
521n,
523n,
541n,
547n,
557n,
563n,
569n,
571n,
577n,
587n,
593n,
599n,
601n,
607n,
613n,
617n,
619n,
631n,
641n,
643n,
647n,
653n,
659n,
661n,
673n,
677n,
683n,
691n,
701n,
709n,
719n,
727n,
733n,
739n,
743n,
751n,
757n,
761n,
769n,
773n,
787n,
797n,
809n,
811n,
821n,
823n,
827n,
829n,
839n,
853n,
857n,
859n,
863n,
877n,
881n,
883n,
887n,
907n,
911n,
919n,
929n,
937n,
941n,
947n,
953n,
967n,
971n,
977n,
983n,
991n,
997n,
1009n,
1013n,
1019n,
1021n,
1031n,
1033n,
1039n,
1049n,
1051n,
1061n,
1063n,
1069n,
1087n,
1091n,
1093n,
1097n,
1103n,
1109n,
1117n,
1123n,
1129n,
1151n,
1153n,
1163n,
1171n,
1181n,
1187n,
1193n,
1201n,
1213n,
1217n,
1223n,
1229n,
1231n,
1237n,
1249n,
1259n,
1277n,
1279n,
1283n,
1289n,
1291n,
1297n,
1301n,
1303n,
1307n,
1319n,
1321n,
1327n,
1361n,
1367n,
1373n,
1381n,
1399n,
1409n,
1423n,
1427n,
1429n,
1433n,
1439n,
1447n,
1451n,
1453n,
1459n,
1471n,
1481n,
1483n,
1487n,
1489n,
1493n,
1499n,
1511n,
1523n,
1531n,
1543n,
1549n,
1553n,
1559n,
1567n,
1571n,
1579n,
1583n,
1597n
]
for (let i = 0; i < firstPrimes.length && (firstPrimes[i] <= w); i++) {
const p = firstPrimes[i]
if (w === p) return true
else if (w % p === 0n) return false
}
/*
1. Let a be the largest integer such that 2**a divides w1.
2. m = (w1) / 2**a.
3. wlen = len (w).
4. For i = 1 to iterations do
4.1 Obtain a string b of wlen bits from an RBG.
Comment: Ensure that 1 < b < w1.
4.2 If ((b 1) or (b w1)), then go to step 4.1.
4.3 z = b**m mod w.
4.4 If ((z = 1) or (z = w 1)), then go to step 4.7.
4.5 For j = 1 to a 1 do.
4.5.1 z = z**2 mod w.
4.5.2 If (z = w1), then go to step 4.7.
4.5.3 If (z = 1), then go to step 4.6.
4.6 Return COMPOSITE.
4.7 Continue.
Comment: Increment i for the do-loop in step 4.
5. Return PROBABLY PRIME.
*/
let a = 0n
const d = w - 1n
let aux = d
while (aux % 2n === 0n) {
aux /= 2n
++a
}
const m = d / (2n ** a)
do {
const b = randBetween(d, 2n)
let z = modPow(b, m, w)
if (z === 1n || z === d) continue
let j = 1
while (j < a) {
z = modPow(z, 2n, w)
if (z === d) break
if (z === 1n) return false
j++
}
if (z !== d) return false
} while (--iterations !== 0)
return true
}
export function _isProbablyPrimeWorkerUrl (): string {
// Let's us first add all the required functions
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 ${randBitsSync.name}=${randBitsSync.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: {data: MainToWorkerMsg}): Promise<void> { // Let's start once we are called
// event.data = {rnd: <bigint>, iterations: <number>}
const isPrime = await isProbablyPrime(event.data.rnd, event.data.iterations)
const msg: WorkerToMainMsg = {
isPrime: isPrime,
value: event.data.rnd,
id: event.data.id
}
postMessage(msg)
}
workerCode += `onmessage = ${onmessage.toString()};`
return _workerUrl(workerCode)
}
if (!IS_BROWSER && _useWorkers) { // node.js with support for workers
const { parentPort, isMainThread } = require('worker_threads') // eslint-disable-line
const isWorker = !(isMainThread as boolean)
/* istanbul ignore if */
if (isWorker) { // worker
parentPort.on('message', function (data: MainToWorkerMsg) { // Let's start once we are called
const isPrime = _isProbablyPrime(data.rnd, data.iterations)
const msg: WorkerToMainMsg = {
isPrime: isPrime,
value: data.rnd,
id: data.id
}
parentPort.postMessage(msg)
})
}
}

107
src/ts/prime.ts Normal file
View File

@ -0,0 +1,107 @@
import { fromBuffer } from './fromBuffer'
import { _isProbablyPrime, _isProbablyPrimeWorkerUrl } from './isProbablyPrime'
import { randBits, randBitsSync } from './randBits'
import { _useWorkers, WorkerToMainMsg, MainToWorkerMsg } from './workerUtils'
/**
* 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).
*
* @param bitLength - The required bit length for the generated prime
* @param iterations - The number of iterations for the Miller-Rabin Probabilistic Primality Test
*
* @throws {RangeError}
* bitLength MUST be > 0
*
* @returns A promise that resolves to a bigint probable prime of bitLength bits.
*/
export function prime (bitLength: number, iterations: number = 16): Promise<bigint> { // eslint-disable-line
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
/* istanbul ignore if */
if (!_useWorkers) { // If there is no support for workers
let rnd = 0n
do {
rnd = fromBuffer(randBitsSync(bitLength, true))
} while (!_isProbablyPrime(rnd, iterations))
return new Promise((resolve) => { resolve(rnd) })
}
return new Promise((resolve, reject) => {
const workerList: Worker[] = []
const _onmessage = (msg: WorkerToMainMsg, newWorker: Worker): void => {
if (msg.isPrime) {
// if a prime number has been found, stop all the workers, and return it
for (let j = 0; j < workerList.length; j++) {
workerList[j].terminate()
}
while (workerList.length > 0) {
workerList.pop()
}
resolve(msg.value)
} else { // if a composite is found, make the worker test another random number
const buf = randBitsSync(bitLength, true)
const rnd = fromBuffer(buf)
try {
const msgToWorker: MainToWorkerMsg = {
rnd: rnd,
iterations: iterations,
id: msg.id
}
newWorker.postMessage(msgToWorker)
} catch (error) {
// The worker has already terminated. There is nothing to handle here
}
}
}
if (IS_BROWSER) { // browser
const workerURL = _isProbablyPrimeWorkerUrl()
for (let i = 0; i < self.navigator.hardwareConcurrency - 1; i++) {
const newWorker = new Worker(workerURL)
newWorker.onmessage = (event) => _onmessage(event.data, newWorker)
workerList.push(newWorker)
}
} else { // Node.js
const { cpus } = require('os') // eslint-disable-line
const { Worker } = require('worker_threads') // eslint-disable-line
for (let i = 0; i < cpus().length - 1; i++) {
const newWorker = new Worker(__filename)
newWorker.on('message', (msg: WorkerToMainMsg) => _onmessage(msg, newWorker))
workerList.push(newWorker)
}
}
for (let i = 0; i < workerList.length; i++) {
randBits(bitLength, true).then(function (buf: Uint8Array|Buffer) {
const rnd = fromBuffer(buf)
workerList[i].postMessage({
rnd: rnd,
iterations: iterations,
id: i
})
}).catch(reject)
}
})
}
/**
* 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.
*
* @param bitLength - The required bit length for the generated prime
* @param iterations - The number of iterations for the Miller-Rabin Probabilistic Primality Test
*
* @throws {RangeError}
* bitLength MUST be > 0
*
* @returns A bigint probable prime of bitLength bits.
*/
export function primeSync (bitLength: number, iterations: number = 16): bigint {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
let rnd = 0n
do {
rnd = fromBuffer(randBitsSync(bitLength, true))
} while (!_isProbablyPrime(rnd, iterations))
return rnd
}

25
src/ts/randBetween.ts Normal file
View File

@ -0,0 +1,25 @@
import { bitLength } from 'bigint-mod-arith'
import { fromBuffer } from './fromBuffer'
import { randBitsSync } from './randBits'
/**
* Returns a cryptographically secure random integer between [min,max]. Both numbers must be >=0
* @param max Returned value will be <= max
* @param min Returned value will be >= min
*
* @throws {RangeError}
* Arguments MUST be: max > 0 && min >=0 && max > min
*
* @returns A cryptographically secure random bigint between [min,max]
*/
export function randBetween (max: bigint, min: bigint = 1n): bigint {
if (max <= 0n || min < 0n || max <= min) throw new RangeError('Arguments MUST be: max > 0 && min >=0 && max > min')
const interval = max - min
const bitLen = bitLength(interval)
let rnd
do {
const buf = randBitsSync(bitLen)
rnd = fromBuffer(buf)
} while (rnd > interval)
return rnd + min
}

60
src/ts/randBits.ts Normal file
View File

@ -0,0 +1,60 @@
import { randBytes, randBytesSync } from './randBytes'
/**
* Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
*
* @param bitLength - The desired number of random bits
* @param forceLength - If we want to force the output to have a specific bit length. It basically forces the msb to be 1
*
* @throws {RangeError}
* bitLength MUST be > 0
*
* @returns A Promise that resolves to a UInt8Array/Buffer (Browser/Node.js) filled with cryptographically secure random bits
*/
export function randBits (bitLength: number, forceLength: boolean = false): Promise<Uint8Array|Buffer> { // eslint-disable-line
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
const byteLength = Math.ceil(bitLength / 8)
const bitLengthMod8 = bitLength % 8
return new Promise((resolve, reject) => {
randBytes(byteLength, false).then(function (rndBytes) { // eslint-disable-line
if (bitLengthMod8 !== 0) {
// Fill with 0's the extra bits
rndBytes[0] = rndBytes[0] & (2 ** bitLengthMod8 - 1)
}
if (forceLength) {
const mask = (bitLengthMod8 !== 0) ? 2 ** (bitLengthMod8 - 1) : 128
rndBytes[0] = rndBytes[0] | mask
}
resolve(rndBytes)
})
})
}
/**
* Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
* @param bitLength - The desired number of random bits
* @param forceLength - If we want to force the output to have a specific bit length. It basically forces the msb to be 1
*
* @throws {RangeError}
* bitLength MUST be > 0
*
* @returns A Uint8Array/Buffer (Browser/Node.js) filled with cryptographically secure random bits
*/
export function randBitsSync (bitLength: number, forceLength: boolean = false): Uint8Array|Buffer {
if (bitLength < 1) throw new RangeError('bitLength MUST be > 0')
const byteLength = Math.ceil(bitLength / 8)
const rndBytes = randBytesSync(byteLength, false)
const bitLengthMod8 = bitLength % 8
if (bitLengthMod8 !== 0) {
// Fill with 0's the extra bits
rndBytes[0] = rndBytes[0] & (2 ** bitLengthMod8 - 1)
}
if (forceLength) {
const mask = (bitLengthMod8 !== 0) ? 2 ** (bitLengthMod8 - 1) : 128
rndBytes[0] = rndBytes[0] | mask
}
return rndBytes
}

64
src/ts/randBytes.ts Normal file
View File

@ -0,0 +1,64 @@
/**
* Secure random bytes for both node and browsers. Node version uses crypto.randomBytes() and browser one self.crypto.getRandomValues()
*
* @param byteLength - The desired number of random bytes
* @param forceLength - If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
*
* @throws {RangeError}
* byteLength MUST be > 0
*
* @returns A promise that resolves to a UInt8Array/Buffer (Browser/Node.js) filled with cryptographically secure random bytes
*/
export function randBytes (byteLength: number, forceLength = false): Promise<Uint8Array|Buffer> { // eslint-disable-line
if (byteLength < 1) throw new RangeError('byteLength MUST be > 0')
return new Promise(function (resolve, reject) {
if (!IS_BROWSER) {
const crypto = require('crypto') // eslint-disable-line
crypto.randomBytes(byteLength, function (err: Error, buf: Buffer) {
/* istanbul ignore if */
if (err !== null) reject(err)
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if (forceLength) buf[0] = buf[0] | 128
resolve(buf)
})
} else { // browser
const buf = new Uint8Array(byteLength)
self.crypto.getRandomValues(buf)
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if (forceLength) buf[0] = buf[0] | 128
resolve(buf)
}
})
}
/**
* Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
*
* @param byteLength - The desired number of random bytes
* @param forceLength - If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
*
* @throws {RangeError}
* byteLength MUST be > 0
*
* @returns A UInt8Array/Buffer (Browser/Node.js) filled with cryptographically secure random bytes
*/
export function randBytesSync (byteLength: number, forceLength: boolean = false): Uint8Array|Buffer {
if (byteLength < 1) throw new RangeError('byteLength MUST be > 0')
/* eslint-disable no-lone-blocks */
if (!IS_BROWSER) { // node
const crypto = require('crypto') // eslint-disable-line
const buf = crypto.randomBytes(byteLength)
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if (forceLength) buf[0] = buf[0] | 128
return buf
} else { // browser
const buf = new Uint8Array(byteLength)
self.crypto.getRandomValues(buf)
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if (forceLength) buf[0] = buf[0] | 128
return buf
}
/* eslint-enable no-lone-blocks */
}

36
src/ts/workerUtils.ts Normal file
View File

@ -0,0 +1,36 @@
export function _workerUrl (workerCode: string): string {
workerCode = `(() => {${workerCode}})()` // encapsulate IIFE
const _blob = new Blob([workerCode], { type: 'text/javascript' })
return window.URL.createObjectURL(_blob)
}
let _useWorkers = false // The following is just to check whether we can use workers
/* eslint-disable no-lone-blocks */
if (!IS_BROWSER) { // Node.js
try {
require.resolve('worker_threads')
_useWorkers = true
} catch (e) {
/* istanbul ignore next */
console.log(`[bigint-crypto-utils] WARNING:
This node version doesn't support worker_threads. You should enable them in order to greatly speedup the generation of big prime numbers.
· With Node >=11 it is enabled by default (consider upgrading).
· With Node 10, starting with 10.5.0, you can enable worker_threads at runtime executing node --experimental-worker `)
}
} else { // Native JS
if (self.Worker !== undefined) _useWorkers = true
}
export { _useWorkers }
export interface WorkerToMainMsg {
isPrime: boolean
value: bigint
id: number
}
export interface MainToWorkerMsg {
rnd: bigint
iterations: number
id: number
}

View File

@ -1,37 +0,0 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const inputs = [
{
value: BigInt(1),
abs: BigInt(1)
},
{
value: BigInt(-2),
abs: BigInt(2)
},
{
value: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'),
abs: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'),
abs: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
}
]
describe('abs', function () {
for (const input of inputs) {
describe(`abs(${input.value})`, function () {
it(`should return ${input.abs}`, function () {
const ret = _pkg.abs(input.value)
chai.expect(ret).to.equal(input.abs)
})
})
}
})

View File

@ -1,34 +0,0 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const inputs = [
{
value: BigInt(1),
bitLength: 1
},
{
value: BigInt(-2),
bitLength: 2
},
{
value: BigInt('11592217955149597331'),
abs: BigInt('11592217955149597331'),
bitLength: 64
}
]
describe('bitLength', function () {
for (const input of inputs) {
describe(`bitLength(${input.value})`, function () {
it(`should return ${input.bitLength}`, function () {
const ret = _pkg.bitLength(input.value)
chai.expect(ret).to.equal(input.bitLength)
})
})
}
})

View File

@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>bigint-crypto-utils - Mocha Tests</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/8.2.1/mocha.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/8.2.1/mocha.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/4.2.0/chai.min.js"></script>
</head>
<body>
<div id="mocha"></div>
<script>mocha.setup('bdd'); mocha.setup({ timeout: 90000 });</script>
<script type="module">
import * as _pkg from '../../../lib/index.browser.bundle.mod.js'
window._pkg = _pkg
import './tests.js'
mocha.run()
</script>
</body>
</html>

View File

@ -1,888 +0,0 @@
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const inputs = [
{
value: BigInt(1),
abs: BigInt(1)
},
{
value: BigInt(-2),
abs: BigInt(2)
},
{
value: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'),
abs: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'),
abs: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
}
];
describe('abs', function () {
for (const input of inputs) {
describe(`abs(${input.value})`, function () {
it(`should return ${input.abs}`, function () {
const ret = _pkg.abs(input.value);
chai.expect(ret).to.equal(input.abs);
});
});
}
});
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const inputs$1 = [
{
value: BigInt(1),
bitLength: 1
},
{
value: BigInt(-2),
bitLength: 2
},
{
value: BigInt('11592217955149597331'),
abs: BigInt('11592217955149597331'),
bitLength: 64
}
];
describe('bitLength', function () {
for (const input of inputs$1) {
describe(`bitLength(${input.value})`, function () {
it(`should return ${input.bitLength}`, function () {
const ret = _pkg.bitLength(input.value);
chai.expect(ret).to.equal(input.bitLength);
});
});
}
});
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const inputs$2 = [
{
a: BigInt(1),
b: BigInt(1),
gcd: BigInt(1)
},
{
a: BigInt(0),
b: BigInt(189),
gcd: BigInt(189)
},
{
a: BigInt(189),
b: BigInt(0),
gcd: BigInt(189)
},
{
a: BigInt(0),
b: BigInt(0),
gcd: BigInt(0)
},
{
a: BigInt(1),
b: BigInt('14546149867129487614601346814'),
gcd: BigInt(1)
},
{
a: BigInt(27),
b: BigInt(18),
gcd: BigInt(9)
},
{
a: BigInt(-27),
b: BigInt(18),
gcd: BigInt(9)
},
{
a: BigInt(256),
b: BigInt(128),
gcd: BigInt(128)
},
{
a: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109'),
b: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
gcd: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109')
}
];
describe('gcd', function () {
for (const input of inputs$2) {
describe(`gcd(${input.a}, ${input.b})`, function () {
it(`should return ${input.gcd}`, function () {
const ret = _pkg.gcd(input.a, input.b);
chai.expect(ret).to.equal(input.gcd);
});
});
}
});
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const numbers = [
{
value: BigInt(1),
prime: false,
iterations: 16,
workers: false
},
{
value: BigInt(2),
prime: true,
iterations: 16,
workers: false
},
{
value: 3,
prime: true,
iterations: 16,
workers: false
},
{
value: BigInt(15),
prime: false,
iterations: 32,
workers: false
},
{
value: 29,
prime: true,
iterations: 16,
workers: false
},
{
value: BigInt('669483106578092405936560831017556154622901950048903016651289'),
prime: true,
iterations: 24,
workers: false
},
{
value: BigInt('2074722246773485207821695222107608587480996474721117292752992589912196684750549658310084416732550077'),
prime: true,
iterations: 16,
workers: false
},
{
value: BigInt('2074722246773485207821695222107608587480996474721117292752992589912196684750549658310084416732550079'),
prime: false,
iterations: 16,
workers: false
},
{
value: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'),
prime: true,
iterations: 24,
workers: true
},
{
value: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
prime: false,
iterations: 16,
workers: true
},
{
value: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'),
prime: true,
iterations: 16,
workers: true
},
{
value: BigInt('940719693126280825126763871881743336375040232953039527942717290104060740215493004508206768342926022549956464101136893240409560470269654765366248516968645294076406953865805712688760371102637642013723011744011617678651884521901163090779813242269935310225049805992299292275574585773507915278612311449919050091057023179541184986547995894821648553256021675133997240195429424258757033557367142630663053464438840832073753440939208165158795269598771598124509831433327480118038278887538430675994497384283550890544882369140852048496460551123626856255619494025370171790720106325655890348475483349150258338517508459674722099347335608814922179633411167540545786247819334838979610017735984374883325689517847175539632896026875016305529321705457954181425405794479825617747354596485074451489940385640535898876551301296003465792117006135339109817937663957519031436646579178503423889430062127572272773511424424297800355292430651838502733756881154935252456036638082486459287411002911323257940893413982671660332662880068976408321968046549017547143836993553556640198884769590214676797037397502067035957959952990027503148987727895561468097917730167320715053689862847457761993196945361244822787209076446259359976421264285658106819879849052247546957718175231'),
prime: false,
iterations: 16,
workers: true
}
];
describe('isProbablyPrime', function () {
this.timeout(90000);
for (const num of numbers) {
describe(`isProbablyPrime(${num.value}, ${num.iterations}, ${!num.workers})`, function () {
it(`should return ${num.prime}`, async function () {
let ret;
if (num.iterations === 16 && num.workers) ret = await _pkg.isProbablyPrime(num.value);
else ret = await _pkg.isProbablyPrime(num.value, num.iterations, !num.workers);
chai.expect(ret).to.equal(num.prime);
});
});
}
describe('isProbablyPrime(-1)', function () {
it('should throw RangeError', function () {
chai.expect(() => _pkg.isProbablyPrime(-1)).to.throw(RangeError);
});
});
});
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const inputs$3 = [
{
a: BigInt(0),
b: BigInt(0),
lcm: BigInt(0)
},
{
a: BigInt(1),
b: BigInt(1),
lcm: BigInt(1)
},
{
a: BigInt(1),
b: BigInt('14546149867129487614601346814'),
lcm: BigInt('14546149867129487614601346814')
},
{
a: BigInt(27),
b: BigInt(18),
lcm: BigInt(27) * BigInt(2)
},
{
a: BigInt(-27),
b: BigInt(18),
lcm: BigInt(27) * BigInt(2)
},
{
a: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109'),
b: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
lcm: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243')
}
];
describe('lcm', function () {
for (const input of inputs$3) {
describe(`lcm(${input.a}, ${input.b})`, function () {
it(`should return ${input.lcm}`, function () {
const ret = _pkg.lcm(input.a, input.b);
chai.expect(ret).to.equal(input.lcm);
});
});
}
});
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const inputs$4 = [
{
value: [BigInt(1), BigInt(2)],
max: BigInt(2)
},
{
value: [BigInt(2), BigInt(1)],
max: BigInt(2)
},
{
value: [BigInt(2), BigInt(2)],
max: BigInt(2)
},
{
value: [BigInt(1), BigInt(-2)],
max: BigInt(1)
},
{
value: [BigInt(-2), BigInt(1)],
max: BigInt(1)
},
{
value: [BigInt(-2), BigInt(-2)],
max: BigInt(-2)
},
{
value: [BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252'), BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
max: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')
},
{
value: [BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')],
max: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')
},
{
value: [BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
max: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252'), BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
max: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')],
max: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('-115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('-115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
max: BigInt('-115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('94120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
max: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145974144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
max: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
max: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('94120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
max: BigInt('94120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145974144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
max: BigInt('918145974144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
max: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
}
];
describe('max', function () {
for (const input of inputs$4) {
describe(`max(${input.value[0]}, ${input.value[1]})`, function () {
it(`should return ${input.max}`, function () {
const ret = _pkg.max(input.value[0], input.value[1]);
chai.expect(ret).to.equal(input.max);
});
});
}
});
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const inputs$5 = [
{
value: [BigInt(1), BigInt(2)],
min: BigInt(1)
},
{
value: [BigInt(2), BigInt(1)],
min: BigInt(1)
},
{
value: [BigInt(2), BigInt(2)],
min: BigInt(2)
},
{
value: [BigInt(1), BigInt(-2)],
min: BigInt(-2)
},
{
value: [BigInt(-2), BigInt(1)],
min: BigInt(-2)
},
{
value: [BigInt(-2), BigInt(-2)],
min: BigInt(-2)
},
{
value: [BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252'), BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
min: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')],
min: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
min: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252'), BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
min: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')
},
{
value: [BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')],
min: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')
},
{
value: [BigInt('-115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('-115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
min: BigInt('-115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('94120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
min: BigInt('94120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145974144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
min: BigInt('918145974144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
min: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('94120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
min: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145974144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
min: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
min: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
}
];
describe('min', function () {
for (const input of inputs$5) {
describe(`min(${input.value[0]}, ${input.value[1]})`, function () {
it(`should return ${input.min}`, function () {
const ret = _pkg.min(input.value[0], input.value[1]);
chai.expect(ret).to.equal(input.min);
});
});
}
});
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const inputs$6 = [
{
a: BigInt(1),
n: BigInt(19),
modInv: BigInt(1)
},
{
a: BigInt(2),
n: BigInt(5),
modInv: BigInt(3)
},
{
a: BigInt(-2),
n: BigInt(5),
modInv: BigInt(2)
}];
const invalidInputs = [
{
a: BigInt(2),
n: BigInt(4)
},
{
a: BigInt(0),
n: BigInt(0)
},
{
a: BigInt(0),
n: BigInt(37)
}
];
describe('modInv', function () {
for (const input of inputs$6) {
describe(`modInv(${input.a}, ${input.n})`, function () {
it(`should return ${input.modInv}`, function () {
const ret = _pkg.modInv(input.a, input.n);
// chai.assert( String(ret) === String(input.modInv) );
chai.expect(String(ret)).to.be.equal(String(input.modInv));
});
});
}
for (const input of invalidInputs) {
describe(`modInv(${input.a}, ${input.n})`, function () {
it('should throw RangeError', function () {
try {
_pkg.modInv(input.a, input.n);
throw new Error('should have failed')
} catch (err) {
chai.expect(err).to.be.instanceOf(RangeError);
}
});
});
}
});
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const inputs$7 = [
{
a: BigInt(4),
b: BigInt(-1),
n: BigInt(1),
modPow: BigInt(0)
},
{
a: BigInt(4),
b: BigInt(-1),
n: BigInt(19),
modPow: BigInt(5)
},
{
a: BigInt(-5),
b: BigInt(2),
n: BigInt(7),
modPow: BigInt(4)
},
{
a: BigInt(2),
b: BigInt(255),
n: BigInt(64),
modPow: BigInt(0)
},
{
a: BigInt(3),
b: BigInt(3),
n: BigInt(25),
modPow: BigInt(2)
}];
const invalidInputs$1 = [
{
a: BigInt(4),
b: BigInt(-1),
n: BigInt(0)
}
];
describe('modPow', function () {
this.timeout(90000);
for (const input of inputs$7) {
describe(`modPow(${input.a}, ${input.b}, ${input.n})`, function () {
it(`should return ${input.modPow}`, function () {
const ret = _pkg.modPow(input.a, input.b, input.n);
chai.expect(String(ret)).to.equal(String(input.modPow));
});
});
}
for (const input of invalidInputs$1) {
describe(`modPow(${input.a}, ${input.b}, ${input.n})`, function () {
it('should throw RangeError', function () {
try {
_pkg.modPow(input.a, input.b, input.n);
throw new Error('should have failed')
} catch (err) {
chai.expect(err).to.be.instanceOf(RangeError);
}
});
});
}
describe('Time profiling', function () {
let iterations = 500;
it(`just testing ${iterations} iterations of a big modular exponentiation (1024 bits)`, function () {
const p = BigInt('103920301461718841589267304263845359224454055603847417021399996422142529929535423886894599506329362009085557636432288745748144369296043048325513558512136442971686130986388589421125262751724362880217790112013162815676017250234401214198365302142787009943498370856167174244675719638815809347261773472114842038647');
const b = BigInt('313632271690673451924314047671460131678794095260951233878123501752357966284491455239133687519908410656818506813151659324961829045286402303082891913186909806785080978448037486178337722667190743610785429936585699831407575170854873682955317589189564880931807976657385223632835801016017549762825562427694700595');
const e = BigInt('452149997592306202232720864363485824701879487303880767747217308770351197801836846325633986474037061753983278534192061455638289551714281047915315943771002615269860312318606105460307037327329178890486613832051027105330475852552183444938408408863970975090778239473049899109989825645608770309107015209564444316');
while (iterations > 0) {
_pkg.modPow(b, e, p);
iterations--;
}
});
});
});
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const bitLengths = [
0,
8,
255,
256,
258,
512,
1024,
2048,
3072
];
describe('Testing prime generation', function () {
this.timeout(120000);
for (const bitLength of bitLengths) {
describe(`prime(${bitLength})`, function () {
if (bitLength > 0) {
it(`should return a random ${bitLength}-bits probable prime`, async function () {
const prime = await _pkg.prime(bitLength);
chai.expect(_pkg.bitLength(prime)).to.equal(bitLength);
});
} else {
it('should throw error', async function () {
chai.expect(() => _pkg.prime(bitLength)).to.throw(RangeError);
});
}
});
}
describe('Testing sync (NOT-RECOMMENDED) version: primeSync()', function () {
it('should return a random 1024-bits probable prime', function () {
const prime = _pkg.primeSync(1024, 16);
chai.expect(_pkg.bitLength(prime)).to.equal(1024);
chai.expect(() => _pkg.primeSync(0)).to.throw(RangeError);
});
});
});
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const numbers$1 = [
{
min: BigInt(1),
max: BigInt(2) ** BigInt(234),
iterations: 100,
error: false,
errorMax: false
},
{
min: BigInt('122461641436345153'),
max: BigInt(2) ** BigInt(234),
iterations: 100,
error: false,
errorMax: false
},
{
min: BigInt(146347),
max: BigInt(2),
iterations: 1,
error: true,
errorMax: false
},
{
min: BigInt(2),
max: BigInt(2),
iterations: 1,
error: true,
errorMax: false
},
{
min: BigInt(-4),
max: BigInt(2),
iterations: 1,
error: true,
errorMax: false
},
{
min: BigInt(1),
max: BigInt(-1),
iterations: 1,
error: true,
errorMax: true
}
];
describe('randBetween', function () {
this.timeout(90000);
for (const num of numbers$1) {
describe(`randBetween(${num.max}, ${num.min})`, function () {
if (!num.error) {
it(`[${num.iterations} iterations] should return x such that min < x < max`, function () {
let ret = true;
for (let i = 0; i < num.iterations; i++) {
const x = _pkg.randBetween(num.max, num.min);
ret = ret && x > num.min && x < num.max;
}
chai.expect(ret).to.equal(true);
});
} else {
it('should throw RangeError (max <=0 || min <0 || min>=max)', function () {
chai.expect(() => _pkg.randBetween(num.max, num.min)).to.throw(RangeError);
});
}
});
describe(`randBetween(${num.max})`, function () {
if (!num.errorMax) {
it(`[${num.iterations} iterations] should return x such that 1 <= x <= max`, function () {
let ret = true;
for (let i = 0; i < num.iterations; i++) {
const x = _pkg.randBetween(num.max);
ret = ret && x >= BigInt(1) && x <= num.max;
}
chai.expect(ret).to.equal(true);
});
} else {
it('should throw RangeError (max <=0)', function () {
chai.expect(() => _pkg.randBetween(num.max)).to.throw(RangeError);
});
}
});
}
});
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const iterations = 10;
const bitLengths$1 = [-1, 0, 3, 8, 16, 511, 2048];
const byteLengths = [-7, 0, 1, 8, 33, 40];
describe('testing randBits', async function () {
for (const bitLength of bitLengths$1) {
describe(`${iterations} iterations of randBitsSync(${bitLength})`, function () {
if (bitLength > 0) {
it('should return buffers', function () {
let ret = true;
for (let i = 0; i < iterations; i++) {
const randbits = _pkg.randBitsSync(bitLength);
// console.log(JSON.stringify(randbits))
const randbits2 = _pkg.randBitsSync(bitLength, true);
// console.log(JSON.stringify(randbits2))
if (!(((randbits instanceof Uint8Array) && (randbits2 instanceof Uint8Array)) ||
((randbits instanceof Buffer) && (randbits2 instanceof Buffer)))) {
ret = false;
break
}
}
chai.expect(ret).to.equal(true);
});
} else {
it('should throw RangeError', function () {
chai.expect(() => _pkg.randBitsSync(bitLength)).to.throw(RangeError);
});
}
});
describe(`${iterations} iterations of randBits(${bitLength})`, async function () {
if (bitLength > 0) {
it('should return buffers', async function () {
let ret = true;
for (let i = 0; i < iterations; i++) {
const randbits = await _pkg.randBits(bitLength);
// console.log(JSON.stringify(randbits))
const randbits2 = await _pkg.randBits(bitLength, true);
// console.log(JSON.stringify(randbits2))
if (!(((randbits instanceof Uint8Array) && (randbits2 instanceof Uint8Array)) ||
((randbits instanceof Buffer) && (randbits2 instanceof Buffer)))) {
ret = false;
break
}
}
chai.expect(ret).to.equal(true);
});
} else {
it('should throw RangeError', function () {
chai.expect(() => _pkg.randBits(bitLength)).to.throw(RangeError);
});
}
});
}
});
describe('testing randBytes', async function () {
for (const byteLength of byteLengths) {
describe(`${iterations} iterations of randBytesSync(${byteLength})`, function () {
if (byteLength > 0) {
it('should return buffers', function () {
let ret = true;
for (let i = 0; i < iterations; i++) {
const randbytes = _pkg.randBytesSync(byteLength);
// console.log(JSON.stringify(randbits))
const randbytes2 = _pkg.randBytesSync(byteLength, true);
// console.log(JSON.stringify(randbits2))
if (!(((randbytes instanceof Uint8Array) && (randbytes2 instanceof Uint8Array)) ||
((randbytes instanceof Buffer) && (randbytes2 instanceof Buffer)))) {
ret = false;
}
}
chai.expect(ret).to.equal(true);
});
} else {
it('should throw RangeError', function () {
chai.expect(() => _pkg.randBytesSync(byteLength)).to.throw(RangeError);
});
}
});
describe(`${iterations} iterations of randBytes(${byteLength})`, async function () {
if (byteLength > 0) {
it('should return buffers', async function () {
let ret = true;
for (let i = 0; i < iterations; i++) {
const randbytes = await _pkg.randBytes(byteLength);
// console.log(JSON.stringify(randbits))
const randbytes2 = await _pkg.randBytes(byteLength, true);
// console.log(JSON.stringify(randbits2))
if (!(((randbytes instanceof Uint8Array) && (randbytes2 instanceof Uint8Array)) ||
((randbytes instanceof Buffer) && (randbytes2 instanceof Buffer)))) {
ret = false;
}
}
chai.expect(ret).to.equal(true);
});
} else {
it('should throw RangeError', function () {
chai.expect(() => _pkg.randBytes(byteLength)).to.throw(RangeError);
});
}
});
}
});
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
// <--
const inputs$8 = [
{
a: BigInt(1),
n: BigInt(19),
toZn: BigInt(1)
},
{
a: BigInt(-25),
n: BigInt(9),
toZn: BigInt(2)
},
{
a: BigInt('12359782465012847510249'),
n: BigInt(5),
toZn: BigInt(4)
}
];
describe('toZn', function () {
for (const input of inputs$8) {
describe(`toZn(${input.a}, ${input.n})`, function () {
it(`should return ${input.toZn}`, function () {
const ret = _pkg.toZn(input.a, input.n);
chai.expect(ret).to.equal(input.toZn);
});
});
}
});

View File

@ -1,66 +0,0 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const inputs = [
{
a: BigInt(1),
b: BigInt(1),
gcd: BigInt(1)
},
{
a: BigInt(0),
b: BigInt(189),
gcd: BigInt(189)
},
{
a: BigInt(189),
b: BigInt(0),
gcd: BigInt(189)
},
{
a: BigInt(0),
b: BigInt(0),
gcd: BigInt(0)
},
{
a: BigInt(1),
b: BigInt('14546149867129487614601346814'),
gcd: BigInt(1)
},
{
a: BigInt(27),
b: BigInt(18),
gcd: BigInt(9)
},
{
a: BigInt(-27),
b: BigInt(18),
gcd: BigInt(9)
},
{
a: BigInt(256),
b: BigInt(128),
gcd: BigInt(128)
},
{
a: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109'),
b: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
gcd: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109')
}
]
describe('gcd', function () {
for (const input of inputs) {
describe(`gcd(${input.a}, ${input.b})`, function () {
it(`should return ${input.gcd}`, function () {
const ret = _pkg.gcd(input.a, input.b)
chai.expect(ret).to.equal(input.gcd)
})
})
}
})

View File

@ -1,101 +0,0 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const numbers = [
{
value: BigInt(1),
prime: false,
iterations: 16,
workers: false
},
{
value: BigInt(2),
prime: true,
iterations: 16,
workers: false
},
{
value: 3,
prime: true,
iterations: 16,
workers: false
},
{
value: BigInt(15),
prime: false,
iterations: 32,
workers: false
},
{
value: 29,
prime: true,
iterations: 16,
workers: false
},
{
value: BigInt('669483106578092405936560831017556154622901950048903016651289'),
prime: true,
iterations: 24,
workers: false
},
{
value: BigInt('2074722246773485207821695222107608587480996474721117292752992589912196684750549658310084416732550077'),
prime: true,
iterations: 16,
workers: false
},
{
value: BigInt('2074722246773485207821695222107608587480996474721117292752992589912196684750549658310084416732550079'),
prime: false,
iterations: 16,
workers: false
},
{
value: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'),
prime: true,
iterations: 24,
workers: true
},
{
value: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
prime: false,
iterations: 16,
workers: true
},
{
value: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'),
prime: true,
iterations: 16,
workers: true
},
{
value: BigInt('940719693126280825126763871881743336375040232953039527942717290104060740215493004508206768342926022549956464101136893240409560470269654765366248516968645294076406953865805712688760371102637642013723011744011617678651884521901163090779813242269935310225049805992299292275574585773507915278612311449919050091057023179541184986547995894821648553256021675133997240195429424258757033557367142630663053464438840832073753440939208165158795269598771598124509831433327480118038278887538430675994497384283550890544882369140852048496460551123626856255619494025370171790720106325655890348475483349150258338517508459674722099347335608814922179633411167540545786247819334838979610017735984374883325689517847175539632896026875016305529321705457954181425405794479825617747354596485074451489940385640535898876551301296003465792117006135339109817937663957519031436646579178503423889430062127572272773511424424297800355292430651838502733756881154935252456036638082486459287411002911323257940893413982671660332662880068976408321968046549017547143836993553556640198884769590214676797037397502067035957959952990027503148987727895561468097917730167320715053689862847457761993196945361244822787209076446259359976421264285658106819879849052247546957718175231'),
prime: false,
iterations: 16,
workers: true
}
]
describe('isProbablyPrime', function () {
this.timeout(90000)
for (const num of numbers) {
describe(`isProbablyPrime(${num.value}, ${num.iterations}, ${!num.workers})`, function () {
it(`should return ${num.prime}`, async function () {
let ret
if (num.iterations === 16 && num.workers) ret = await _pkg.isProbablyPrime(num.value)
else ret = await _pkg.isProbablyPrime(num.value, num.iterations, !num.workers)
chai.expect(ret).to.equal(num.prime)
})
})
}
describe('isProbablyPrime(-1)', function () {
it('should throw RangeError', function () {
chai.expect(() => _pkg.isProbablyPrime(-1)).to.throw(RangeError)
})
})
})

93
test/isProbablyPrime.ts Normal file
View File

@ -0,0 +1,93 @@
describe('isProbablyPrime', function () {
this.timeout(90000)
const numbers = [
{
value: BigInt(1),
prime: false,
iterations: 16,
workers: false
},
{
value: BigInt(2),
prime: true,
iterations: 16,
workers: false
},
{
value: 3,
prime: true,
iterations: 16,
workers: false
},
{
value: BigInt(15),
prime: false,
iterations: 32,
workers: false
},
{
value: 29,
prime: true,
iterations: 16,
workers: false
},
{
value: BigInt('669483106578092405936560831017556154622901950048903016651289'),
prime: true,
iterations: 24,
workers: false
},
{
value: BigInt('2074722246773485207821695222107608587480996474721117292752992589912196684750549658310084416732550077'),
prime: true,
iterations: 16,
workers: false
},
{
value: BigInt('2074722246773485207821695222107608587480996474721117292752992589912196684750549658310084416732550079'),
prime: false,
iterations: 16,
workers: false
},
{
value: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'),
prime: true,
iterations: 24,
workers: true
},
{
value: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
prime: false,
iterations: 16,
workers: true
},
{
value: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'),
prime: true,
iterations: 16,
workers: true
},
{
value: BigInt('940719693126280825126763871881743336375040232953039527942717290104060740215493004508206768342926022549956464101136893240409560470269654765366248516968645294076406953865805712688760371102637642013723011744011617678651884521901163090779813242269935310225049805992299292275574585773507915278612311449919050091057023179541184986547995894821648553256021675133997240195429424258757033557367142630663053464438840832073753440939208165158795269598771598124509831433327480118038278887538430675994497384283550890544882369140852048496460551123626856255619494025370171790720106325655890348475483349150258338517508459674722099347335608814922179633411167540545786247819334838979610017735984374883325689517847175539632896026875016305529321705457954181425405794479825617747354596485074451489940385640535898876551301296003465792117006135339109817937663957519031436646579178503423889430062127572272773511424424297800355292430651838502733756881154935252456036638082486459287411002911323257940893413982671660332662880068976408321968046549017547143836993553556640198884769590214676797037397502067035957959952990027503148987727895561468097917730167320715053689862847457761993196945361244822787209076446259359976421264285658106819879849052247546957718175231'),
prime: false,
iterations: 16,
workers: true
}
]
for (const num of numbers) {
describe(`isProbablyPrime(${num.value}, ${num.iterations}, ${String(!num.workers)})`, function () {
it(`should return ${String(num.prime)}`, async function () {
let ret
if (num.iterations === 16 && num.workers) ret = await _pkg.isProbablyPrime(num.value)
else ret = await _pkg.isProbablyPrime(num.value, num.iterations, !num.workers)
chai.expect(ret).to.equal(num.prime)
})
})
}
describe('isProbablyPrime(-1)', function () {
it('should throw RangeError', function () {
chai.expect(() => _pkg.isProbablyPrime(-1)).to.throw(RangeError) // eslint-disable-line
})
})
})

View File

@ -1,51 +0,0 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const inputs = [
{
a: BigInt(0),
b: BigInt(0),
lcm: BigInt(0)
},
{
a: BigInt(1),
b: BigInt(1),
lcm: BigInt(1)
},
{
a: BigInt(1),
b: BigInt('14546149867129487614601346814'),
lcm: BigInt('14546149867129487614601346814')
},
{
a: BigInt(27),
b: BigInt(18),
lcm: BigInt(27) * BigInt(2)
},
{
a: BigInt(-27),
b: BigInt(18),
lcm: BigInt(27) * BigInt(2)
},
{
a: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109'),
b: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
lcm: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243')
}
]
describe('lcm', function () {
for (const input of inputs) {
describe(`lcm(${input.a}, ${input.b})`, function () {
it(`should return ${input.lcm}`, function () {
const ret = _pkg.lcm(input.a, input.b)
chai.expect(ret).to.equal(input.lcm)
})
})
}
})

View File

@ -1,93 +0,0 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const inputs = [
{
value: [BigInt(1), BigInt(2)],
max: BigInt(2)
},
{
value: [BigInt(2), BigInt(1)],
max: BigInt(2)
},
{
value: [BigInt(2), BigInt(2)],
max: BigInt(2)
},
{
value: [BigInt(1), BigInt(-2)],
max: BigInt(1)
},
{
value: [BigInt(-2), BigInt(1)],
max: BigInt(1)
},
{
value: [BigInt(-2), BigInt(-2)],
max: BigInt(-2)
},
{
value: [BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252'), BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
max: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')
},
{
value: [BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')],
max: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')
},
{
value: [BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
max: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252'), BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
max: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')],
max: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('-115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('-115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
max: BigInt('-115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('94120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
max: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145974144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
max: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
max: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('94120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
max: BigInt('94120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145974144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
max: BigInt('918145974144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
max: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
}
]
describe('max', function () {
for (const input of inputs) {
describe(`max(${input.value[0]}, ${input.value[1]})`, function () {
it(`should return ${input.max}`, function () {
const ret = _pkg.max(input.value[0], input.value[1])
chai.expect(ret).to.equal(input.max)
})
})
}
})

View File

@ -1,93 +0,0 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const inputs = [
{
value: [BigInt(1), BigInt(2)],
min: BigInt(1)
},
{
value: [BigInt(2), BigInt(1)],
min: BigInt(1)
},
{
value: [BigInt(2), BigInt(2)],
min: BigInt(2)
},
{
value: [BigInt(1), BigInt(-2)],
min: BigInt(-2)
},
{
value: [BigInt(-2), BigInt(1)],
min: BigInt(-2)
},
{
value: [BigInt(-2), BigInt(-2)],
min: BigInt(-2)
},
{
value: [BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252'), BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
min: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')],
min: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
min: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252'), BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
min: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')
},
{
value: [BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')],
min: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252')
},
{
value: [BigInt('-115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'), BigInt('-115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')],
min: BigInt('-115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
},
{
value: [BigInt('94120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
min: BigInt('94120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145974144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
min: BigInt('918145974144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
min: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('94120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
min: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('918145974144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
min: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
},
{
value: [BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'), BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')],
min: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
}
]
describe('min', function () {
for (const input of inputs) {
describe(`min(${input.value[0]}, ${input.value[1]})`, function () {
it(`should return ${input.min}`, function () {
const ret = _pkg.min(input.value[0], input.value[1])
chai.expect(ret).to.equal(input.min)
})
})
}
})

View File

@ -1,63 +0,0 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const inputs = [
{
a: BigInt(1),
n: BigInt(19),
modInv: BigInt(1)
},
{
a: BigInt(2),
n: BigInt(5),
modInv: BigInt(3)
},
{
a: BigInt(-2),
n: BigInt(5),
modInv: BigInt(2)
}]
const invalidInputs = [
{
a: BigInt(2),
n: BigInt(4)
},
{
a: BigInt(0),
n: BigInt(0)
},
{
a: BigInt(0),
n: BigInt(37)
}
]
describe('modInv', function () {
for (const input of inputs) {
describe(`modInv(${input.a}, ${input.n})`, function () {
it(`should return ${input.modInv}`, function () {
const ret = _pkg.modInv(input.a, input.n)
// chai.assert( String(ret) === String(input.modInv) );
chai.expect(String(ret)).to.be.equal(String(input.modInv))
})
})
}
for (const input of invalidInputs) {
describe(`modInv(${input.a}, ${input.n})`, function () {
it('should throw RangeError', function () {
try {
_pkg.modInv(input.a, input.n)
throw new Error('should have failed')
} catch (err) {
chai.expect(err).to.be.instanceOf(RangeError)
}
})
})
}
})

View File

@ -1,83 +0,0 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const inputs = [
{
a: BigInt(4),
b: BigInt(-1),
n: BigInt(1),
modPow: BigInt(0)
},
{
a: BigInt(4),
b: BigInt(-1),
n: BigInt(19),
modPow: BigInt(5)
},
{
a: BigInt(-5),
b: BigInt(2),
n: BigInt(7),
modPow: BigInt(4)
},
{
a: BigInt(2),
b: BigInt(255),
n: BigInt(64),
modPow: BigInt(0)
},
{
a: BigInt(3),
b: BigInt(3),
n: BigInt(25),
modPow: BigInt(2)
}]
const invalidInputs = [
{
a: BigInt(4),
b: BigInt(-1),
n: BigInt(0)
}
]
describe('modPow', function () {
this.timeout(90000)
for (const input of inputs) {
describe(`modPow(${input.a}, ${input.b}, ${input.n})`, function () {
it(`should return ${input.modPow}`, function () {
const ret = _pkg.modPow(input.a, input.b, input.n)
chai.expect(String(ret)).to.equal(String(input.modPow))
})
})
}
for (const input of invalidInputs) {
describe(`modPow(${input.a}, ${input.b}, ${input.n})`, function () {
it('should throw RangeError', function () {
try {
_pkg.modPow(input.a, input.b, input.n)
throw new Error('should have failed')
} catch (err) {
chai.expect(err).to.be.instanceOf(RangeError)
}
})
})
}
describe('Time profiling', function () {
let iterations = 500
it(`just testing ${iterations} iterations of a big modular exponentiation (1024 bits)`, function () {
const p = BigInt('103920301461718841589267304263845359224454055603847417021399996422142529929535423886894599506329362009085557636432288745748144369296043048325513558512136442971686130986388589421125262751724362880217790112013162815676017250234401214198365302142787009943498370856167174244675719638815809347261773472114842038647')
const b = BigInt('313632271690673451924314047671460131678794095260951233878123501752357966284491455239133687519908410656818506813151659324961829045286402303082891913186909806785080978448037486178337722667190743610785429936585699831407575170854873682955317589189564880931807976657385223632835801016017549762825562427694700595')
const e = BigInt('452149997592306202232720864363485824701879487303880767747217308770351197801836846325633986474037061753983278534192061455638289551714281047915315943771002615269860312318606105460307037327329178890486613832051027105330475852552183444938408408863970975090778239473049899109989825645608770309107015209564444316')
while (iterations > 0) {
_pkg.modPow(b, e, p)
iterations--
}
})
})
})

View File

@ -1,24 +1,15 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const bitLengths = [
0,
8,
255,
256,
258,
512,
1024,
2048,
3072
]
describe('Testing prime generation', function () {
const bitLengths = [
0,
8,
255,
256,
258,
512,
1024,
2048,
3072
]
this.timeout(120000)
for (const bitLength of bitLengths) {
describe(`prime(${bitLength})`, function () {
@ -28,8 +19,8 @@ describe('Testing prime generation', function () {
chai.expect(_pkg.bitLength(prime)).to.equal(bitLength)
})
} else {
it('should throw error', async function () {
chai.expect(() => _pkg.prime(bitLength)).to.throw(RangeError)
it('should throw error', function () {
chai.expect(() => _pkg.prime(bitLength)).to.throw(RangeError) // eslint-disable-line
})
}
})

View File

@ -1,57 +1,48 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const numbers = [
{
min: BigInt(1),
max: BigInt(2) ** BigInt(234),
iterations: 100,
error: false,
errorMax: false
},
{
min: BigInt('122461641436345153'),
max: BigInt(2) ** BigInt(234),
iterations: 100,
error: false,
errorMax: false
},
{
min: BigInt(146347),
max: BigInt(2),
iterations: 1,
error: true,
errorMax: false
},
{
min: BigInt(2),
max: BigInt(2),
iterations: 1,
error: true,
errorMax: false
},
{
min: BigInt(-4),
max: BigInt(2),
iterations: 1,
error: true,
errorMax: false
},
{
min: BigInt(1),
max: BigInt(-1),
iterations: 1,
error: true,
errorMax: true
}
]
describe('randBetween', function () {
const numbers = [
{
min: BigInt(1),
max: BigInt(2) ** BigInt(234),
iterations: 100,
error: false,
errorMax: false
},
{
min: BigInt('122461641436345153'),
max: BigInt(2) ** BigInt(234),
iterations: 100,
error: false,
errorMax: false
},
{
min: BigInt(146347),
max: BigInt(2),
iterations: 1,
error: true,
errorMax: false
},
{
min: BigInt(2),
max: BigInt(2),
iterations: 1,
error: true,
errorMax: false
},
{
min: BigInt(-4),
max: BigInt(2),
iterations: 1,
error: true,
errorMax: false
},
{
min: BigInt(1),
max: BigInt(-1),
iterations: 1,
error: true,
errorMax: true
}
]
this.timeout(90000)
for (const num of numbers) {
describe(`randBetween(${num.max}, ${num.min})`, function () {

View File

@ -1,16 +1,8 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const iterations = 10
const bitLengths = [-1, 0, 3, 8, 16, 511, 2048]
const byteLengths = [-7, 0, 1, 8, 33, 40]
describe('testing randBits', async function () {
describe('testing randBits', function () {
for (const bitLength of bitLengths) {
describe(`${iterations} iterations of randBitsSync(${bitLength})`, function () {
if (bitLength > 0) {
@ -35,7 +27,7 @@ describe('testing randBits', async function () {
})
}
})
describe(`${iterations} iterations of randBits(${bitLength})`, async function () {
describe(`${iterations} iterations of randBits(${bitLength})`, function () {
if (bitLength > 0) {
it('should return buffers', async function () {
let ret = true
@ -54,14 +46,14 @@ describe('testing randBits', async function () {
})
} else {
it('should throw RangeError', function () {
chai.expect(() => _pkg.randBits(bitLength)).to.throw(RangeError)
chai.expect(() => _pkg.randBits(bitLength)).to.throw(RangeError) // eslint-disable-line
})
}
})
}
})
describe('testing randBytes', async function () {
describe('testing randBytes', function () {
for (const byteLength of byteLengths) {
describe(`${iterations} iterations of randBytesSync(${byteLength})`, function () {
if (byteLength > 0) {
@ -85,7 +77,7 @@ describe('testing randBytes', async function () {
})
}
})
describe(`${iterations} iterations of randBytes(${byteLength})`, async function () {
describe(`${iterations} iterations of randBytes(${byteLength})`, function () {
if (byteLength > 0) {
it('should return buffers', async function () {
let ret = true
@ -103,7 +95,7 @@ describe('testing randBytes', async function () {
})
} else {
it('should throw RangeError', function () {
chai.expect(() => _pkg.randBytes(byteLength)).to.throw(RangeError)
chai.expect(() => _pkg.randBytes(byteLength)).to.throw(RangeError) // eslint-disable-line
})
}
})

View File

@ -1,36 +0,0 @@
'use strict'
// Every test file (you can create as many as you want) should start like this
// Please, do NOT touch. They will be automatically removed for browser tests -->
const _pkg = require('../lib/index.node')
const chai = require('chai')
// <--
const inputs = [
{
a: BigInt(1),
n: BigInt(19),
toZn: BigInt(1)
},
{
a: BigInt(-25),
n: BigInt(9),
toZn: BigInt(2)
},
{
a: BigInt('12359782465012847510249'),
n: BigInt(5),
toZn: BigInt(4)
}
]
describe('toZn', function () {
for (const input of inputs) {
describe(`toZn(${input.a}, ${input.n})`, function () {
it(`should return ${input.toZn}`, function () {
const ret = _pkg.toZn(input.a, input.n)
chai.expect(ret).to.equal(input.toZn)
})
})
}
})

39
tsconfig.json Normal file
View File

@ -0,0 +1,39 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"target": "es2020", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"lib": [ "es2020", "DOM" , "WebWorker"], /* Specify library files to be included in the compilation. */
"allowJs": true, /* Allow javascript files to be compiled. */
"checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'react', 'react-jsx', 'react-jsxdev', 'preserve' or 'react-native'. */
"strict": true, /* Enable all strict type-checking options. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
/* Module Resolution Options */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
"typeRoots": [ "./build/typings", "./node_modules/@types" ], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"include": ["src/**/*", "build/typings/**/*", "test/**/*"]
}

198
types/index.d.ts vendored
View File

@ -1,198 +0,0 @@
/**
* 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
*
* @throws {RangeError} a and b MUST be > 0
*
* @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
* iterations of Miller-Rabin Probabilistic Primality Test (FIPS 186-4 C.3.1)
*
* @param {number | bigint} w A positive 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 {boolean} [disableWorkers = false] Disable the use of workers for the primality test
*
* @throws {RangeError} w MUST be >= 0
*
* @returns {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, disableWorkers?: boolean): 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
*
* @throws {RangeError} a does not have inverse modulo n
*
* @returns {bigint} the inverse modulo n
*/
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.
* 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).
*
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {Promise<bigint>} A promise that resolves to a bigint probable prime of bitLength bits.
*/
export function prime(bitLength: number, iterations?: number): Promise<bigint>;
/**
* 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.
*
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {bigint} A bigint probable prime of bitLength bits.
*/
export function primeSync(bitLength: number, iterations?: number): bigint;
/**
* Returns a cryptographically secure random integer between [min,max]. Both numbers must be >=0
* @param {bigint} max Returned value will be <= max
* @param {bigint} [min = BigInt(1)] Returned value will be >= min
*
* @throws {RangeError} Arguments MUST be: max > 0 && min >=0 && max > min
*
* @returns {bigint} A cryptographically secure random bigint between [min,max]
*/
export function randBetween(max: bigint, min?: bigint): bigint;
/**
* Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
*
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {Promise<Buffer | Uint8Array>} A Promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
*/
export function randBits(bitLength: number, forceLength?: boolean): Promise<Buffer | Uint8Array>;
/**
* Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
* @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
*
* @throws {RangeError} bitLength MUST be > 0
*
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits
*/
export function randBitsSync(bitLength: number, forceLength?: boolean): Buffer | Uint8Array;
/**
* Secure random bytes for both node and browsers. Node version uses crypto.randomBytes() and browser one self.crypto.getRandomValues()
*
* @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
*
* @throws {RangeError} byteLength MUST be > 0
*
* @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<Buffer | Uint8Array>;
/**
* 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 {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
*
* @throws {RangeError} byteLength MUST be > 0
*
* @returns {Buffer | Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
*/
export function randBytesSync(byteLength: number, forceLength?: boolean): Buffer | Uint8Array;
/**
* 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;