diff --git a/lib/crypto/BigNumber.js b/lib/crypto/BigNumber.js new file mode 100644 index 0000000..fda2e84 --- /dev/null +++ b/lib/crypto/BigNumber.js @@ -0,0 +1,65 @@ +'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 (length && arr.length < length) + arr.unshift(0); + return Buffer.from(arr); + } + + toBuffer() { + return Buffer.from(this._n.toByteArray()); + } + + toString(radix = 10) { + const result = this._n.toString(radix); + if (radix === 16) + return result.padStart(2, '0'); + return result; + } + + 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)); + } +} + +module.exports = BigNumber; diff --git a/lib/crypto/Crypto.js b/lib/crypto/Crypto.js index 7a6db0e..a39fd75 100644 --- a/lib/crypto/Crypto.js +++ b/lib/crypto/Crypto.js @@ -2,7 +2,7 @@ const crypto = require('crypto'); -const BigNumber = require('../BigNumber.js'); +const BigNumber = require('./BigNumber.js'); const mgf1 = require('./MGF1'); const modPow = (base, power, mod) => { @@ -27,7 +27,7 @@ const emsaPSS = (msg, salt) => { const dbMask = mgf1.generate(mTickHash, db.length); const maskedDb = mgf1.xor(db, dbMask); - let maskedDbMsb = mgf1.rjust(BigNumber.fromBuffer(maskedDb.slice(0, 1)).toString(2), 8, '0'); + let maskedDbMsb = mgf1.rjust(new BigNumber(maskedDb.slice(0, 1)).toString(2), 8, '0'); maskedDbMsb = `0${maskedDbMsb.substr(1)}`; diff --git a/lib/crypto/MGF1.js b/lib/crypto/MGF1.js index 0a7aeed..f986a5c 100644 --- a/lib/crypto/MGF1.js +++ b/lib/crypto/MGF1.js @@ -2,7 +2,7 @@ const crypto = require('crypto'); -const BigNumber = require('../BigNumber.js'); +const BigNumber = require('./BigNumber.js'); const MFG_LEN = 32;