Repository: justmoon/node-bignum
Branch: main
Commit: ef2e02533e59
Files: 19
Total size: 79.4 KB
Directory structure:
gitextract_0bfbdiwo/
├── .dntrc
├── .github/
│ └── workflows/
│ └── main.yml
├── .gitignore
├── .npmignore
├── README.markdown
├── appveyor.yml
├── bignum.cc
├── binding.gyp
├── examples/
│ ├── gen.js
│ ├── perfect.js
│ └── simple.js
├── index.js
├── package.json
└── test/
├── big.js
├── buf.js
├── gh52.js
├── isbignum.js
├── seed.js
└── wincrash.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .dntrc
================================================
## DNT config file
## see https://github.com/rvagg/dnt
NODE_VERSIONS="\
v0.10.40 \
v0.12.7 \
"
IOJS_VERSIONS="\
v1.8.4 \
v2.0.1 \
v2.5.0 \
v3.0.0 \
"
OUTPUT_PREFIX="bignum-"
TEST_CMD="\
cd /dnt/ && \
npm install node-gyp && \
npm install --nodedir=/usr/src/node && \
npm test; \
"
LOG_OK_CMD="sed 's/^ ..32m100...0m .. tests$/ok/' | tail -2 | head -1"
================================================
FILE: .github/workflows/main.yml
================================================
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest] # windows-latest needs openssl installed in C:\OpenSSL-Win64\
node-version: [10.x, 12.x, 13.x]
steps:
- name: Checkout
uses: actions/checkout@v1
with:
fetch-depth: 1
- name: Install and test with Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm run build --if-present
- run: npm test
env:
CI: true
================================================
FILE: .gitignore
================================================
# Files
.lock-wscript
package-lock.json
# Filetypes
.*.swp
# Paths
/build
/node_modules
/coverage
/binding
/.nyc_output
/docker
================================================
FILE: .npmignore
================================================
.lock-wscript
.travis.yml
appveyor.yml
.dntrc
.*.swp
pre-gyp-publish.sh
build
node_modules
coverage
binding
.nyc_output
test
examples
docker
================================================
FILE: README.markdown
================================================
bignum
======
[](https://github.com/justmoon/node-bignum/actions?workflow=CI)
Arbitrary precision integral arithmetic for Node.js using
OpenSSL.
This library is based on
[node-bigint](https://github.com/substack/node-bigint) by
[substack](https://github.com/substack), but instead of using libgmp,
it uses the builtin bignum functionality provided by OpenSSL. The
advantage is that OpenSSL is already part of Node.js, so this
library does not add any external dependency whatsoever.
BigInt
======
JavaScript now has a BigInt object. If you are using Node 10.4 or newer, you should use or migrate to [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt).
differences
===========
When switching from node-bigint to node-bignum, please be aware of
these differences:
- Bignum rounds towards zero for integer divisions, e.g. `10 / -3 = -3`, whereas bigint
rounds towards negative infinity, e.g. `10 / -3 = -4`.
- nextPrime() is not supported.
- sqrt() and root() are not supported.
(Patches for the missing functionality are welcome.)
example
=======
simple.js
---------
```js
var bignum = require('bignum');
var b = bignum('782910138827292261791972728324982')
.sub('182373273283402171237474774728373')
.div(8)
;
console.log(b);
```
***
$ node simple.js
<Bignum 75067108192986261319312244199576>
perfect.js
----------
Generate the perfect numbers:
```js
// If 2**n-1 is prime, then (2**n-1) * 2**(n-1) is perfect.
var bignum = require('bignum');
for (var n = 0; n < 100; n++) {
var p = bignum.pow(2, n).sub(1);
if (p.probPrime(50)) {
var perfect = p.mul(bignum.pow(2, n - 1));
console.log(perfect.toString());
}
}
```
***
6
28
496
8128
33550336
8589869056
137438691328
2305843008139952128
2658455991569831744654692615953842176
191561942608236107294793378084303638130997321548169216
methods[0]
==========
bignum(n, base=10)
------------------
Create a new `bignum` from `n` and a base. `n` can be a string, integer, or
another `bignum`.
If you pass in a string you can set the base that string is encoded in.
.toString(base=10)
------------------
Print out the `bignum` instance in the requested base as a string.
bignum.fromBuffer(buf, opts)
----------------------------
Create a new `bignum` from a `Buffer`.
The default options are:
```js
{
endian : 'big',
size : 1, // number of bytes in each word
}
```
Note that endian doesn't matter when size = 1. If you wish to reverse the entire buffer byte by byte, pass size: 'auto'.
bignum.prime(bits, safe=true)
-----------------------------
Generate a probable prime of length `bits`. If `safe` is true, it will be a "safe" prime of the form p=2p'+1 where p' is also prime.
bignum.isBigNum(num)
-----------------------------
Return true if `num` is identified as a bignum instance. Otherwise, return false.
methods[1]
==========
For all of the instance methods below you can write either
```js
bignum.method(x, y, z)
```
or if x is a `bignum` instance``
```js
x.method(y, z)
```
.toNumber()
-----------
Turn a `bignum` into a `Number`. If the `bignum` is too big you'll lose
precision or you'll get ±`Infinity`.
.toBuffer(opts)
-------------
Return a new `Buffer` with the data from the `bignum`.
The default options are:
```js
{
endian : 'big',
size : 1, // number of bytes in each word
}
```
Note that endian doesn't matter when size = 1. If you wish to reverse the entire buffer byte by byte, pass size: 'auto'.
.add(n)
-------
Return a new `bignum` containing the instance value plus `n`.
.sub(n)
-------
Return a new `bignum` containing the instance value minus `n`.
.mul(n)
-------
Return a new `bignum` containing the instance value multiplied by `n`.
.div(n)
-------
Return a new `bignum` containing the instance value integrally divided by `n`.
.abs()
------
Return a new `bignum` with the absolute value of the instance.
.neg()
------
Return a new `bignum` with the negative of the instance value.
.cmp(n)
-------
Compare the instance value to `n`. Return a positive integer if `> n`, a
negative integer if `< n`, and 0 if `== n`.
.gt(n)
------
Return a boolean: whether the instance value is greater than n (`> n`).
.ge(n)
------
Return a boolean: whether the instance value is greater than or equal to n
(`>= n`).
.eq(n)
------
Return a boolean: whether the instance value is equal to n (`== n`).
.lt(n)
------
Return a boolean: whether the instance value is less than n (`< n`).
.le(n)
------
Return a boolean: whether the instance value is less than or equal to n
(`<= n`).
.and(n)
-------
Return a new `bignum` with the instance value bitwise AND (&)-ed with `n`.
.or(n)
------
Return a new `bignum` with the instance value bitwise inclusive-OR (|)-ed with
`n`.
.xor(n)
-------
Return a new `bignum` with the instance value bitwise exclusive-OR (^)-ed with
`n`.
.mod(n)
-------
Return a new `bignum` with the instance value modulo `n`.
`m`.
.pow(n)
-------
Return a new `bignum` with the instance value raised to the `n`th power.
.powm(n, m)
-----------
Return a new `bignum` with the instance value raised to the `n`th power modulo
`m`.
.invertm(m)
-----------
Compute the multiplicative inverse modulo `m`.
.rand()
-------
.rand(upperBound)
-----------------
If `upperBound` is supplied, return a random `bignum` between the instance value
and `upperBound - 1`, inclusive.
Otherwise, return a random `bignum` between 0 and the instance value - 1,
inclusive.
.probPrime()
------------
Return whether the bignum is:
* certainly prime (true)
* probably prime ('maybe')
* certainly composite (false)
using [BN_is_prime_ex](http://www.openssl.org/docs/crypto/BN_generate_prime.html).
.sqrt()
-------
Return a new `bignum` that is the square root. This truncates.
.root(n)
-------
Return a new `bignum` that is the `nth` root. This truncates.
.shiftLeft(n)
-------------
Return a new `bignum` that is the `2^n` multiple. Equivalent of the `<<`
operator.
.shiftRight(n)
--------------
Return a new `bignum` of the value integer divided by
`2^n`. Equivalent of the `>>` operator.
.gcd(n)
-------
Return the greatest common divisor of the current `bignum` with `n` as a new
`bignum`.
.jacobi(n)
-------
Return the Jacobi symbol (or Legendre symbol if `n` is prime) of the current
`bignum` (= a) over `n`. Note that `n` must be odd and >= 3. 0 <= a < n.
Returns -1 or 1 as an int (NOT a bignum). Throws an error on failure.
.bitLength()
------------
Return the number of bits used to represent the current `bignum`.
install
=======
To compile the package, your system needs to be set up for building Node.js
modules.
You can install node-bignum with [npm](http://npmjs.org):
npm install bignum
develop
=======
You can clone the git repo and compile with
git clone git://github.com/justmoon/node-bignum.git
cd node-bignum
npm install
Run the tests with
npm test
================================================
FILE: appveyor.yml
================================================
environment:
node_pre_gyp_accessKeyId:
secure: EXM80HyHBdjKthrNyOlVa/8KKy7m5TdzTtGw0JmnaTs=
node_pre_gyp_secretAccessKey:
secure: PiO+DWUG15lw8VbOG2LRQHDUu2dn5w/fnY1MNXK5IgO35K37q4k7Y2YDPKqvjHgH
# kudos to serialport for much of this
matrix:
- nodejs_version: "4"
- nodejs_version: "6"
- nodejs_version: "8"
- nodejs_version: "10"
platform:
- x86
- x64
install:
- ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) $env:platform;
- ps: $env:Path += ";$(pwd)\node_modules\.bin";
- ps: >
@{
"nodejs_version" = $env:nodejs_version
"platform" = $env:platform
"node binary version" = $(node -v)
"node platform@arch" = $(node -p 'process.platform + process.arch')
"npm version" = $(npm -v)
"APPVEYOR_REPO_COMMIT_MESSAGE" = $env:APPVEYOR_REPO_COMMIT_MESSAGE
"git latest tag" = "$(git describe --tags --always HEAD)"
"appveyor_repo_tag" = $env:appveyor_repo_tag
} | Out-String | Write-Host;
# work around bug in npm 2.15.1 where checksums were coming back bad (node 0.12)
- ps: >
if ($(npm -v) -eq "2.15.1") {
npm install -g npm@3 | Write-Host;
}
npm -v | Write-Host;
# work around an issue with node-gyp v3.3.1 and node 4x
# package.json has no certificates in it so we're cool
# https://github.com/nodejs/node-gyp/issues/921
- ps: npm config set -g cafile=package.json | Write-Host;
- ps: npm config set -g strict-ssl=false | Write-Host;
build_script:
- IF /I "%platform%"=="x86" (SET target_arch="ia32") ELSE (SET target_arch="x64")
- IF /I "%platform%"=="x64" ECHO x64 && CALL "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64
- IF /I "%platform%"=="x86" ECHO x86 && CALL "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86
- npm install --build-from-source --msvs_version=2013
test_script:
- npm test
- node-pre-gyp package 2>&1
- node-pre-gyp unpublish publish --release 2>&1
- node-pre-gyp clean
- npm install --fallback-to-build=false
deploy: off
version: "{build}"
================================================
FILE: bignum.cc
================================================
#include <stdint.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <nan.h>
#include <openssl/bn.h>
#include <map>
#include <utility>
using namespace v8;
using namespace node;
using namespace std;
#define REQ_STR_ARG(I, VAR) \
if (info.Length()<= (I) || !info[I]->IsString()) { \
Nan::ThrowTypeError("Argument " #I " must be a string"); \
return; \
} \
Local<String> VAR = Local<String>::Cast(info[I]);
#define REQ_UTF8_ARG(I, VAR) \
if (info.Length() <= (I) || !info[I]->IsString()) { \
Nan::ThrowTypeError( \
"Argument " #I " must be a utf8 string"); \
return; \
} \
String::Utf8Value VAR(info[I]->ToString());
#define REQ_INT32_ARG(I, VAR) \
if (info.Length() <= (I) || !info[I]->IsInt32()) { \
Nan::ThrowTypeError("Argument " #I " must be an int32"); \
return; \
} \
int32_t VAR = info[I]->ToInt32()->Value();
#define REQ_UINT32_ARG(I, VAR) \
if (info.Length() <= (I) || !info[I]->IsUint32()) { \
Nan::ThrowTypeError("Argument " #I " must be a uint32"); \
return; \
} \
uint32_t VAR = Nan::To<int32_t>(info[I]).FromJust();
#define REQ_INT64_ARG(I, VAR) \
if (info.Length() <= (I) || !info[I]->IsNumber()) { \
Nan::ThrowTypeError("Argument " #I " must be an int64"); \
return; \
} \
int64_t VAR = info[I]->ToInteger(info.GetIsolate()->GetCurrentContext()).ToLocalChecked()->Value();
#define REQ_UINT64_ARG(I, VAR) \
if (info.Length() <= (I) || !info[I]->IsNumber()) { \
Nan::ThrowTypeError("Argument " #I " must be a uint64"); \
return; \
} \
uint64_t VAR = Nan::To<v8::Integer>(info[I]).ToLocalChecked()->Value();
#define REQ_BOOL_ARG(I, VAR) \
if (info.Length() <= (I) || !info[I]->IsBoolean()) { \
Nan::ThrowTypeError("Argument " #I " must be a boolean"); \
return; \
} \
bool VAR = Nan::To<v8::Boolean>(info[I]).ToLocalChecked()->Value();
#define WRAP_RESULT(RES, VAR) \
Local<Value> arg[1] = { Nan::New<External>(static_cast<BigNum*>(RES)) }; \
Local<Object> VAR = Nan::NewInstance( \
Nan::New<FunctionTemplate>(constructor_template)->GetFunction(info.GetIsolate()->GetCurrentContext()).ToLocalChecked(), \
1, \
arg \
).ToLocalChecked();
class AutoBN_CTX
{
protected:
BN_CTX* ctx;
BN_CTX* operator=(BN_CTX* ctx_new) { return ctx = ctx_new; }
public:
AutoBN_CTX()
{
ctx = BN_CTX_new();
// TODO: Handle ctx == NULL
}
~AutoBN_CTX()
{
if (ctx != NULL)
BN_CTX_free(ctx);
}
operator BN_CTX*() { return ctx; }
BN_CTX& operator*() { return *ctx; }
BN_CTX** operator&() { return &ctx; }
bool operator!() { return (ctx == NULL); }
};
/**
* BN_jacobi_priv() computes the Jacobi symbol of A with respect to N.
*
* Hence, *jacobi = 1 when the jacobi symbol is unity and *jacobi = -1 when the
* jacobi symbol is -1. N must be odd and >= 3. It is required that 0 <= A < N.
*
* When successful 0 is returned. -1 is returned on failure.
*
* This is an implementation of an iterative version of Algorithm 2.149 on page
* 73 of the book "Handbook of Applied Cryptography" by Menezes, Oorshot,
* Vanstone. Note that there is a typo in step 1. Step 1 should return the value
* 1. The algorithm has a running time of O((lg N)^2) bit operations.
*
* @author Adam L. Young
*/
int BN_jacobi_priv(const BIGNUM *A,const BIGNUM *N,int *jacobi,
BN_CTX *ctx)
{
int e,returnvalue=0,s,bit0,bit1,bit2,a1bit0,a1bit1;
BIGNUM *zero,*a1,*n1,*three,*tmp;
if (!jacobi)
return -1;
*jacobi = 1;
if ((!A) || (!N) || (!ctx))
return -1;
if (!BN_is_odd(N))
return -1; /* ERROR: BN_jacobi() given an even N */
if (BN_cmp(A,N) >= 0)
return -1;
n1=BN_new();zero=BN_new();a1=BN_new();three=BN_new();tmp=BN_new();
BN_set_word(zero,0);
BN_set_word(three,3);
if (BN_cmp(N,three) < 0)
{ /* This function was written by Adam L. Young */
returnvalue = -1;
goto endBN_jacobi;
}
if (BN_cmp(zero,A) > 0)
{
returnvalue = -1;
goto endBN_jacobi;
}
BN_copy(a1,A);
BN_copy(n1,N);
startjacobistep1:
if (BN_is_zero(a1)) /* step 1 */
goto endBN_jacobi; /* *jacobi = 1; */
if (BN_is_one(a1)) /* step 2 */
goto endBN_jacobi; /* *jacobi = 1; */
for (e=0;;e++) /* step 3 */
if (BN_is_odd(a1))
break;
else
BN_rshift1(a1,a1);
s = 1; /* step 4 */
bit0 = BN_is_odd(n1);
bit1 = BN_is_bit_set(n1,1);
if (e % 2)
{
bit2 = BN_is_bit_set(n1,2);
if ((!bit2) && (bit1) && (bit0))
s = -1;
if ((bit2) && (!bit1) && (bit0))
s = -1;
}
a1bit0 = BN_is_odd(a1); /* step 5 */
a1bit1 = BN_is_bit_set(a1,1);
if (((bit1) && (bit0)) && ((a1bit1) && (a1bit0)))
s = -s;
BN_mod(n1,n1,a1,ctx); /* step 6 */
BN_copy(tmp,a1);
BN_copy(a1,n1);
BN_copy(n1,tmp);
*jacobi *= s; /* step 7 */
goto startjacobistep1;
endBN_jacobi:
BN_clear_free(zero);
BN_clear_free(tmp);BN_clear_free(a1);
BN_clear_free(n1);BN_clear_free(three);
return returnvalue;
}
class BigNum : public Nan::ObjectWrap {
public:
static void Initialize(Local<Object> target);
BIGNUM* bignum_;
static Nan::Persistent<Function> js_conditioner;
static void SetJSConditioner(Local<Function> constructor);
protected:
static Nan::Persistent<FunctionTemplate> constructor_template;
BigNum(const Nan::Utf8String& str, uint64_t base);
BigNum(uint64_t num);
BigNum(int64_t num);
BigNum(BIGNUM *num);
BigNum();
~BigNum();
static NAN_METHOD(New);
static NAN_METHOD(ToString);
static NAN_METHOD(Badd);
static NAN_METHOD(Bsub);
static NAN_METHOD(Bmul);
static NAN_METHOD(Bdiv);
static NAN_METHOD(Uadd);
static NAN_METHOD(Usub);
static NAN_METHOD(Umul);
static NAN_METHOD(Udiv);
static NAN_METHOD(Umul_2exp);
static NAN_METHOD(Udiv_2exp);
static NAN_METHOD(Babs);
static NAN_METHOD(Bneg);
static NAN_METHOD(Bmod);
static NAN_METHOD(Umod);
static NAN_METHOD(Bpowm);
static NAN_METHOD(Upowm);
static NAN_METHOD(Upow);
static NAN_METHOD(Uupow);
static NAN_METHOD(Brand0);
static NAN_METHOD(Uprime0);
static NAN_METHOD(Probprime);
static NAN_METHOD(Bcompare);
static NAN_METHOD(Scompare);
static NAN_METHOD(Ucompare);
static NAN_METHOD(Band);
static NAN_METHOD(Bor);
static NAN_METHOD(Bxor);
static NAN_METHOD(Binvertm);
static NAN_METHOD(Bsqrt);
static NAN_METHOD(Broot);
static NAN_METHOD(BitLength);
static NAN_METHOD(Bgcd);
static NAN_METHOD(Bjacobi);
static NAN_METHOD(Bsetcompact);
static NAN_METHOD(IsBitSet);
static Local<Value> Bop(Nan::NAN_METHOD_ARGS_TYPE info, int op);
};
Nan::Persistent<FunctionTemplate> BigNum::constructor_template;
Nan::Persistent<Function> BigNum::js_conditioner;
void BigNum::SetJSConditioner(Local<Function> constructor) {
js_conditioner.Reset(constructor);
}
void BigNum::Initialize(v8::Local<v8::Object> target) {
Nan::HandleScope scope;
Local<FunctionTemplate> tmpl = Nan::New<FunctionTemplate>(New);
constructor_template.Reset(tmpl);
tmpl->InstanceTemplate()->SetInternalFieldCount(1);
tmpl->SetClassName(Nan::New("BigNum").ToLocalChecked());
Nan::SetMethod(tmpl, "uprime0", Uprime0);
Nan::SetPrototypeMethod(tmpl, "tostring", ToString);
Nan::SetPrototypeMethod(tmpl, "badd", Badd);
Nan::SetPrototypeMethod(tmpl, "bsub", Bsub);
Nan::SetPrototypeMethod(tmpl, "bmul", Bmul);
Nan::SetPrototypeMethod(tmpl, "bdiv", Bdiv);
Nan::SetPrototypeMethod(tmpl, "uadd", Uadd);
Nan::SetPrototypeMethod(tmpl, "usub", Usub);
Nan::SetPrototypeMethod(tmpl, "umul", Umul);
Nan::SetPrototypeMethod(tmpl, "udiv", Udiv);
Nan::SetPrototypeMethod(tmpl, "umul2exp", Umul_2exp);
Nan::SetPrototypeMethod(tmpl, "udiv2exp", Udiv_2exp);
Nan::SetPrototypeMethod(tmpl, "babs", Babs);
Nan::SetPrototypeMethod(tmpl, "bneg", Bneg);
Nan::SetPrototypeMethod(tmpl, "bmod", Bmod);
Nan::SetPrototypeMethod(tmpl, "umod", Umod);
Nan::SetPrototypeMethod(tmpl, "bpowm", Bpowm);
Nan::SetPrototypeMethod(tmpl, "upowm", Upowm);
Nan::SetPrototypeMethod(tmpl, "upow", Upow);
Nan::SetPrototypeMethod(tmpl, "brand0", Brand0);
Nan::SetPrototypeMethod(tmpl, "probprime", Probprime);
Nan::SetPrototypeMethod(tmpl, "bcompare", Bcompare);
Nan::SetPrototypeMethod(tmpl, "scompare", Scompare);
Nan::SetPrototypeMethod(tmpl, "ucompare", Ucompare);
Nan::SetPrototypeMethod(tmpl, "band", Band);
Nan::SetPrototypeMethod(tmpl, "bor", Bor);
Nan::SetPrototypeMethod(tmpl, "bxor", Bxor);
Nan::SetPrototypeMethod(tmpl, "binvertm", Binvertm);
Nan::SetPrototypeMethod(tmpl, "bsqrt", Bsqrt);
Nan::SetPrototypeMethod(tmpl, "broot", Broot);
Nan::SetPrototypeMethod(tmpl, "bitLength", BitLength);
Nan::SetPrototypeMethod(tmpl, "gcd", Bgcd);
Nan::SetPrototypeMethod(tmpl, "jacobi", Bjacobi);
Nan::SetPrototypeMethod(tmpl, "setCompact", Bsetcompact);
Nan::SetPrototypeMethod(tmpl, "isbitset", IsBitSet);
v8::Isolate *isolate = v8::Isolate::GetCurrent();
Nan::Set(target, Nan::New("BigNum").ToLocalChecked(), tmpl->GetFunction(isolate->GetCurrentContext()).ToLocalChecked());
}
BigNum::BigNum(const Nan::Utf8String& str, uint64_t base) : Nan::ObjectWrap (),
bignum_(BN_new())
{
BN_zero(bignum_);
BIGNUM *res = bignum_;
const char *cstr = *str;
switch (base) {
case 2:
for (int i = 0, l = str.length(); i < l; i++) {
if (cstr[l-i-1] != '0') {
BN_set_bit(bignum_, i);
}
}
break;
case 10:
BN_dec2bn(&res, cstr);
break;
case 16:
BN_hex2bn(&res, cstr);
break;
default:
Nan::ThrowError("Invalid base, only 10 and 16 are supported");
return;
}
}
BigNum::BigNum(uint64_t num) : Nan::ObjectWrap (),
bignum_(BN_new())
{
if (sizeof(BN_ULONG) >= 8 || num <= 0xFFFFFFFFL) {
BN_set_word(bignum_, num);
} else {
BN_set_word(bignum_, num >> 32);
BN_lshift(bignum_, bignum_, 32);
BN_add_word(bignum_, num & 0xFFFFFFFFL);
}
}
BigNum::BigNum(int64_t num) : Nan::ObjectWrap (),
bignum_(BN_new())
{
bool neg = (num < 0);
if (neg) {
num = -num;
}
if (num < 0) { // num is -2^63
BN_one(bignum_);
BN_lshift(bignum_, bignum_, 63);
} else if (sizeof(BN_ULONG) >= 8 || num <= 0xFFFFFFFFL) {
BN_set_word(bignum_, num);
} else {
BN_set_word(bignum_, num >> 32);
BN_lshift(bignum_, bignum_, 32);
BN_add_word(bignum_, num & 0xFFFFFFFFL);
}
if (neg) {
BN_set_negative(bignum_, 1);
}
}
BigNum::BigNum(BIGNUM *num) : Nan::ObjectWrap (),
bignum_(BN_new())
{
BN_copy(bignum_, num);
}
BigNum::BigNum() : Nan::ObjectWrap (),
bignum_(BN_new())
{
BN_zero(bignum_);
}
BigNum::~BigNum()
{
BN_clear_free(bignum_);
}
NAN_METHOD(BigNum::New)
{
if (!info.IsConstructCall()) {
int len = info.Length();
Local<Value>* newArgs = new Local<Value>[len];
for (int i = 0; i < len; i++) {
newArgs[i] = info[i];
}
Nan::TryCatch tryCatch;
Nan::MaybeLocal<Object> newInstMaybeLocal = Nan::NewInstance(
Nan::New<FunctionTemplate>(constructor_template)->GetFunction(info.GetIsolate()->GetCurrentContext()).ToLocalChecked(), len, newArgs);
if (tryCatch.HasCaught()) {
tryCatch.ReThrow();
return;
}
Local<Value> newInst = newInstMaybeLocal.ToLocalChecked();
delete[] newArgs;
info.GetReturnValue().Set(newInst);
return;
}
BigNum *bignum;
uint64_t base;
Local<Context> currentContext = info.GetIsolate()->GetCurrentContext();
if (info[0]->IsExternal()) {
bignum = static_cast<BigNum*>(External::Cast(*(info[0]))->Value());
} else {
int len = info.Length();
Local<Object> ctx = Nan::New<Object>();
Local<Value>* newArgs = new Local<Value>[len];
for (int i = 0; i < len; i++) {
newArgs[i] = info[i];
}
Local<Value> obj;
const int ok = Nan::New<Function>(js_conditioner)->
Call(currentContext, ctx, info.Length(), newArgs).ToLocal(&obj);
delete[] newArgs;
if (!ok) {
Nan::ThrowError("Invalid type passed to bignum constructor");
return;
}
Nan::Utf8String str(Nan::Get(obj->ToObject(currentContext).ToLocalChecked(), Nan::New("num").ToLocalChecked()).ToLocalChecked()->ToString(currentContext).ToLocalChecked());
base = Nan::To<int64_t>(Nan::Get(obj->ToObject(currentContext).ToLocalChecked(), Nan::New("base").ToLocalChecked()).ToLocalChecked()).FromJust();
bignum = new BigNum(str, base);
}
bignum->Wrap(info.This());
info.GetReturnValue().Set(info.This());
}
NAN_METHOD(BigNum::ToString)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
uint64_t base = 10;
if (info.Length() > 0) {
REQ_UINT64_ARG(0, tbase);
base = tbase;
}
char *to = NULL;
switch (base) {
case 10:
to = BN_bn2dec(bignum->bignum_);
break;
case 16:
to = BN_bn2hex(bignum->bignum_);
break;
default:
Nan::ThrowError("Invalid base, only 10 and 16 are supported");
return;
}
Local<Value> result = Nan::New<String>(to).ToLocalChecked();
OPENSSL_free(to);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Badd)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
BigNum *res = new BigNum();
BN_add(res->bignum_, bignum->bignum_, bn->bignum_);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Bsub)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
BigNum *res = new BigNum();
BN_sub(res->bignum_, bignum->bignum_, bn->bignum_);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Bmul)
{
AutoBN_CTX ctx;
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
BigNum *res = new BigNum();
BN_mul(res->bignum_, bignum->bignum_, bn->bignum_, ctx);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Bdiv)
{
AutoBN_CTX ctx;
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *bi = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
BigNum *res = new BigNum();
BN_div(res->bignum_, NULL, bignum->bignum_, bi->bignum_, ctx);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Uadd)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_UINT64_ARG(0, x);
BigNum *res = new BigNum(bignum->bignum_);
if (sizeof(BN_ULONG) >= 8 || x <= 0xFFFFFFFFL) {
BN_add_word(res->bignum_, x);
} else {
BigNum *bn = new BigNum(x);
BN_add(res->bignum_, bignum->bignum_, bn->bignum_);
}
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Usub)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_UINT64_ARG(0, x);
BigNum *res = new BigNum(bignum->bignum_);
if (sizeof(BN_ULONG) >= 8 || x <= 0xFFFFFFFFL) {
BN_sub_word(res->bignum_, x);
} else {
BigNum *bn = new BigNum(x);
BN_sub(res->bignum_, bignum->bignum_, bn->bignum_);
}
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Umul)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_UINT64_ARG(0, x);
BigNum *res = new BigNum(bignum->bignum_);
if (sizeof(BN_ULONG) >= 8 || x <= 0xFFFFFFFFL) {
BN_mul_word(res->bignum_, x);
} else {
AutoBN_CTX ctx;
BigNum *bn = new BigNum(x);
BN_mul(res->bignum_, bignum->bignum_, bn->bignum_, ctx);
}
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Udiv)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_UINT64_ARG(0, x);
BigNum *res = new BigNum(bignum->bignum_);
if (sizeof(BN_ULONG) >= 8 || x <= 0xFFFFFFFFL) {
BN_div_word(res->bignum_, x);
} else {
AutoBN_CTX ctx;
BigNum *bn = new BigNum(x);
BN_div(res->bignum_, NULL, bignum->bignum_, bn->bignum_, ctx);
}
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Umul_2exp)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_UINT32_ARG(0, x);
BigNum *res = new BigNum();
BN_lshift(res->bignum_, bignum->bignum_, x);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Udiv_2exp)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_UINT32_ARG(0, x);
BigNum *res = new BigNum();
BN_rshift(res->bignum_, bignum->bignum_, x);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Babs)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *res = new BigNum(bignum->bignum_);
BN_set_negative(res->bignum_, 0);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Bneg)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *res = new BigNum(bignum->bignum_);
BN_set_negative(res->bignum_, !BN_is_negative(res->bignum_));
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Bmod)
{
AutoBN_CTX ctx;
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
BigNum *res = new BigNum();
BN_div(NULL, res->bignum_, bignum->bignum_, bn->bignum_, ctx);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Umod)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_UINT64_ARG(0, x);
BigNum *res = new BigNum();
if (sizeof(BN_ULONG) >= 8 || x <= 0xFFFFFFFFL) {
BN_set_word(res->bignum_, BN_mod_word(bignum->bignum_, x));
} else {
AutoBN_CTX ctx;
BigNum *bn = new BigNum(x);
BN_div(NULL, res->bignum_, bignum->bignum_, bn->bignum_, ctx);
}
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Bpowm)
{
AutoBN_CTX ctx;
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *bn1 = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
BigNum *bn2 = Nan::ObjectWrap::Unwrap<BigNum>(info[1]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
BigNum *res = new BigNum();
BN_mod_exp(res->bignum_, bignum->bignum_, bn1->bignum_, bn2->bignum_, ctx);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Upowm)
{
AutoBN_CTX ctx;
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_UINT64_ARG(0, x);
BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[1]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
BigNum *exp = new BigNum(x);
BigNum *res = new BigNum();
BN_mod_exp(res->bignum_, bignum->bignum_, exp->bignum_, bn->bignum_, ctx);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Upow)
{
AutoBN_CTX ctx;
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_UINT64_ARG(0, x);
BigNum *exp = new BigNum(x);
BigNum *res = new BigNum();
BN_exp(res->bignum_, bignum->bignum_, exp->bignum_, ctx);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Brand0)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *res = new BigNum();
BN_rand_range(res->bignum_, bignum->bignum_);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Uprime0)
{
REQ_UINT32_ARG(0, x);
REQ_BOOL_ARG(1, safe);
BigNum *res = new BigNum();
BN_generate_prime_ex(res->bignum_, x, safe, NULL, NULL, NULL);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Probprime)
{
AutoBN_CTX ctx;
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_UINT32_ARG(0, reps);
info.GetReturnValue().Set(Nan::New<Number>(BN_is_prime_ex(bignum->bignum_, reps, ctx, NULL)));
}
NAN_METHOD(BigNum::IsBitSet)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_UINT32_ARG(0, n);
info.GetReturnValue().Set(Nan::New<Number>(BN_is_bit_set(bignum->bignum_, n)));
}
NAN_METHOD(BigNum::Bcompare)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
info.GetReturnValue().Set(Nan::New<Number>(BN_cmp(bignum->bignum_, bn->bignum_)));
}
NAN_METHOD(BigNum::Scompare)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_INT64_ARG(0, x);
BigNum *bn = new BigNum(x);
int res = BN_cmp(bignum->bignum_, bn->bignum_);
info.GetReturnValue().Set(Nan::New<Number>(res));
}
NAN_METHOD(BigNum::Ucompare)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
REQ_UINT64_ARG(0, x);
int res;
if (sizeof(BN_ULONG) >= 8 || x <= 0xFFFFFFFFL) {
BIGNUM* bn = BN_new();
BN_set_word(bn, x);
res = BN_cmp(bignum->bignum_, bn);
BN_clear_free(bn);
} else {
BigNum *bn = new BigNum(x);
res = BN_cmp(bignum->bignum_, bn->bignum_);
}
info.GetReturnValue().Set(Nan::New<Number>(res));
}
// Utility functions from converting OpenSSL's MPI
// format to two's complement, which is what bitwise
// operations are expected to work on
static void
mpi2twosComplement(uint8_t *bytes, size_t numBytes)
{
int i;
bytes[0] &= ~0x80;
for (i = 0; i < (int) numBytes; i++) {
bytes[i] = ~bytes[i];
}
for (i = numBytes - 1; i >= 0; i--) {
if (bytes[i] == 0xff) {
bytes[i] = 0;
} else {
bytes[i]++;
break;
}
}
}
static void
twos_complement2mpi(uint8_t *bytes, size_t numBytes)
{
int i;
for (i = numBytes - 1; i >= 0; i--) {
if (bytes[i] == 0) {
bytes[i] = 0xff;
} else {
bytes[i]--;
break;
}
}
for (i = 0; i < (int) numBytes; i++) {
bytes[i] = ~bytes[i];
}
bytes[0] |= 0x80;
}
const int BN_PAYLOAD_OFFSET = 4;
// Shifts things around in an OpenSSL MPI buffer so that
// the sizes of bignum operands match
static void
shiftSizeAndMSB(uint8_t *bytes, uint8_t *sizeBuffer, size_t offset)
{
memset(bytes + offset, 0, BN_PAYLOAD_OFFSET);
memcpy(bytes, sizeBuffer, BN_PAYLOAD_OFFSET);
// We've copied the size header over; now we just need to move
// the MSB signifying negativity if it's present
if(bytes[BN_PAYLOAD_OFFSET + offset] & 0x80) {
bytes[BN_PAYLOAD_OFFSET] |= 0x80;
bytes[BN_PAYLOAD_OFFSET + offset] &= ~0x80;
}
}
static bool
isMinimumNegativeNumber(uint8_t *bytes, size_t size)
{
if (bytes[0] != 0x80) {
return false;
}
for (size_t i = 1; i < size; i++) {
if (bytes[i] != 0) {
return false;
}
}
return true;
}
static void
swapEndianness(uint8_t *bytes)
{
uint8_t tmp;
tmp = bytes[0];
bytes[0] = bytes[3];
bytes[3] = tmp;
tmp = bytes[1];
bytes[1] = bytes[2];
bytes[2] = tmp;
}
Local<Value>
BigNum::Bop(Nan::NAN_METHOD_ARGS_TYPE info, int op)
{
Nan::EscapableHandleScope scope;
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
bool bignumNegative = BN_is_negative(bignum->bignum_);
bool bnNegative = BN_is_negative(bn->bignum_);
BigNum *res = new BigNum();
// Modified from https://github.com/Worlize/WebSocket-Node/blob/master/src/xor.cpp
// Portions Copyright (c) Agora S.A.
// Licensed under the MIT License.
int payloadSize = BN_bn2mpi(bignum->bignum_, NULL);
int maskSize = BN_bn2mpi(bn->bignum_, NULL);
uint32_t size = max(payloadSize, maskSize);
int offset = abs(payloadSize - maskSize);
int payloadOffset = 0;
int maskOffset = 0;
if (payloadSize < maskSize) {
payloadOffset = offset;
} else if (payloadSize > maskSize) {
maskOffset = offset;
}
uint8_t* payload = (uint8_t*) calloc(size, sizeof(char));
uint8_t* mask = (uint8_t*) calloc(size, sizeof(char));
BN_bn2mpi(bignum->bignum_, payload + payloadOffset);
BN_bn2mpi(bn->bignum_, mask + maskOffset);
if (payloadSize < maskSize) {
shiftSizeAndMSB(payload, mask, payloadOffset);
} else {
shiftSizeAndMSB(mask, payload, maskOffset);
}
payload += BN_PAYLOAD_OFFSET;
mask += BN_PAYLOAD_OFFSET;
size -= BN_PAYLOAD_OFFSET;
if(bignumNegative) {
mpi2twosComplement(payload, size);
}
if(bnNegative) {
mpi2twosComplement(mask, size);
}
uint32_t* pos32 = (uint32_t*) payload;
uint32_t* end32 = pos32 + (size / 4);
uint32_t* mask32 = (uint32_t*) mask;
switch (op) {
case 0: while (pos32 < end32) *(pos32++) &= *(mask32++); break;
case 1: while (pos32 < end32) *(pos32++) |= *(mask32++); break;
case 2: while (pos32 < end32) *(pos32++) ^= *(mask32++); break;
}
uint8_t* pos8 = (uint8_t*) pos32;
uint8_t* end8 = payload + size;
uint8_t* mask8 = (uint8_t*) mask32;
switch (op) {
case 0: while (pos8 < end8) *(pos8++) &= *(mask8++); break;
case 1: while (pos8 < end8) *(pos8++) |= *(mask8++); break;
case 2: while (pos8 < end8) *(pos8++) ^= *(mask8++); break;
}
payload -= BN_PAYLOAD_OFFSET;
mask -= BN_PAYLOAD_OFFSET;
size += BN_PAYLOAD_OFFSET;
// If the value is the largest negative number representible by
// size bytes, we need to add another byte to the payload buffer,
// otherwise OpenSSL's BN_mpi2bn will interpret the number as -0
if (isMinimumNegativeNumber(payload + BN_PAYLOAD_OFFSET, size - BN_PAYLOAD_OFFSET)) {
bool bigEndian = (size - BN_PAYLOAD_OFFSET) == *((uint32_t *) payload);
uint8_t *newPayload = (uint8_t *) calloc(size + 1, 1);
memcpy(newPayload + 5, payload + BN_PAYLOAD_OFFSET, size - BN_PAYLOAD_OFFSET);
newPayload[BN_PAYLOAD_OFFSET] = 0x80;
size++;
size -= BN_PAYLOAD_OFFSET;
memcpy(newPayload, &size, BN_PAYLOAD_OFFSET);
size += BN_PAYLOAD_OFFSET;
if (!bigEndian) {
swapEndianness(newPayload);
}
free(payload);
payload = newPayload;
} else if(payload[BN_PAYLOAD_OFFSET] & 0x80) {
twos_complement2mpi(payload + BN_PAYLOAD_OFFSET, size - BN_PAYLOAD_OFFSET);
}
BN_mpi2bn(payload, size, res->bignum_);
WRAP_RESULT(res, result);
free(payload);
free(mask);
return scope.Escape(result);
}
NAN_METHOD(BigNum::Band)
{
info.GetReturnValue().Set(Bop(info, 0));
}
NAN_METHOD(BigNum::Bor)
{
info.GetReturnValue().Set(Bop(info, 1));
}
NAN_METHOD(BigNum::Bxor)
{
info.GetReturnValue().Set(Bop(info, 2));
}
NAN_METHOD(BigNum::Binvertm)
{
AutoBN_CTX ctx;
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *bn = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
BigNum *res = new BigNum();
BN_mod_inverse(res->bignum_, bignum->bignum_, bn->bignum_, ctx);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Bsqrt)
{
Nan::ThrowError("sqrt is not supported by OpenSSL.");
}
NAN_METHOD(BigNum::Broot)
{
Nan::ThrowError("root is not supported by OpenSSL.");
}
NAN_METHOD(BigNum::BitLength)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
int size = BN_num_bits(bignum->bignum_);
Local<Value> result = Nan::New<Integer>(size);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Bgcd)
{
AutoBN_CTX ctx;
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *bi = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
BigNum *res = new BigNum();
BN_gcd(res->bignum_, bignum->bignum_, bi->bignum_, ctx);
WRAP_RESULT(res, result);
info.GetReturnValue().Set(result);
}
NAN_METHOD(BigNum::Bjacobi)
{
AutoBN_CTX ctx;
BigNum *bn_a = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
BigNum *bn_n = Nan::ObjectWrap::Unwrap<BigNum>(info[0]->ToObject(info.GetIsolate()->GetCurrentContext()).ToLocalChecked());
int res = 0;
if (BN_jacobi_priv(bn_a->bignum_, bn_n->bignum_, &res, ctx) == -1) {
Nan::ThrowError("Jacobi symbol calculation failed");
return;
}
info.GetReturnValue().Set(Nan::New<Integer>(res));
}
NAN_METHOD(BigNum::Bsetcompact)
{
BigNum *bignum = Nan::ObjectWrap::Unwrap<BigNum>(info.This());
unsigned int nCompact = Nan::To<uint32_t>(info[0]).FromJust();
unsigned int nSize = nCompact >> 24;
bool fNegative =(nCompact & 0x00800000) != 0;
unsigned int nWord = nCompact & 0x007fffff;
if (nSize <= 3)
{
nWord >>= 8*(3-nSize);
BN_set_word(bignum->bignum_, nWord);
}
else
{
BN_set_word(bignum->bignum_, nWord);
BN_lshift(bignum->bignum_, bignum->bignum_, 8*(nSize-3));
}
BN_set_negative(bignum->bignum_, fNegative);
info.GetReturnValue().Set(info.This());
}
static NAN_METHOD(SetJSConditioner)
{
Nan::HandleScope scope;
BigNum::SetJSConditioner(Local<Function>::Cast(info[0]));
return;
}
extern "C" void
init (Local<Object> target)
{
Nan::HandleScope scope;
BigNum::Initialize(target);
Nan::SetMethod(target, "setJSConditioner", SetJSConditioner);
}
NODE_MODULE(bignum, init)
================================================
FILE: binding.gyp
================================================
{
'targets': [
{
'target_name': 'bignum',
'sources': [ 'bignum.cc' ],
'include_dirs': [
"<!(node -e \"require('nan')\")"
],
'conditions': [
# For Windows, require either a 32-bit or 64-bit
# separately-compiled OpenSSL library.
# Currently set up to use with the following OpenSSL distro:
#
# http://slproweb.com/products/Win32OpenSSL.html
[
'OS=="win"', {
'conditions': [
[
'target_arch=="x64"', {
'variables': {
'openssl_root%': 'C:/OpenSSL-Win64'
},
}, {
'variables': {
'openssl_root%': 'C:/OpenSSL-Win32'
}
}
]
],
'libraries': [
'-l<(openssl_root)/lib/libeay32.lib',
],
'include_dirs': [
'<(openssl_root)/include',
],
},
# Otherwise, if not Windows, link against the exposed OpenSSL
# in Node.
{
'conditions': [
[
'target_arch=="ia32"', {
'variables': {
'openssl_config_path': '<(nodedir)/deps/openssl/config/piii'
}
}
],
[
'target_arch=="x64"', {
'variables': {
'openssl_config_path': '<(nodedir)/deps/openssl/config/k8'
},
}
],
[
'target_arch=="arm"', {
'variables': {
'openssl_config_path': '<(nodedir)/deps/openssl/config/arm'
}
}
],
[
'target_arch=="arm64"', {
'variables': {
'openssl_config_path': '<(nodedir)/deps/openssl/config/aarch64'
}
},
],
[
'target_arch=="ppc64"', {
'variables': {
'openssl_config_path': '<(nodedir)/deps/openssl/config/powerpc64'
}
},
]
],
'include_dirs': [
"<(nodedir)/deps/openssl/openssl/include",
"<(openssl_config_path)"
]
}
]
]
}
]
}
================================================
FILE: examples/gen.js
================================================
// Generate two primes p and q to the Digital Signature Standard (DSS)
// http://www.itl.nist.gov/fipspubs/fip186.htm appendix 2.2
var bignum = require('../')
var assert = require('assert')
var q = bignum(2).pow(159).add(1).rand(bignum(2).pow(160)).nextPrime()
var L = 512 + 64 * Math.floor(Math.random() * 8)
do {
var X = bignum(2).pow(L - 1).add(1).rand(bignum(2).pow(L))
var c = X.mod(q.mul(2))
var p = X.sub(c.sub(1)) // p is congruent to 1 % 2q somehow!
} while (p.lt(bignum.pow(2, L - 1)) || p.probPrime(50) === false)
assert.ok(q.gt(bignum.pow(2, 159)), 'q > 2**159')
assert.ok(q.lt(bignum.pow(2, 160)), 'q < 2**160')
assert.ok(p.gt(bignum.pow(2, L - 1)), 'p > 2**(L-1)')
assert.ok(q.lt(bignum.pow(2, L)), 'p < 2**L')
assert.ok(q.mul(p.sub(1).div(q)).add(1).eq(p), 'q divides p - 1')
assert.ok(p.probPrime(50), 'p is not prime!')
assert.ok(q.probPrime(50), 'q is not prime!')
console.dir({ p: p, q: q })
================================================
FILE: examples/perfect.js
================================================
// If 2**n-1 is prime, then (2**n-1) * 2**(n-1) is perfect.
var bignum = require('../')
for (var n = 0; n < 100; n++) {
var p = bignum.pow(2, n).sub(1)
if (p.probPrime(50)) {
var perfect = p.mul(bignum.pow(2, n - 1))
console.log(perfect.toString())
}
}
================================================
FILE: examples/simple.js
================================================
var bignum = require('../')
var b = bignum('782910138827292261791972728324982')
.sub('182373273283402171237474774728373')
.div(8)
console.log(b)
================================================
FILE: index.js
================================================
var bin = require('bindings')('bignum')
var Buffer = require('safe-buffer').Buffer
var BigNum = bin.BigNum
module.exports = BigNum
BigNum.conditionArgs = function (num, base) {
if (typeof num !== 'string') num = num.toString(base || 10)
if (num.match(/e\+/)) { // positive exponent
if (!Number(num).toString().match(/e+/)) {
return {
num: Math.floor(Number(num)).toString(),
base: 10
}
} else {
var pow = Math.ceil(Math.log(num) / Math.log(2))
var n = (num / Math.pow(2, pow)).toString(2)
.replace(/^0/, '')
var i = n.length - n.indexOf('.')
n = n.replace(/\./, '')
for (; i <= pow; i++) n += '0'
return {
num: n,
base: 2
}
}
} else if (num.match(/e-/)) { // negative exponent
return {
num: Math.floor(Number(num)).toString(),
base: base || 10
}
} else {
return {
num: num,
base: base || 10
}
}
}
bin.setJSConditioner(BigNum.conditionArgs)
BigNum.isBigNum = function (num) {
if (!num) {
return false
}
for (var key in BigNum.prototype) {
if (!num[key]) {
return false
}
}
return true
}
BigNum.prototype.inspect = function () {
return '<BigNum ' + this.toString(10) + '>'
}
BigNum.prototype.toString = function (base) {
var value
if (base) {
value = this.tostring(base)
} else {
value = this.tostring()
}
if (base > 10 && typeof value === 'string') {
value = value.toLowerCase()
}
return value
}
BigNum.prototype.toNumber = function () {
return parseInt(this.toString(), 10)
}
;['add', 'sub', 'mul', 'div', 'mod'].forEach(function (op) {
BigNum.prototype[op] = function (num) {
var x
if (BigNum.isBigNum(num)) {
return this['b' + op](num)
} else if (typeof num === 'number') {
if (num >= 0) {
return this['u' + op](num)
} else if (op === 'add') {
return this.usub(-num)
} else if (op === 'sub') {
return this.uadd(-num)
} else {
x = BigNum(num)
return this['b' + op](x)
}
} else if (typeof num === 'string') {
x = BigNum(num)
return this['b' + op](x)
} else {
throw new TypeError('Unspecified operation for type ' +
(typeof num) + ' for ' + op)
}
}
})
BigNum.prototype.abs = function () {
return this.babs()
}
BigNum.prototype.neg = function () {
return this.bneg()
}
BigNum.prototype.powm = function (num, mod) {
var m
if ((typeof mod) === 'number' || (typeof mod) === 'string') {
m = BigNum(mod)
} else if (BigNum.isBigNum(mod)) {
m = mod
}
if ((typeof num) === 'number') {
return this.upowm(num, m)
} else if ((typeof num) === 'string') {
var n = BigNum(num)
return this.bpowm(n, m)
} else if (BigNum.isBigNum(num)) {
return this.bpowm(num, m)
}
}
BigNum.prototype.mod = function (num, mod) {
var m
if ((typeof mod) === 'number' || (typeof mod) === 'string') {
m = BigNum(mod)
} else if (BigNum.isBigNum(mod)) {
m = mod
}
if ((typeof num) === 'number') {
return this.umod(num, m)
} else if ((typeof num) === 'string') {
var n = BigNum(num)
return this.bmod(n, m)
} else if (BigNum.isBigNum(num)) {
return this.bmod(num, m)
}
}
BigNum.prototype.pow = function (num) {
if (typeof num === 'number') {
if (num >= 0) {
return this.upow(num)
} else {
return BigNum.prototype.powm.call(this, num, this)
}
} else {
var x = parseInt(num.toString(), 10)
return BigNum.prototype.pow.call(this, x)
}
}
BigNum.prototype.shiftLeft = function (num) {
if (typeof num === 'number') {
if (num >= 0) {
return this.umul2exp(num)
} else {
return this.shiftRight(-num)
}
} else {
var x = parseInt(num.toString(), 10)
return BigNum.prototype.shiftLeft.call(this, x)
}
}
BigNum.prototype.shiftRight = function (num) {
if (typeof num === 'number') {
if (num >= 0) {
return this.udiv2exp(num)
} else {
return this.shiftLeft(-num)
}
} else {
var x = parseInt(num.toString(), 10)
return BigNum.prototype.shiftRight.call(this, x)
}
}
BigNum.prototype.cmp = function (num) {
if (BigNum.isBigNum(num)) {
return this.bcompare(num)
} else if (typeof num === 'number') {
if (num < 0) {
return this.scompare(num)
} else {
return this.ucompare(num)
}
} else {
var x = BigNum(num)
return this.bcompare(x)
}
}
BigNum.prototype.gt = function (num) {
return this.cmp(num) > 0
}
BigNum.prototype.ge = function (num) {
return this.cmp(num) >= 0
}
BigNum.prototype.eq = function (num) {
return this.cmp(num) === 0
}
BigNum.prototype.ne = function (num) {
return this.cmp(num) !== 0
}
BigNum.prototype.lt = function (num) {
return this.cmp(num) < 0
}
BigNum.prototype.le = function (num) {
return this.cmp(num) <= 0
}
'and or xor'.split(' ').forEach(function (name) {
BigNum.prototype[name] = function (num) {
if (BigNum.isBigNum(num)) {
return this['b' + name](num)
} else {
var x = BigNum(num)
return this['b' + name](x)
}
}
})
BigNum.prototype.sqrt = function () {
return this.bsqrt()
}
BigNum.prototype.root = function (num) {
if (BigNum.isBigNum(num)) {
return this.broot(num)
} else {
return this.broot(num)
}
}
BigNum.prototype.rand = function (to) {
if (to === undefined) {
if (this.toString() === '1') {
return BigNum(0)
} else {
return this.brand0()
}
} else {
var x = BigNum.isBigNum(to) ? to.sub(this) : BigNum(to).sub(this)
return x.brand0().add(this)
}
}
BigNum.prototype.invertm = function (mod) {
if (BigNum.isBigNum(mod)) {
return this.binvertm(mod)
} else {
var x = BigNum(mod)
return this.binvertm(x)
}
}
BigNum.prime = function (bits, safe) {
if (typeof safe === 'undefined') {
safe = true
}
// Force uint32
bits >>>= 0
return BigNum.uprime0(bits, !!safe)
}
BigNum.prototype.probPrime = function (reps) {
var n = this.probprime(reps || 10)
return { 1: true, 0: false }[n]
}
BigNum.prototype.nextPrime = function () {
var num = this
do {
num = num.add(1)
} while (!num.probPrime())
return num
}
BigNum.prototype.isBitSet = function (n) {
return this.isbitset(n) === 1
}
BigNum.fromBuffer = function (buf, opts) {
if (!opts) opts = {}
var endian = { 1: 'big', '-1': 'little' }[opts.endian] ||
opts.endian || 'big'
var size = opts.size === 'auto' ? Math.ceil(buf.length) : (opts.size || 1)
if (buf.length % size !== 0) {
throw new RangeError('Buffer length (' + buf.length + ')' +
' must be a multiple of size (' + size + ')'
)
}
var hex = []
for (var i = 0; i < buf.length; i += size) {
var chunk = []
for (var j = 0; j < size; j++) {
chunk.push(buf[i + (endian === 'big' ? j : (size - j - 1))])
}
hex.push(chunk
.map(function (c) {
return (c < 16 ? '0' : '') + c.toString(16)
})
.join('')
)
}
return BigNum(hex.join(''), 16)
}
BigNum.prototype.toBuffer = function (opts) {
if (typeof opts === 'string') {
if (opts !== 'mpint') return 'Unsupported Buffer representation'
var abs = this.abs()
var buf = abs.toBuffer({ size: 1, endian: 'big' })
var len = buf.length === 1 && buf[0] === 0 ? 0 : buf.length
if (buf[0] & 0x80) len++
var ret = Buffer.alloc(4 + len)
if (len > 0) buf.copy(ret, 4 + (buf[0] & 0x80 ? 1 : 0))
if (buf[0] & 0x80) ret[4] = 0
ret[0] = len & (0xff << 24)
ret[1] = len & (0xff << 16)
ret[2] = len & (0xff << 8)
ret[3] = len & (0xff << 0)
// two's compliment for negative integers:
var isNeg = this.lt(0)
if (isNeg) {
for (var i = 4; i < ret.length; i++) {
ret[i] = 0xff - ret[i]
}
}
ret[4] = (ret[4] & 0x7f) | (isNeg ? 0x80 : 0)
if (isNeg) ret[ret.length - 1]++
return ret
}
if (!opts) opts = {}
var endian = { 1: 'big', '-1': 'little' }[opts.endian] ||
opts.endian || 'big'
var hex = this.toString(16)
if (hex.charAt(0) === '-') {
throw new Error('converting negative numbers to Buffers not supported yet')
}
var size = opts.size === 'auto' ? Math.ceil(hex.length / 2) : (opts.size || 1)
len = Math.ceil(hex.length / (2 * size)) * size
buf = Buffer.alloc(len)
// zero-pad the hex string so the chunks are all `size` long
while (hex.length < 2 * len) hex = '0' + hex
var hx = hex
.split(new RegExp('(.{' + (2 * size) + '})'))
.filter(function (s) { return s.length > 0 })
hx.forEach(function (chunk, i) {
for (var j = 0; j < size; j++) {
var ix = i * size + (endian === 'big' ? j : size - j - 1)
buf[ix] = parseInt(chunk.slice(j * 2, j * 2 + 2), 16)
}
})
return buf
}
Object.keys(BigNum.prototype).forEach(function (name) {
if (name === 'inspect' || name === 'toString') return
BigNum[name] = function (num) {
var args = [].slice.call(arguments, 1)
if (BigNum.isBigNum(num)) {
return num[name].apply(num, args)
} else {
var bigi = BigNum(num)
return bigi[name].apply(bigi, args)
}
}
})
================================================
FILE: package.json
================================================
{
"name": "bignum",
"version": "0.13.1",
"description": "Arbitrary-precision integer arithmetic using OpenSSL",
"main": "./index.js",
"repository": {
"type": "git",
"url": "http://github.com/justmoon/node-bignum.git"
},
"keywords": [
"openssl",
"big",
"bignum",
"bigint",
"integer",
"arithmetic",
"precision"
],
"author": {
"name": "Stefan Thomas",
"email": "justmoon@members.fsf.org",
"url": "http://www.justmoon.net"
},
"dependencies": {
"bindings": "^1.5.0",
"nan": "^2.14.0",
"safe-buffer": "^5.2.0"
},
"devDependencies": {
"put": "0.0.6",
"standard": "^14.3.1",
"tap": "^14.10.5"
},
"scripts": {
"install": "node-gyp rebuild",
"test": "standard && tap --timeout 120 test/*.js"
},
"license": "MIT",
"contributors": [
"James Halliday <mail@substack.net>",
"Rod Vagg <rod@vagg.org>"
]
}
================================================
FILE: test/big.js
================================================
var Buffer = require('safe-buffer').Buffer
var BigNum = require('../')
var test = require('tap').test
test('create', { timeout: 120000 }, function (t) {
t.deepEqual(BigNum(1337).toString(), '1337')
t.deepEqual(BigNum('1337').toString(), '1337')
t.deepEqual(new BigNum('100').toString(), '100')
t.deepEqual(
new BigNum('55555555555555555555555555').toString(),
'55555555555555555555555555'
)
t.deepEqual(Number(BigNum('1e+100').toString()), 1e+100)
t.deepEqual(Number(BigNum('1e+100').bitLength()), 333)
t.deepEqual(Number(BigNum('1.23e+45').toString()), 1.23e+45)
for (var i = 0; i < 10; i++) {
t.deepEqual(
BigNum('1.23456e+' + i).toString(),
Math.floor(1.23456 * Math.pow(10, i))
)
}
t.deepEqual(BigNum('1.23e-45').toString(), '0')
t.throws(function () { BigNum(undefined) })
t.throws(function () { BigNum(null) })
t.end()
})
test('add', { timeout: 120000 }, function (t) {
for (var i = -10; i < 10; i++) {
for (var j = -10; j < 10; j++) {
var js = j.toString()
var ks = (i + j).toString()
t.deepEqual(BigNum(i).add(j).toString(), ks)
t.deepEqual(BigNum(i).add(js).toString(), ks)
t.deepEqual(BigNum(i).add(BigNum(j)).toString(), ks)
t.deepEqual(BigNum.add(i, j).toString(), ks)
}
}
t.deepEqual(
BigNum(
'201781752444966478956292456789265633588628356858680927185287861892' +
'9889675589272409635031813235465496971529430565627918846694860512' +
'1492948268400884893722767401972695174353441'
).add(
'939769862972759638577945343130228368606420083646071622223953046277' +
'3784500359975110887672142614667937014937371109558223563373329424' +
'0624814097369771481147215472578762824607080'
).toString(),
'1141551615417726117534237799919494002195048440504752549409240908170367' +
'41759492475205227039558501334339864668016751861424100681899362117762' +
'365770656374869982874551457998960521'
)
t.end()
})
test('sub', { timeout: 120000 }, function (t) {
for (var i = -10; i < 10; i++) {
for (var j = -10; j < 10; j++) {
var js = j.toString()
var ks = (i - j).toString()
t.deepEqual(BigNum(i).sub(j).toString(), ks)
t.deepEqual(BigNum(i).sub(js).toString(), ks)
t.deepEqual(BigNum(i).sub(BigNum(j)).toString(), ks)
t.deepEqual(BigNum.sub(i, j).toString(), ks)
}
}
t.deepEqual(
BigNum(
'635849762218952604062459342660379446997761295162166888134051068531' +
'9813941775949841573516110003093332652267534768664621969514455380' +
'8051168706779408804756208386011014197185296'
).sub(
'757617343536280696839135295661092954931163607913400460585109207644' +
'7966483882748233585856350085641718822741649072106343655764769889' +
'6399869016678013515043471880323279258685478'
).toString(),
'-121767581317328092776675953000713507933402312751233572451058139112815' +
'25421067983920123402400825483861704741143034417216862503145088348700' +
'309898604710287263494312265061500182'
)
t.end()
})
test('mul', { timeout: 120000 }, function (t) {
for (var i = -10; i < 10; i++) {
for (var j = -10; j < 10; j++) {
var js = j.toString()
var ks = (i * j).toString()
t.deepEqual(BigNum(i).mul(j).toString(), ks)
t.deepEqual(BigNum(i).mul(js).toString(), ks)
t.deepEqual(BigNum(i).mul(BigNum(j)).toString(), ks)
t.deepEqual(BigNum.mul(i, j).toString(), ks)
}
}
t.deepEqual(
BigNum(
'433593290010590489671135819286259593426549306666324008679782084292' +
'2446494189019075159822930571858728009485237489829138626896756141' +
'8738958337632249177044975686477011571044266'
).mul(
'127790264841901718791915669264129510947625523373763053776083279450' +
'3886212911067061184379695097643279217271150419129022856601771338' +
'794256383410400076210073482253089544155377'
).toString(),
'5540900136412485758752141142221047463857522755277604708501015732755989' +
'17659432099233635577634197309727815375309484297883528869192732141328' +
'99346769031695550850320602049507618052164677667378189154076988316301' +
'23719953859959804490669091769150047414629675184805332001182298088891' +
'58079529848220802017396422115936618644438110463469902675126288489182' +
'82'
)
t.deepEqual(
BigNum('10000000000000000000000000000').mul(-123).toString(),
'-1230000000000000000000000000000'
)
t.end()
})
test('div', { timeout: 120000 }, function (t) {
for (var i = -10; i < 10; i++) {
for (var j = -10; j < 10; j++) {
var js = j.toString()
var round = ((i / j) < 0) ? Math.ceil : Math.floor
var ks = round(i / j).toString()
if (ks.match(/^-?\d+$/)) { // ignore exceptions
t.deepEqual(BigNum(i).div(j).toString(), ks)
t.deepEqual(BigNum(i).div(js).toString(), ks)
t.deepEqual(BigNum(i).div(BigNum(j)).toString(), ks)
t.deepEqual(BigNum.div(i, j).toString(), ks)
}
}
}
t.deepEqual(
BigNum(
'433593290010590489671135819286259593426549306666324008679782084292' +
'2446494189019075159822930571858728009485237489829138626896756141' +
'8738958337632249177044975686477011571044266'
).div(
'127790264841901718791915669264129510947625523373763053776083279450' +
'3886212911067061184379695097643279217271150419129022856601771338' +
'794256383410400076210073482253089544155377'
).toString(),
'33'
)
t.end()
})
test('abs', { timeout: 120000 }, function (t) {
t.deepEqual(
BigNum(
'433593290010590489671135819286259593426549306666324008679782084292' +
'2446494189019075159822930571858728009485237489829138626896756141' +
'8738958337632249177044975686477011571044266'
).abs().toString(),
'4335932900105904896711358192862595934265493066663240086797820842922446' +
'49418901907515982293057185872800948523748982913862689675614187389583' +
'37632249177044975686477011571044266'
)
t.deepEqual(
BigNum(
'-43359329001059048967113581928625959342654930666632400867978208429' +
'2244649418901907515982293057185872800948523748982913862689675614' +
'18738958337632249177044975686477011571044266'
).abs().toString(),
'4335932900105904896711358192862595934265493066663240086797820842922446' +
'49418901907515982293057185872800948523748982913862689675614187389583' +
'37632249177044975686477011571044266'
)
t.end()
})
test('neg', { timeout: 120000 }, function (t) {
t.deepEqual(
BigNum(
'433593290010590489671135819286259593426549306666324008679782084292' +
'2446494189019075159822930571858728009485237489829138626896756141' +
'8738958337632249177044975686477011571044266'
).neg().toString(),
'-433593290010590489671135819286259593426549306666324008679782084292244' +
'64941890190751598229305718587280094852374898291386268967561418738958' +
'337632249177044975686477011571044266'
)
t.deepEqual(
BigNum(
'-43359329001059048967113581928625959342654930666632400867978208429' +
'2244649418901907515982293057185872800948523748982913862689675614' +
'18738958337632249177044975686477011571044266'
).neg().toString(),
'4335932900105904896711358192862595934265493066663240086797820842922446' +
'49418901907515982293057185872800948523748982913862689675614187389583' +
'37632249177044975686477011571044266'
)
t.end()
})
test('mod', { timeout: 120000 }, function (t) {
for (var i = 0; i < 10; i++) {
for (var j = 0; j < 10; j++) {
var js = j.toString()
if (!isNaN(i % j)) {
var ks = (i % j).toString()
t.deepEqual(BigNum(i).mod(j).toString(), ks)
t.deepEqual(BigNum(i).mod(js).toString(), ks)
t.deepEqual(BigNum(i).mod(BigNum(j)).toString(), ks)
t.deepEqual(BigNum.mod(i, j).toString(), ks)
}
}
}
t.deepEqual(
BigNum('486541542410442549118519277483401413')
.mod('1802185856709793916115771381388554')
.toString()
, '1753546955507985683376775889880387'
)
t.end()
})
test('cmp', { timeout: 120000 }, function (t) {
for (var i = -10; i <= 10; i++) {
var bi = BigNum(i)
for (var j = -10; j <= 10; j++) {
[j, BigNum(j)].forEach(function (jj) {
t.deepEqual(bi.lt(jj), i < j)
t.deepEqual(bi.le(jj), i <= j)
t.deepEqual(bi.eq(jj), i === j)
t.deepEqual(bi.ne(jj), i !== j)
t.deepEqual(bi.gt(jj), i > j)
t.deepEqual(bi.ge(jj), i >= j)
})
}
}
t.end()
})
test('powm', { timeout: 120000 }, function (t) {
var twos = [2, '2', BigNum(2), BigNum('2')]
var tens = [100000, '100000', BigNum(100000), BigNum(100000)]
twos.forEach(function (two) {
tens.forEach(function (ten) {
t.deepEqual(
BigNum('111111111').powm(two, ten).toString(),
'54321'
)
})
})
t.deepEqual(
BigNum('624387628734576238746587435')
.powm(2732, '457676874367586')
.toString()
, '335581885073251'
)
t.end()
})
test('pow', { timeout: 120000 }, function (t) {
[2, '2', BigNum(2), BigNum('2')].forEach(function (two) {
t.deepEqual(
BigNum('111111111').pow(two).toString(),
'12345678987654321'
)
})
t.deepEqual(
BigNum('3487438743234789234879').pow(22).toString(),
'861281136448465709000943928980299119292959327175552412961995332536782980636409994680542395362634321718164701236369695670918217801815161694902810780084448291245512671429670376051205638247649202527956041058237646154753587769450973231275642223337064356190945030999709422512682440247294915605076918925272414789710234097768366414400280590151549041536921814066973515842848197905763447515344747881160891303219471850554054186959791307149715821010152303317328860351766337716947079041'
)
t.end()
})
test('and', { timeout: 120000 }, function (t) {
for (var i = 0; i < 256; i += 7) {
for (var j = 0; j < 256; j += 7) {
var js = j.toString()
var ks = (i & j).toString()
t.deepEqual(BigNum(i).and(j).toString(), ks)
t.deepEqual(BigNum(i).and(js).toString(), ks)
t.deepEqual(BigNum(i).and(BigNum(j)).toString(), ks)
t.deepEqual(BigNum.and(i, j).toString(), ks)
t.deepEqual(BigNum(-1 * i).and(j).toString(), ((-1 * i) & j).toString())
t.deepEqual(BigNum(i).and(-1 * j).toString(), (i & (-1 * j)).toString())
t.deepEqual(BigNum(-1 * i).and(-1 * j).toString(), ((-1 * i) & (-1 * j)).toString())
}
}
t.deepEqual(BigNum.and(BigNum('111111', 16), BigNum('111111', 16)).toString(16), '111111')
t.deepEqual(BigNum.and(BigNum('111110', 16), BigNum('111111', 16)).toString(16), '111110')
t.deepEqual(BigNum.and(BigNum('111112', 16), BigNum('111111', 16)).toString(16), '111110')
t.deepEqual(BigNum.and(BigNum('111121', 16), BigNum('111111', 16)).toString(16), '111101')
t.deepEqual(BigNum.and(BigNum('111131', 16), BigNum('111111', 16)).toString(16), '111111')
t.deepEqual(BigNum.and(BigNum('-111111', 16), BigNum('111111', 16)).toString(16), '01')
t.deepEqual(BigNum.and(BigNum('111111', 16), BigNum('-111111', 16)).toString(16), '01')
t.deepEqual(BigNum.and(BigNum('-111111', 16), BigNum('-111111', 16)).toString(16), '-111111')
t.end()
})
test('or', { timeout: 120000 }, function (t) {
for (var i = 0; i < 256; i += 7) {
for (var j = 0; j < 256; j += 7) {
var js = j.toString()
var ks = (i | j).toString()
t.deepEqual(BigNum(i).or(j).toString(), ks)
t.deepEqual(BigNum(i).or(js).toString(), ks)
t.deepEqual(BigNum(i).or(BigNum(j)).toString(), ks)
t.deepEqual(BigNum.or(i, j).toString(), ks)
t.deepEqual(BigNum(-1 * i).or(j).toString(), ((-1 * i) | j).toString())
t.deepEqual(BigNum(i).or(-1 * j).toString(), (i | (-1 * j)).toString())
t.deepEqual(BigNum(-1 * i).or(-1 * j).toString(), ((-1 * i) | (-1 * j)).toString())
}
}
t.deepEqual(BigNum.or(BigNum('111111', 16), BigNum('111111', 16)).toString(16), '111111')
t.deepEqual(BigNum.or(BigNum('111110', 16), BigNum('111111', 16)).toString(16), '111111')
t.deepEqual(BigNum.or(BigNum('111112', 16), BigNum('111111', 16)).toString(16), '111113')
t.deepEqual(BigNum.or(BigNum('111121', 16), BigNum('111111', 16)).toString(16), '111131')
t.deepEqual(BigNum.or(BigNum('-111111', 16), BigNum('111111', 16)).toString(16), '-01')
t.deepEqual(BigNum.or(BigNum('111111', 16), BigNum('-111111', 16)).toString(16), '-01')
t.deepEqual(BigNum.or(BigNum('-111111', 16), BigNum('-111111', 16)).toString(16), '-111111')
t.end()
})
test('xor', { timeout: 120000 }, function (t) {
for (var i = 0; i < 256; i += 7) {
for (var j = 0; j < 256; j += 7) {
var js = j.toString()
var ks = (i ^ j).toString()
t.deepEqual(BigNum(i).xor(j).toString(), ks)
t.deepEqual(BigNum(i).xor(js).toString(), ks)
t.deepEqual(BigNum(i).xor(BigNum(j)).toString(), ks)
t.deepEqual(BigNum.xor(i, j).toString(), ks)
t.deepEqual(BigNum(-1 * i).xor(j).toString(), ((-1 * i) ^ j).toString())
t.deepEqual(BigNum(i).xor(-1 * j).toString(), (i ^ (-1 * j)).toString())
t.deepEqual(BigNum(-1 * i).xor(-1 * j).toString(), ((-1 * i) ^ (-1 * j)).toString())
}
}
t.deepEqual(BigNum.xor(BigNum('111111', 16), BigNum('111111', 16)).toString(), 0)
t.deepEqual(BigNum.xor(BigNum('111110', 16), BigNum('111111', 16)).toString(), 1)
t.deepEqual(BigNum.xor(BigNum('111112', 16), BigNum('111111', 16)).toString(), 3)
t.deepEqual(BigNum.xor(BigNum('111121', 16), BigNum('111111', 16)).toString(), 0x30)
t.deepEqual(BigNum.xor(BigNum('-111111', 16), BigNum('111111', 16)).toString(), -2)
t.deepEqual(BigNum.xor(BigNum('111111', 16), BigNum('-111111', 16)).toString(), -2)
t.deepEqual(BigNum.xor(BigNum('-111111', 16), BigNum('-111111', 16)).toString(), 0)
t.end()
})
test('rand', { timeout: 120000 }, function (t) {
for (var i = 1; i < 1000; i++) {
var x = BigNum(i).rand().toNumber()
t.ok(x >= 0 && x < i)
var y = BigNum(i).rand(i + 10).toNumber()
t.ok(i <= y && y < i + 10)
var z = BigNum.rand(i, i + 10).toNumber()
t.ok(i <= z && z < i + 10)
}
t.end()
})
test('primes', { timeout: 120000 }, function (t) {
var ps = { 2: true, 3: true, 5: true, 7: true }
for (var i = 0; i <= 10; i++) {
t.deepEqual(BigNum(i).probPrime(), Boolean(ps[i]))
}
var ns = {
2: 3,
3: 5,
15313: 15319,
222919: 222931,
611939: 611951,
334214459: '334214467',
961748927: '961748941',
9987704933: '9987704953'
}
Object.keys(ns).forEach(function (n) {
t.deepEqual(
BigNum(n).nextPrime().toString(),
ns[n].toString()
)
})
var uniques = [
'3', '11', '37', '101', '9091', '9901', '333667', '909091', '99990001',
'999999000001', '9999999900000001', '909090909090909091',
'1111111111111111111', '11111111111111111111111',
'900900900900990990990991'
]
var wagstaff = [
'3', '11', '43', '683', '2731', '43691', '174763', '2796203',
'715827883', '2932031007403', '768614336404564651',
'201487636602438195784363', '845100400152152934331135470251',
'56713727820156410577229101238628035243'
]
var big = [
'4669523849932130508876392554713407521319117239637943224980015676156491',
'54875133386847519273109693154204970395475080920935355580245252923343305939004903',
'204005728266090048777253207241416669051476369216501266754813821619984472224780876488344279',
'2074722246773485207821695222107608587480996474721117292752992589912196684750549658310084416732550077',
'5628290459057877291809182450381238927697314822133923421169378062922140081498734424133112032854812293'
]
;[uniques, wagstaff, big].forEach(function (xs) {
xs.forEach(function (x) {
var p = BigNum(x).probPrime()
t.ok(p === true || p === 'maybe')
})
})
t.end()
})
test('isbitset', { timeout: 120000 }, function (t) {
function mkbin (bn) {
var bin = ''
for (var i = 0; i < bn.bitLength(); ++i) {
bin += bn.isBitSet(i) ? '1' : '0'
}
return bin
}
t.deepEqual(mkbin(BigNum(127)), '1111111')
t.deepEqual(mkbin(BigNum(-127)), '1111111')
t.deepEqual(mkbin(BigNum(128)), '00000001')
t.deepEqual(mkbin(BigNum(-128)), '00000001')
t.deepEqual(mkbin(BigNum(129)), '10000001')
t.deepEqual(mkbin(BigNum(-129)), '10000001')
t.end()
})
test('invertm', { timeout: 120000 }, function (t) {
// numbers from http://www.itl.nist.gov/fipspubs/fip186.htm appendix 5
var q = BigNum('b20db0b101df0c6624fc1392ba55f77d577481e5', 16)
var k = BigNum('79577ddcaafddc038b865b19f8eb1ada8a2838c6', 16)
var kinv = k.invertm(q)
t.deepEqual(kinv.toString(16), '2784e3d672d972a74e22c67f4f4f726ecc751efa')
t.end()
})
test('shift', { timeout: 120000 }, function (t) {
t.deepEqual(BigNum(37).shiftLeft(2).toString(), (37 << 2).toString()) // 148
t.deepEqual(BigNum(37).shiftRight(2).toString(), (37 >> 2).toString()) // 9
t.equal(
BigNum(2).pow(Math.pow(2, 10)).shiftRight(4).toString(),
BigNum(2).pow(Math.pow(2, 10)).div(16).toString()
)
t.end()
})
test('mod', { timeout: 120000 }, function (t) {
t.deepEqual(BigNum(55555).mod(2).toString(), '1')
t.deepEqual(
BigNum('1234567').mod(
BigNum('4321')
).toNumber(),
1234567 % 4321
)
t.end()
})
test('endian', { timeout: 120000 }, function (t) {
var a = BigNum(0x0102030405)
t.deepEqual(a.toBuffer({ endian: 'big', size: 2 }).toString('hex'), '000102030405')
t.deepEqual(a.toBuffer({ endian: 'little', size: 2 }).toString('hex'), '010003020504')
var b = BigNum(0x0102030405)
t.deepEqual(b.toBuffer({ endian: 'big', size: 'auto' }).toString('hex'), '0102030405')
t.deepEqual(b.toBuffer({ endian: 'little', size: 'auto' }).toString('hex'), '0504030201')
var c = Buffer.from('000102030405', 'hex')
t.deepEqual(BigNum.fromBuffer(c, { endian: 'big', size: 'auto' }).toString(16), '0102030405')
t.deepEqual(BigNum.fromBuffer(c, { endian: 'little', size: 'auto' }).toString(16), '050403020100')
t.end()
})
test('bitlength', { timeout: 120000 }, function (t) {
var bl = BigNum(
'433593290010590489671135819286259593426549306666324008679782084292' +
'2446494189019075159822930571858728009485237489829138626896756141' +
'873895833763224917704497568647701157104426'
).bitLength()
t.equal(bl > 0, true)
t.end()
})
test('gcd', { timeout: 120000 }, function (t) {
var b1 = BigNum('234897235923342343242')
var b2 = BigNum('234790237101762305340234')
var expected = BigNum('6')
t.equal(b1.gcd(b2).toString(), expected.toString())
t.end()
})
test('jacobi', { timeout: 120000 }, function (t) {
// test case from p. 134 of D. R. Stinson
var b1 = BigNum('7411')
var b2 = BigNum('9283')
t.equal(b1.jacobi(b2), -1)
// test case from p. 132 of D. R. Stinson
b1 = BigNum('6278')
b2 = BigNum('9975')
t.equal(b1.jacobi(b2), -1)
// test case from p. 74 of Men. Oorsh. Vans.
b1 = BigNum('158')
b2 = BigNum('235')
t.equal(b1.jacobi(b2), -1)
// test case from p. 216 of Kumanduri Romero
b1 = BigNum('4')
b2 = BigNum('7')
t.equal(b1.jacobi(b2), 1)
// test case from p. 363 of K. R. Rosen
b1 = BigNum('68')
b2 = BigNum('111')
t.equal(b1.jacobi(b2), 1)
t.end()
})
================================================
FILE: test/buf.js
================================================
var BigNum = require('../')
var put = require('put')
var test = require('tap').test
var Buffer = require('safe-buffer').Buffer
test('bufBe', function (t) {
var buf1 = Buffer.from([1, 2, 3, 4])
var num = BigNum.fromBuffer(buf1, { size: 4 }).toNumber()
t.deepEqual(
num,
1 * Math.pow(256, 3) +
2 * Math.pow(256, 2) +
3 * 256 +
4
)
var buf2 = put().word32be(num).buffer()
t.deepEqual(buf1, buf2,
'[ ' + [].slice.call(buf1) + ' ] != [ ' + [].slice.call(buf2) + ' ]'
)
t.end()
})
test('bufLe', function (t) {
var buf1 = Buffer.from([1, 2, 3, 4])
var num = BigNum
.fromBuffer(buf1, { size: 4, endian: 'little' })
.toNumber()
var buf2 = put().word32le(num).buffer()
t.deepEqual(buf1, buf2,
'[ ' + [].join.call(buf1, ',') + ' ] != [ ' + [].join.call(buf2, ',') + ' ]'
)
t.end()
})
test('bufBe_le', function (t) {
var bufBe = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8])
var bufLe = Buffer.from([4, 3, 2, 1, 8, 7, 6, 5])
var numBe = BigNum
.fromBuffer(bufBe, { size: 4, endian: 'big' })
.toString()
var numLe = BigNum
.fromBuffer(bufLe, { size: 4, endian: 'little' })
.toString()
t.deepEqual(numBe, numLe)
t.end()
})
test('buf_high_bits', function (t) {
var bufBe = Buffer.from([
201, 202, 203, 204,
205, 206, 207, 208
])
var bufLe = Buffer.from([
204, 203, 202, 201,
208, 207, 206, 205
])
var numBe = BigNum
.fromBuffer(bufBe, { size: 4, endian: 'big' })
.toString()
var numLe = BigNum
.fromBuffer(bufLe, { size: 4, endian: 'little' })
.toString()
t.deepEqual(numBe, numLe)
t.end()
})
test('buf_to_from', function (t) {
var nums = [
0, 1, 10, 15, 3, 16,
7238, 1337, 31337, 505050,
'172389721984375328763297498273498732984324',
'32848432742',
'12988282841231897498217398217398127983721983719283721',
'718293798217398217312387213972198321'
]
nums.forEach(function (num) {
var b = BigNum(num)
var u = b.toBuffer()
t.ok(u)
t.deepEqual(
BigNum.fromBuffer(u).toString(),
b.toString()
)
})
t.throws(function () {
BigNum(-1).toBuffer() // can't pack negative numbers yet
})
t.end()
})
test('toBuf', function (t) {
var buf = Buffer.from([0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f])
var b = BigNum(
0x0a * 256 * 256 * 256 * 256 * 256 +
0x0b * 256 * 256 * 256 * 256 +
0x0c * 256 * 256 * 256 +
0x0d * 256 * 256 +
0x0e * 256 +
0x0f
)
t.deepEqual(b.toString(16), '0a0b0c0d0e0f')
t.deepEqual(
[].slice.call(b.toBuffer({ endian: 'big', size: 2 })),
[0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f]
)
t.deepEqual(
[].slice.call(b.toBuffer({ endian: 'little', size: 2 })),
[0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e]
)
t.deepEqual(
BigNum.fromBuffer(buf).toString(16),
b.toString(16)
)
t.deepEqual(
[].slice.call(BigNum(43135012110).toBuffer({
endian: 'little', size: 4
})),
[0x0a, 0x00, 0x00, 0x00, 0x0e, 0x0d, 0x0c, 0x0b]
)
t.deepEqual(
[].slice.call(BigNum(43135012110).toBuffer({
endian: 'big', size: 4
})),
[0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e]
)
t.end()
})
test('zeroPad', function (t) {
var b = BigNum(0x123456)
t.deepEqual(
[].slice.call(b.toBuffer({ endian: 'big', size: 4 })),
[0x00, 0x12, 0x34, 0x56]
)
t.deepEqual(
[].slice.call(b.toBuffer({ endian: 'little', size: 4 })),
[0x56, 0x34, 0x12, 0x00]
)
t.end()
})
test('toMpint', function (t) {
// test values taken directly out of
// http://tools.ietf.org/html/rfc4251#page-10
var refs = {
0: Buffer.from([0x00, 0x00, 0x00, 0x00]),
'9a378f9b2e332a7': Buffer.from([
0x00, 0x00, 0x00, 0x08,
0x09, 0xa3, 0x78, 0xf9,
0xb2, 0xe3, 0x32, 0xa7
]),
80: Buffer.from([0x00, 0x00, 0x00, 0x02, 0x00, 0x80]),
'-1234': Buffer.from([0x00, 0x00, 0x00, 0x02, 0xed, 0xcc]),
'-deadbeef': Buffer.from([0x00, 0x00, 0x00, 0x05, 0xff, 0x21, 0x52, 0x41, 0x11])
}
Object.keys(refs).forEach(function (key) {
var buf0 = BigNum(key, 16).toBuffer('mpint')
var buf1 = refs[key]
t.deepEqual(
buf0, buf1,
buf0.inspect() + ' != ' + buf1.inspect() + ' for BigNum(' + key + ')'
)
})
t.end()
})
================================================
FILE: test/gh52.js
================================================
var BigNum = require('../')
var test = require('tap').test
test('github52', function (t) {
// verify that numbers aren't truncated to 32 bits when running on
// 32-bit platforms (where the OpenSSL sizeof(BN_ULONG) is 32 bits)
var num = new BigNum(0x100000000)
t.equal(num.toString(), '4294967296')
t.equal(num.add(0x100000000).toString(), '8589934592')
t.equal(num.sub(0x100000001).toString(), '-1')
t.equal(num.mul(0x100000000).toString().toString(), '18446744073709551616')
t.equal(num.div(0x100000002).toString(), '0')
t.equal(num.mod(0x100000002).toString(), '4294967296')
num = new BigNum(2)
t.equal(num.powm(0x100000001, 4).toString(), '0')
num = new BigNum(-0x100000000)
t.ok(num.cmp(-0x100000000) === 0)
num = new BigNum(0x100000000)
t.ok(num.cmp(0x100000000) === 0)
t.end()
})
================================================
FILE: test/isbignum.js
================================================
var BigNum = require('../')
var test = require('tap').test
test('create', function (t) {
var validBn = BigNum('42')
var testObj
testObj = BigNum('123')
t.equal(BigNum.isBigNum(testObj), true)
testObj = {}
t.equal(BigNum.isBigNum(testObj), false)
testObj = {}
t.throws(function () {
validBn.add(testObj)
})
testObj = falsePositive()
t.equal(BigNum.isBigNum(testObj), true)
// this causes a hard crash, so its disabled for now
// testObj = falsePositive()
// t.throws(function() {
// validBn.add(testObj)
// })
t.end()
})
function falsePositive () {
var obj = {}
for (var key in BigNum.prototype) {
obj[key] = true
}
return obj
}
================================================
FILE: test/seed.js
================================================
// skip on Windows for now, this doesn't work
if (process.platform === 'win32') {
process.exit(0)
}
var path = require('path')
var execFile = require('child_process').execFile
var test = require('tap').test
test('rand', function (t) {
var to = setTimeout(function () {
t.fail('never executed')
}, 5000)
var args = [
'-p',
'require("' + path.join(__dirname, '..') + '").rand(1000).toString()'
]
execFile(process.execPath, args, function (err1, r1) {
execFile(process.execPath, args, function (err2, r2) {
clearTimeout(to)
t.ifError(err1)
t.ifError(err2)
t.ok(
r1.match(/^\d+[\r\n]+/),
JSON.stringify(r1) + ' is not an integer'
)
t.ok(
r2.match(/^\d+[\r\n]+/),
JSON.stringify(r2) + ' is not an integer'
)
var n1 = parseInt(r1.split(/[\r\n]+/)[0], 10)
var n2 = parseInt(r2.split(/[\r\n]+/)[0], 10)
t.ok(n1 >= 0, 'n1 >= 0')
t.ok(n2 >= 0, 'n2 >= 0')
t.ok(n1 < 1000, 'n1 < 1000')
t.ok(n2 < 1000, 'n2 < 1000')
t.ok(n1 !== n2, 'n1 != n2')
t.end()
})
})
})
================================================
FILE: test/wincrash.js
================================================
var BigNum = require('../')
var test = require('tap').test
test('windowsCrash', function (t) {
var num = new BigNum(1234)
t.equal(num.toString(), '1234')
t.end()
})
gitextract_0bfbdiwo/
├── .dntrc
├── .github/
│ └── workflows/
│ └── main.yml
├── .gitignore
├── .npmignore
├── README.markdown
├── appveyor.yml
├── bignum.cc
├── binding.gyp
├── examples/
│ ├── gen.js
│ ├── perfect.js
│ └── simple.js
├── index.js
├── package.json
└── test/
├── big.js
├── buf.js
├── gh52.js
├── isbignum.js
├── seed.js
└── wincrash.js
SYMBOL INDEX (52 symbols across 3 files)
FILE: bignum.cc
class AutoBN_CTX (line 75) | class AutoBN_CTX
method BN_CTX (line 79) | BN_CTX* operator=(BN_CTX* ctx_new) { return ctx = ctx_new; }
method AutoBN_CTX (line 82) | AutoBN_CTX()
method BN_CTX (line 95) | BN_CTX& operator*() { return *ctx; }
method BN_CTX (line 96) | BN_CTX** operator&() { return &ctx; }
function BN_jacobi_priv (line 115) | int BN_jacobi_priv(const BIGNUM *A,const BIGNUM *N,int *jacobi,
class BigNum (line 183) | class BigNum : public Nan::ObjectWrap {
function NAN_METHOD (line 378) | NAN_METHOD(BigNum::New)
function NAN_METHOD (line 436) | NAN_METHOD(BigNum::ToString)
function NAN_METHOD (line 465) | NAN_METHOD(BigNum::Badd)
function NAN_METHOD (line 479) | NAN_METHOD(BigNum::Bsub)
function NAN_METHOD (line 492) | NAN_METHOD(BigNum::Bmul)
function NAN_METHOD (line 506) | NAN_METHOD(BigNum::Bdiv)
function NAN_METHOD (line 520) | NAN_METHOD(BigNum::Uadd)
function NAN_METHOD (line 538) | NAN_METHOD(BigNum::Usub)
function NAN_METHOD (line 556) | NAN_METHOD(BigNum::Umul)
function NAN_METHOD (line 575) | NAN_METHOD(BigNum::Udiv)
function NAN_METHOD (line 594) | NAN_METHOD(BigNum::Umul_2exp)
function NAN_METHOD (line 607) | NAN_METHOD(BigNum::Udiv_2exp)
function NAN_METHOD (line 620) | NAN_METHOD(BigNum::Babs)
function NAN_METHOD (line 632) | NAN_METHOD(BigNum::Bneg)
function NAN_METHOD (line 644) | NAN_METHOD(BigNum::Bmod)
function NAN_METHOD (line 658) | NAN_METHOD(BigNum::Umod)
function NAN_METHOD (line 677) | NAN_METHOD(BigNum::Bpowm)
function NAN_METHOD (line 692) | NAN_METHOD(BigNum::Upowm)
function NAN_METHOD (line 709) | NAN_METHOD(BigNum::Upow)
function NAN_METHOD (line 725) | NAN_METHOD(BigNum::Brand0)
function NAN_METHOD (line 738) | NAN_METHOD(BigNum::Uprime0)
function NAN_METHOD (line 752) | NAN_METHOD(BigNum::Probprime)
function NAN_METHOD (line 762) | NAN_METHOD(BigNum::IsBitSet)
function NAN_METHOD (line 771) | NAN_METHOD(BigNum::Bcompare)
function NAN_METHOD (line 780) | NAN_METHOD(BigNum::Scompare)
function NAN_METHOD (line 791) | NAN_METHOD(BigNum::Ucompare)
function mpi2twosComplement (line 813) | static void
function twos_complement2mpi (line 832) | static void
function shiftSizeAndMSB (line 855) | static void
function isMinimumNegativeNumber (line 869) | static bool
function swapEndianness (line 885) | static void
function NAN_METHOD (line 1014) | NAN_METHOD(BigNum::Band)
function NAN_METHOD (line 1019) | NAN_METHOD(BigNum::Bor)
function NAN_METHOD (line 1024) | NAN_METHOD(BigNum::Bxor)
function NAN_METHOD (line 1029) | NAN_METHOD(BigNum::Binvertm)
function NAN_METHOD (line 1043) | NAN_METHOD(BigNum::Bsqrt)
function NAN_METHOD (line 1048) | NAN_METHOD(BigNum::Broot)
function NAN_METHOD (line 1053) | NAN_METHOD(BigNum::BitLength)
function NAN_METHOD (line 1063) | NAN_METHOD(BigNum::Bgcd)
function NAN_METHOD (line 1077) | NAN_METHOD(BigNum::Bjacobi)
function NAN_METHOD (line 1093) | NAN_METHOD(BigNum::Bsetcompact)
function NAN_METHOD (line 1116) | static NAN_METHOD(SetJSConditioner)
function init (line 1125) | void
FILE: test/big.js
function mkbin (line 450) | function mkbin (bn) {
FILE: test/isbignum.js
function falsePositive (line 31) | function falsePositive () {
Condensed preview — 19 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (86K chars).
[
{
"path": ".dntrc",
"chars": 523,
"preview": "## DNT config file\n## see https://github.com/rvagg/dnt\n\nNODE_VERSIONS=\"\\\n v0.10.40 \\\n v0.12.7 \\\n\"\nIOJS_VERSIO"
},
{
"path": ".github/workflows/main.yml",
"chars": 629,
"preview": "name: CI\n\non: [push, pull_request]\n\njobs:\n build:\n\n runs-on: ${{ matrix.os }}\n\n strategy:\n matrix:\n o"
},
{
"path": ".gitignore",
"chars": 130,
"preview": "# Files\n.lock-wscript\npackage-lock.json\n\n# Filetypes\n.*.swp\n\n# Paths\n/build\n/node_modules\n/coverage\n/binding\n/.nyc_outpu"
},
{
"path": ".npmignore",
"chars": 141,
"preview": ".lock-wscript\n.travis.yml\nappveyor.yml\n.dntrc\n.*.swp\npre-gyp-publish.sh\nbuild\nnode_modules\ncoverage\nbinding\n.nyc_output\n"
},
{
"path": "README.markdown",
"chars": 7073,
"preview": "bignum\n======\n\n[](https://github.com/just"
},
{
"path": "appveyor.yml",
"chars": 2121,
"preview": "environment:\n node_pre_gyp_accessKeyId:\n secure: EXM80HyHBdjKthrNyOlVa/8KKy7m5TdzTtGw0JmnaTs=\n node_pre_gyp_secretA"
},
{
"path": "bignum.cc",
"chars": 30463,
"preview": "#include <stdint.h>\n#include <cstdio>\n#include <cstdlib>\n#include <cstring>\n#include <algorithm>\n#include <iostream>\n\n#i"
},
{
"path": "binding.gyp",
"chars": 2498,
"preview": "{\n 'targets': [\n {\n 'target_name': 'bignum',\n 'sources': [ 'bignum.cc' ],\n 'include_dirs': [\n "
},
{
"path": "examples/gen.js",
"chars": 923,
"preview": "// Generate two primes p and q to the Digital Signature Standard (DSS)\n// http://www.itl.nist.gov/fipspubs/fip186.htm ap"
},
{
"path": "examples/perfect.js",
"chars": 268,
"preview": "// If 2**n-1 is prime, then (2**n-1) * 2**(n-1) is perfect.\nvar bignum = require('../')\n\nfor (var n = 0; n < 100; n++) {"
},
{
"path": "examples/simple.js",
"chars": 151,
"preview": "var bignum = require('../')\n\nvar b = bignum('782910138827292261791972728324982')\n .sub('1823732732834021712374747747283"
},
{
"path": "index.js",
"chars": 9172,
"preview": "var bin = require('bindings')('bignum')\nvar Buffer = require('safe-buffer').Buffer\nvar BigNum = bin.BigNum\n\nmodule.expor"
},
{
"path": "package.json",
"chars": 915,
"preview": "{\n \"name\": \"bignum\",\n \"version\": \"0.13.1\",\n \"description\": \"Arbitrary-precision integer arithmetic using OpenSSL\",\n "
},
{
"path": "test/big.js",
"chars": 19247,
"preview": "var Buffer = require('safe-buffer').Buffer\nvar BigNum = require('../')\nvar test = require('tap').test\n\ntest('create', { "
},
{
"path": "test/buf.js",
"chars": 4248,
"preview": "var BigNum = require('../')\nvar put = require('put')\nvar test = require('tap').test\nvar Buffer = require('safe-buffer')."
},
{
"path": "test/gh52.js",
"chars": 820,
"preview": "var BigNum = require('../')\nvar test = require('tap').test\n\ntest('github52', function (t) {\n // verify that numbers are"
},
{
"path": "test/isbignum.js",
"chars": 690,
"preview": "var BigNum = require('../')\nvar test = require('tap').test\n\ntest('create', function (t) {\n var validBn = BigNum('42')\n "
},
{
"path": "test/seed.js",
"chars": 1114,
"preview": "// skip on Windows for now, this doesn't work\nif (process.platform === 'win32') {\n process.exit(0)\n}\n\nvar path = requir"
},
{
"path": "test/wincrash.js",
"chars": 173,
"preview": "var BigNum = require('../')\nvar test = require('tap').test\n\ntest('windowsCrash', function (t) {\n var num = new BigNum(1"
}
]
About this extraction
This page contains the full source code of the justmoon/node-bignum GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 19 files (79.4 KB), approximately 26.8k tokens, and a symbol index with 52 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.