mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
efe5b81df9
Start moving src/crypto functionality out to a separate dep that can be shared with other projects that need to emulate Node.js crypto behavior. PR-URL: https://github.com/nodejs/node/pull/53803 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
298 lines
7.7 KiB
JavaScript
298 lines
7.7 KiB
JavaScript
// Flags: --expose-internals
|
|
'use strict';
|
|
|
|
const common = require('../common');
|
|
if (!common.hasCrypto)
|
|
common.skip('missing crypto');
|
|
|
|
const assert = require('assert');
|
|
|
|
const {
|
|
generatePrime,
|
|
generatePrimeSync,
|
|
checkPrime,
|
|
checkPrimeSync,
|
|
} = require('crypto');
|
|
|
|
const { promisify } = require('util');
|
|
const pgeneratePrime = promisify(generatePrime);
|
|
const pCheckPrime = promisify(checkPrime);
|
|
|
|
['hello', false, {}, []].forEach((i) => {
|
|
assert.throws(() => generatePrime(i), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
assert.throws(() => generatePrimeSync(i), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
});
|
|
|
|
['hello', false, 123].forEach((i) => {
|
|
assert.throws(() => generatePrime(80, i, common.mustNotCall()), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
assert.throws(() => generatePrimeSync(80, i), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
});
|
|
|
|
['hello', false, 123].forEach((i) => {
|
|
assert.throws(() => generatePrime(80, {}), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
});
|
|
|
|
[-1, 0, 2 ** 31, 2 ** 31 + 1, 2 ** 32 - 1, 2 ** 32].forEach((size) => {
|
|
assert.throws(() => generatePrime(size, common.mustNotCall()), {
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: />= 1 && <= 2147483647/
|
|
});
|
|
assert.throws(() => generatePrimeSync(size), {
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: />= 1 && <= 2147483647/
|
|
});
|
|
});
|
|
|
|
['test', -1, {}, []].forEach((i) => {
|
|
assert.throws(() => generatePrime(8, { safe: i }, common.mustNotCall()), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
assert.throws(() => generatePrime(8, { rem: i }, common.mustNotCall()), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
assert.throws(() => generatePrime(8, { add: i }, common.mustNotCall()), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
assert.throws(() => generatePrimeSync(8, { safe: i }), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
assert.throws(() => generatePrimeSync(8, { rem: i }), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
assert.throws(() => generatePrimeSync(8, { add: i }), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
});
|
|
|
|
{
|
|
// Negative BigInts should not be converted to 0 silently.
|
|
|
|
assert.throws(() => generatePrime(20, { add: -1n }, common.mustNotCall()), {
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: 'The value of "options.add" is out of range. It must be >= 0. ' +
|
|
'Received -1n'
|
|
});
|
|
|
|
assert.throws(() => generatePrime(20, { rem: -1n }, common.mustNotCall()), {
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: 'The value of "options.rem" is out of range. It must be >= 0. ' +
|
|
'Received -1n'
|
|
});
|
|
|
|
assert.throws(() => checkPrime(-1n, common.mustNotCall()), {
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: 'The value of "candidate" is out of range. It must be >= 0. ' +
|
|
'Received -1n'
|
|
});
|
|
}
|
|
|
|
generatePrime(80, common.mustSucceed((prime) => {
|
|
assert(checkPrimeSync(prime));
|
|
checkPrime(prime, common.mustSucceed((result) => {
|
|
assert(result);
|
|
}));
|
|
}));
|
|
|
|
assert(checkPrimeSync(generatePrimeSync(80)));
|
|
|
|
generatePrime(80, {}, common.mustSucceed((prime) => {
|
|
assert(checkPrimeSync(prime));
|
|
}));
|
|
|
|
assert(checkPrimeSync(generatePrimeSync(80, {})));
|
|
|
|
generatePrime(32, { safe: true }, common.mustSucceed((prime) => {
|
|
assert(checkPrimeSync(prime));
|
|
const buf = Buffer.from(prime);
|
|
const val = buf.readUInt32BE();
|
|
const check = (val - 1) / 2;
|
|
buf.writeUInt32BE(check);
|
|
assert(checkPrimeSync(buf));
|
|
}));
|
|
|
|
{
|
|
const prime = generatePrimeSync(32, { safe: true });
|
|
assert(checkPrimeSync(prime));
|
|
const buf = Buffer.from(prime);
|
|
const val = buf.readUInt32BE();
|
|
const check = (val - 1) / 2;
|
|
buf.writeUInt32BE(check);
|
|
assert(checkPrimeSync(buf));
|
|
}
|
|
|
|
const add = 12;
|
|
const rem = 11;
|
|
const add_buf = Buffer.from([add]);
|
|
const rem_buf = Buffer.from([rem]);
|
|
generatePrime(
|
|
32,
|
|
{ add: add_buf, rem: rem_buf },
|
|
common.mustSucceed((prime) => {
|
|
assert(checkPrimeSync(prime));
|
|
const buf = Buffer.from(prime);
|
|
const val = buf.readUInt32BE();
|
|
assert.strictEqual(val % add, rem);
|
|
}));
|
|
|
|
{
|
|
const prime = generatePrimeSync(32, { add: add_buf, rem: rem_buf });
|
|
assert(checkPrimeSync(prime));
|
|
const buf = Buffer.from(prime);
|
|
const val = buf.readUInt32BE();
|
|
assert.strictEqual(val % add, rem);
|
|
}
|
|
|
|
{
|
|
const prime = generatePrimeSync(32, { add: BigInt(add), rem: BigInt(rem) });
|
|
assert(checkPrimeSync(prime));
|
|
const buf = Buffer.from(prime);
|
|
const val = buf.readUInt32BE();
|
|
assert.strictEqual(val % add, rem);
|
|
}
|
|
|
|
{
|
|
// The behavior when specifying only add without rem should depend on the
|
|
// safe option.
|
|
|
|
if (process.versions.openssl >= '1.1.1f') {
|
|
generatePrime(128, {
|
|
bigint: true,
|
|
add: 5n
|
|
}, common.mustSucceed((prime) => {
|
|
assert(checkPrimeSync(prime));
|
|
assert.strictEqual(prime % 5n, 1n);
|
|
}));
|
|
|
|
generatePrime(128, {
|
|
bigint: true,
|
|
safe: true,
|
|
add: 5n
|
|
}, common.mustSucceed((prime) => {
|
|
assert(checkPrimeSync(prime));
|
|
assert.strictEqual(prime % 5n, 3n);
|
|
}));
|
|
}
|
|
}
|
|
|
|
{
|
|
// This is impossible because it implies (prime % 2**64) == 1 and
|
|
// prime < 2**64, meaning prime = 1, but 1 is not prime.
|
|
for (const add of [2n ** 64n, 2n ** 65n]) {
|
|
assert.throws(() => {
|
|
generatePrimeSync(64, { add });
|
|
}, {
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: 'invalid options.add'
|
|
});
|
|
}
|
|
|
|
// Any parameters with rem >= add lead to an impossible condition.
|
|
for (const rem of [7n, 8n, 3000n]) {
|
|
assert.throws(() => {
|
|
generatePrimeSync(64, { add: 7n, rem });
|
|
}, {
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: 'invalid options.rem'
|
|
});
|
|
}
|
|
|
|
// This is possible, but not allowed. It implies prime == 7, which means that
|
|
// we did not actually generate a random prime.
|
|
assert.throws(() => {
|
|
generatePrimeSync(3, { add: 8n, rem: 7n });
|
|
}, {
|
|
code: 'ERR_OUT_OF_RANGE'
|
|
});
|
|
|
|
if (process.versions.openssl >= '1.1.1f') {
|
|
// This is possible and allowed (but makes little sense).
|
|
assert.strictEqual(generatePrimeSync(4, {
|
|
add: 15n,
|
|
rem: 13n,
|
|
bigint: true
|
|
}), 13n);
|
|
}
|
|
}
|
|
|
|
[1, 'hello', {}, []].forEach((i) => {
|
|
assert.throws(() => checkPrime(i), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
});
|
|
|
|
for (const checks of ['hello', {}, []]) {
|
|
assert.throws(() => checkPrime(2n, { checks }, common.mustNotCall()), {
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message: /checks/
|
|
});
|
|
assert.throws(() => checkPrimeSync(2n, { checks }), {
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
message: /checks/
|
|
});
|
|
}
|
|
|
|
for (const checks of [-(2 ** 31), -1, 2 ** 31, 2 ** 32 - 1, 2 ** 32, 2 ** 50]) {
|
|
assert.throws(() => checkPrime(2n, { checks }, common.mustNotCall()), {
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: /<= 2147483647/
|
|
});
|
|
assert.throws(() => checkPrimeSync(2n, { checks }), {
|
|
code: 'ERR_OUT_OF_RANGE',
|
|
message: /<= 2147483647/
|
|
});
|
|
}
|
|
|
|
assert(!checkPrimeSync(Buffer.from([0x1])));
|
|
assert(checkPrimeSync(Buffer.from([0x2])));
|
|
assert(checkPrimeSync(Buffer.from([0x3])));
|
|
assert(!checkPrimeSync(Buffer.from([0x4])));
|
|
|
|
assert(
|
|
!checkPrimeSync(
|
|
Buffer.from([0x1]),
|
|
{
|
|
fast: true,
|
|
trialDivision: true,
|
|
checks: 10
|
|
}));
|
|
|
|
(async function() {
|
|
const prime = await pgeneratePrime(36);
|
|
assert(await pCheckPrime(prime));
|
|
})().then(common.mustCall());
|
|
|
|
assert.throws(() => {
|
|
generatePrimeSync(32, { bigint: '' });
|
|
}, { code: 'ERR_INVALID_ARG_TYPE' });
|
|
|
|
assert.throws(() => {
|
|
generatePrime(32, { bigint: '' }, common.mustNotCall());
|
|
}, { code: 'ERR_INVALID_ARG_TYPE' });
|
|
|
|
{
|
|
const prime = generatePrimeSync(3, { bigint: true });
|
|
assert.strictEqual(typeof prime, 'bigint');
|
|
assert.strictEqual(prime, 7n);
|
|
assert(checkPrimeSync(prime));
|
|
checkPrime(prime, common.mustSucceed(assert));
|
|
}
|
|
|
|
{
|
|
generatePrime(3, { bigint: true }, common.mustSucceed((prime) => {
|
|
assert.strictEqual(typeof prime, 'bigint');
|
|
assert.strictEqual(prime, 7n);
|
|
assert(checkPrimeSync(prime));
|
|
checkPrime(prime, common.mustSucceed(assert));
|
|
}));
|
|
}
|