diff --git a/lib/BigNumber.js b/lib/BigNumber.js deleted file mode 100644 index 8423f5d..0000000 --- a/lib/BigNumber.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -const { jsbn: { BigInteger } } = require('node-forge'); - -class BigNumber { - constructor(value, radix = 10) { - if (value === null || value === undefined) - throw new Error('value is missing.'); - - this._n = new BigInteger(null); - - if (value instanceof BigNumber) - this._n = value._n; - else if (value instanceof BigInteger) - this._n = value; - else if (typeof value === 'number') - this._n.fromInt(value); - else if (typeof value === 'string') - this._n.fromString(value, radix); - else if (Buffer.isBuffer(value)) - this._n.fromString(value.toString('hex'), 16); - else if (Array.isArray(value)) - this._n.fromString(Buffer.from(value).toString('hex'), 16); - else - throw new TypeError('Unsupported value type.'); - } - - toBEBuffer(length = undefined) { - const arr = this._n.toByteArray(); - if (length && arr.length > length) - throw new Error('Number out of range.'); - while (arr.length < length) - arr.unshift(0); - return Buffer.from(arr); - } - - toBuffer() { - return Buffer.from(this._n.toByteArray()); - } - - toString(radix = 10) { - return this._n.toString(radix); - } - - and(num) { - return new BigNumber(this._n.and(new BigNumber(num)._n)); - } - - mul(num) { - return new BigNumber(this._n.multiply(new BigNumber(num)._n)); - } - - mod(num) { - return new BigNumber(this._n.mod(new BigNumber(num)._n)); - } - - shrn(num) { - return new BigNumber(this._n.shiftRight(new BigNumber(num)._n)); - } - - static fromBuffer(buf) { - return new BigNumber(buf.toString('hex'), 16); - } -} - -module.exports = BigNumber; diff --git a/test/unit/BigNumber.js b/test/unit/BigNumber.js new file mode 100644 index 0000000..0b95bca --- /dev/null +++ b/test/unit/BigNumber.js @@ -0,0 +1,48 @@ +'use strict'; + +/* eslint-env node, mocha */ + +const { assert } = require('chai'); +const { jsbn: { BigInteger } } = require('node-forge'); + +const BigNumber = require('../../lib/crypto/BigNumber'); + +const types = [ + { name: 'BigNumber', value: new BigNumber(11) }, + { name: 'BigInteger', value: new BigInteger('11') }, + { name: 'string with default radix', value: '11' }, + { name: 'string with radix 16', value: '0b', radix: 16 }, + { name: 'Buffer', value: Buffer.from('0b', 'hex') }, + { name: 'Array', value: [11] }, +]; + +describe('BigNumber', () => { + describe('creating an instance', () => { + it('should throw with no value given', () => assert.throws(() => new BigNumber())); + it('should throw wrong value type', () => assert.throws(() => new BigNumber({}))); + + for (const { name, value, radix } of types) { + let instance; + describe(`out of ${name}`, () => { + it('create instance', () => assert.doesNotThrow(() => { + instance = new BigNumber(value, radix); + })); + it('toString with radix 10', () => assert.equal(instance.toString(), '11')); + it('toString with radix 16', () => assert.equal(instance.toString(16), '0b')); + it('toBuffer', () => assert.equal(instance.toBuffer().toString('hex'), '0b')); + it('toBEBuffer without length', () => assert.equal(instance.toBEBuffer().toString('hex'), '0b')); + it('toBEBuffer with length', () => assert.equal(instance.toBEBuffer(4).toString('hex'), '0000000b')); + }); + } + }); + describe('exports', () => { + it('toBEBuffer with too short length should throw', () => assert.throw(() => new BigNumber(837462187362).toBEBuffer(1))); + }); + describe('operators', () => { + const num = new BigNumber(1); + it('and', () => assert.equal(num.and(1), 1)); + it('mul', () => assert.equal(num.mul(2), 2)); + it('mod', () => assert.equal(num.mod(1), 0)); + it('shrn', () => assert.equal(num.shrn(1), 0)); + }); +});