2018-06-01 13:16:43 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const crypto = require('crypto');
|
2019-11-06 15:16:56 +00:00
|
|
|
|
|
|
|
const BigNumber = require('../BigNumber.js');
|
2018-06-01 13:16:43 +00:00
|
|
|
|
|
|
|
const MFG_LEN = 32;
|
|
|
|
|
|
|
|
const divceil = (a, b) => ~~(((a + b) - 1) / b); // eslint-disable-line no-bitwise
|
2019-11-06 15:16:56 +00:00
|
|
|
const rjust = (string, width, padding = ' ') => {
|
2018-06-01 13:16:43 +00:00
|
|
|
padding = padding.substr(0, 1);
|
|
|
|
if (string.length < width)
|
|
|
|
return padding.repeat(width - string.length) + string;
|
|
|
|
return string;
|
|
|
|
};
|
|
|
|
const xor = (a, b) => {
|
|
|
|
if (a.length !== b.length)
|
|
|
|
throw new Error('Different length for a and b');
|
|
|
|
|
|
|
|
for (let i = 0; i < a.length; i++)
|
|
|
|
a[i] ^= b[i]; // eslint-disable-line no-bitwise
|
|
|
|
|
|
|
|
return a;
|
|
|
|
};
|
|
|
|
const i2osp = (x, len) => {
|
|
|
|
if (x >= 256 ** len)
|
|
|
|
throw new Error('Integer too large');
|
|
|
|
|
2019-11-06 15:16:56 +00:00
|
|
|
return Buffer.from(rjust(new BigNumber(x).toBEBuffer(4).toString().replace(/\x00/gi, ''), len, '\x00')); // eslint-disable-line no-control-regex
|
2018-06-01 13:16:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
generate(seed, masklen) {
|
|
|
|
if (masklen > 4294967296 * MFG_LEN)
|
2018-05-31 08:29:00 +00:00
|
|
|
throw new Error('Mask too long');
|
|
|
|
|
|
|
|
|
2018-06-01 13:16:43 +00:00
|
|
|
const b = [];
|
2018-05-31 08:29:00 +00:00
|
|
|
|
2018-06-01 13:16:43 +00:00
|
|
|
for (let i = 0; i < divceil(masklen, MFG_LEN); i++)
|
|
|
|
b[i] = crypto.createHash('sha256').update(Buffer.concat([seed, i2osp(i, 4)])).digest();
|
2018-05-31 08:29:00 +00:00
|
|
|
|
|
|
|
|
2018-06-01 13:16:43 +00:00
|
|
|
return (Buffer.concat(b)).slice(0, masklen);
|
|
|
|
},
|
|
|
|
xor,
|
|
|
|
rjust,
|
|
|
|
};
|