11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciif (!common.hasCrypto)
51cb0ef41Sopenharmony_ci  common.skip('missing crypto');
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciconst assert = require('assert');
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciconst {
101cb0ef41Sopenharmony_ci  generatePrime,
111cb0ef41Sopenharmony_ci  generatePrimeSync,
121cb0ef41Sopenharmony_ci  checkPrime,
131cb0ef41Sopenharmony_ci  checkPrimeSync,
141cb0ef41Sopenharmony_ci} = require('crypto');
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ciconst { promisify } = require('util');
171cb0ef41Sopenharmony_ciconst pgeneratePrime = promisify(generatePrime);
181cb0ef41Sopenharmony_ciconst pCheckPrime = promisify(checkPrime);
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci['hello', false, {}, []].forEach((i) => {
211cb0ef41Sopenharmony_ci  assert.throws(() => generatePrime(i), {
221cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
231cb0ef41Sopenharmony_ci  });
241cb0ef41Sopenharmony_ci  assert.throws(() => generatePrimeSync(i), {
251cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
261cb0ef41Sopenharmony_ci  });
271cb0ef41Sopenharmony_ci});
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ci['hello', false, 123].forEach((i) => {
301cb0ef41Sopenharmony_ci  assert.throws(() => generatePrime(80, i, common.mustNotCall()), {
311cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
321cb0ef41Sopenharmony_ci  });
331cb0ef41Sopenharmony_ci  assert.throws(() => generatePrimeSync(80, i), {
341cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
351cb0ef41Sopenharmony_ci  });
361cb0ef41Sopenharmony_ci});
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci['hello', false, 123].forEach((i) => {
391cb0ef41Sopenharmony_ci  assert.throws(() => generatePrime(80, {}), {
401cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
411cb0ef41Sopenharmony_ci  });
421cb0ef41Sopenharmony_ci});
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci[-1, 0, 2 ** 31, 2 ** 31 + 1, 2 ** 32 - 1, 2 ** 32].forEach((size) => {
451cb0ef41Sopenharmony_ci  assert.throws(() => generatePrime(size, common.mustNotCall()), {
461cb0ef41Sopenharmony_ci    code: 'ERR_OUT_OF_RANGE',
471cb0ef41Sopenharmony_ci    message: />= 1 && <= 2147483647/
481cb0ef41Sopenharmony_ci  });
491cb0ef41Sopenharmony_ci  assert.throws(() => generatePrimeSync(size), {
501cb0ef41Sopenharmony_ci    code: 'ERR_OUT_OF_RANGE',
511cb0ef41Sopenharmony_ci    message: />= 1 && <= 2147483647/
521cb0ef41Sopenharmony_ci  });
531cb0ef41Sopenharmony_ci});
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci['test', -1, {}, []].forEach((i) => {
561cb0ef41Sopenharmony_ci  assert.throws(() => generatePrime(8, { safe: i }, common.mustNotCall()), {
571cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
581cb0ef41Sopenharmony_ci  });
591cb0ef41Sopenharmony_ci  assert.throws(() => generatePrime(8, { rem: i }, common.mustNotCall()), {
601cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
611cb0ef41Sopenharmony_ci  });
621cb0ef41Sopenharmony_ci  assert.throws(() => generatePrime(8, { add: i }, common.mustNotCall()), {
631cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
641cb0ef41Sopenharmony_ci  });
651cb0ef41Sopenharmony_ci  assert.throws(() => generatePrimeSync(8, { safe: i }), {
661cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
671cb0ef41Sopenharmony_ci  });
681cb0ef41Sopenharmony_ci  assert.throws(() => generatePrimeSync(8, { rem: i }), {
691cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
701cb0ef41Sopenharmony_ci  });
711cb0ef41Sopenharmony_ci  assert.throws(() => generatePrimeSync(8, { add: i }), {
721cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
731cb0ef41Sopenharmony_ci  });
741cb0ef41Sopenharmony_ci});
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci{
771cb0ef41Sopenharmony_ci  // Negative BigInts should not be converted to 0 silently.
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  assert.throws(() => generatePrime(20, { add: -1n }, common.mustNotCall()), {
801cb0ef41Sopenharmony_ci    code: 'ERR_OUT_OF_RANGE',
811cb0ef41Sopenharmony_ci    message: 'The value of "options.add" is out of range. It must be >= 0. ' +
821cb0ef41Sopenharmony_ci             'Received -1n'
831cb0ef41Sopenharmony_ci  });
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci  assert.throws(() => generatePrime(20, { rem: -1n }, common.mustNotCall()), {
861cb0ef41Sopenharmony_ci    code: 'ERR_OUT_OF_RANGE',
871cb0ef41Sopenharmony_ci    message: 'The value of "options.rem" is out of range. It must be >= 0. ' +
881cb0ef41Sopenharmony_ci             'Received -1n'
891cb0ef41Sopenharmony_ci  });
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  assert.throws(() => checkPrime(-1n, common.mustNotCall()), {
921cb0ef41Sopenharmony_ci    code: 'ERR_OUT_OF_RANGE',
931cb0ef41Sopenharmony_ci    message: 'The value of "candidate" is out of range. It must be >= 0. ' +
941cb0ef41Sopenharmony_ci             'Received -1n'
951cb0ef41Sopenharmony_ci  });
961cb0ef41Sopenharmony_ci}
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_cigeneratePrime(80, common.mustSucceed((prime) => {
991cb0ef41Sopenharmony_ci  assert(checkPrimeSync(prime));
1001cb0ef41Sopenharmony_ci  checkPrime(prime, common.mustSucceed((result) => {
1011cb0ef41Sopenharmony_ci    assert(result);
1021cb0ef41Sopenharmony_ci  }));
1031cb0ef41Sopenharmony_ci}));
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ciassert(checkPrimeSync(generatePrimeSync(80)));
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_cigeneratePrime(80, {}, common.mustSucceed((prime) => {
1081cb0ef41Sopenharmony_ci  assert(checkPrimeSync(prime));
1091cb0ef41Sopenharmony_ci}));
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ciassert(checkPrimeSync(generatePrimeSync(80, {})));
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_cigeneratePrime(32, { safe: true }, common.mustSucceed((prime) => {
1141cb0ef41Sopenharmony_ci  assert(checkPrimeSync(prime));
1151cb0ef41Sopenharmony_ci  const buf = Buffer.from(prime);
1161cb0ef41Sopenharmony_ci  const val = buf.readUInt32BE();
1171cb0ef41Sopenharmony_ci  const check = (val - 1) / 2;
1181cb0ef41Sopenharmony_ci  buf.writeUInt32BE(check);
1191cb0ef41Sopenharmony_ci  assert(checkPrimeSync(buf));
1201cb0ef41Sopenharmony_ci}));
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci{
1231cb0ef41Sopenharmony_ci  const prime = generatePrimeSync(32, { safe: true });
1241cb0ef41Sopenharmony_ci  assert(checkPrimeSync(prime));
1251cb0ef41Sopenharmony_ci  const buf = Buffer.from(prime);
1261cb0ef41Sopenharmony_ci  const val = buf.readUInt32BE();
1271cb0ef41Sopenharmony_ci  const check = (val - 1) / 2;
1281cb0ef41Sopenharmony_ci  buf.writeUInt32BE(check);
1291cb0ef41Sopenharmony_ci  assert(checkPrimeSync(buf));
1301cb0ef41Sopenharmony_ci}
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ciconst add = 12;
1331cb0ef41Sopenharmony_ciconst rem = 11;
1341cb0ef41Sopenharmony_ciconst add_buf = Buffer.from([add]);
1351cb0ef41Sopenharmony_ciconst rem_buf = Buffer.from([rem]);
1361cb0ef41Sopenharmony_cigeneratePrime(
1371cb0ef41Sopenharmony_ci  32,
1381cb0ef41Sopenharmony_ci  { add: add_buf, rem: rem_buf },
1391cb0ef41Sopenharmony_ci  common.mustSucceed((prime) => {
1401cb0ef41Sopenharmony_ci    assert(checkPrimeSync(prime));
1411cb0ef41Sopenharmony_ci    const buf = Buffer.from(prime);
1421cb0ef41Sopenharmony_ci    const val = buf.readUInt32BE();
1431cb0ef41Sopenharmony_ci    assert.strictEqual(val % add, rem);
1441cb0ef41Sopenharmony_ci  }));
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci{
1471cb0ef41Sopenharmony_ci  const prime = generatePrimeSync(32, { add: add_buf, rem: rem_buf });
1481cb0ef41Sopenharmony_ci  assert(checkPrimeSync(prime));
1491cb0ef41Sopenharmony_ci  const buf = Buffer.from(prime);
1501cb0ef41Sopenharmony_ci  const val = buf.readUInt32BE();
1511cb0ef41Sopenharmony_ci  assert.strictEqual(val % add, rem);
1521cb0ef41Sopenharmony_ci}
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci{
1551cb0ef41Sopenharmony_ci  const prime = generatePrimeSync(32, { add: BigInt(add), rem: BigInt(rem) });
1561cb0ef41Sopenharmony_ci  assert(checkPrimeSync(prime));
1571cb0ef41Sopenharmony_ci  const buf = Buffer.from(prime);
1581cb0ef41Sopenharmony_ci  const val = buf.readUInt32BE();
1591cb0ef41Sopenharmony_ci  assert.strictEqual(val % add, rem);
1601cb0ef41Sopenharmony_ci}
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci{
1631cb0ef41Sopenharmony_ci  // The behavior when specifying only add without rem should depend on the
1641cb0ef41Sopenharmony_ci  // safe option.
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci  if (process.versions.openssl >= '1.1.1f') {
1671cb0ef41Sopenharmony_ci    generatePrime(128, {
1681cb0ef41Sopenharmony_ci      bigint: true,
1691cb0ef41Sopenharmony_ci      add: 5n
1701cb0ef41Sopenharmony_ci    }, common.mustSucceed((prime) => {
1711cb0ef41Sopenharmony_ci      assert(checkPrimeSync(prime));
1721cb0ef41Sopenharmony_ci      assert.strictEqual(prime % 5n, 1n);
1731cb0ef41Sopenharmony_ci    }));
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci    generatePrime(128, {
1761cb0ef41Sopenharmony_ci      bigint: true,
1771cb0ef41Sopenharmony_ci      safe: true,
1781cb0ef41Sopenharmony_ci      add: 5n
1791cb0ef41Sopenharmony_ci    }, common.mustSucceed((prime) => {
1801cb0ef41Sopenharmony_ci      assert(checkPrimeSync(prime));
1811cb0ef41Sopenharmony_ci      assert.strictEqual(prime % 5n, 3n);
1821cb0ef41Sopenharmony_ci    }));
1831cb0ef41Sopenharmony_ci  }
1841cb0ef41Sopenharmony_ci}
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci{
1871cb0ef41Sopenharmony_ci  // This is impossible because it implies (prime % 2**64) == 1 and
1881cb0ef41Sopenharmony_ci  // prime < 2**64, meaning prime = 1, but 1 is not prime.
1891cb0ef41Sopenharmony_ci  for (const add of [2n ** 64n, 2n ** 65n]) {
1901cb0ef41Sopenharmony_ci    assert.throws(() => {
1911cb0ef41Sopenharmony_ci      generatePrimeSync(64, { add });
1921cb0ef41Sopenharmony_ci    }, {
1931cb0ef41Sopenharmony_ci      code: 'ERR_OUT_OF_RANGE',
1941cb0ef41Sopenharmony_ci      message: 'invalid options.add'
1951cb0ef41Sopenharmony_ci    });
1961cb0ef41Sopenharmony_ci  }
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci  // Any parameters with rem >= add lead to an impossible condition.
1991cb0ef41Sopenharmony_ci  for (const rem of [7n, 8n, 3000n]) {
2001cb0ef41Sopenharmony_ci    assert.throws(() => {
2011cb0ef41Sopenharmony_ci      generatePrimeSync(64, { add: 7n, rem });
2021cb0ef41Sopenharmony_ci    }, {
2031cb0ef41Sopenharmony_ci      code: 'ERR_OUT_OF_RANGE',
2041cb0ef41Sopenharmony_ci      message: 'invalid options.rem'
2051cb0ef41Sopenharmony_ci    });
2061cb0ef41Sopenharmony_ci  }
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci  // This is possible, but not allowed. It implies prime == 7, which means that
2091cb0ef41Sopenharmony_ci  // we did not actually generate a random prime.
2101cb0ef41Sopenharmony_ci  assert.throws(() => {
2111cb0ef41Sopenharmony_ci    generatePrimeSync(3, { add: 8n, rem: 7n });
2121cb0ef41Sopenharmony_ci  }, {
2131cb0ef41Sopenharmony_ci    code: 'ERR_OUT_OF_RANGE'
2141cb0ef41Sopenharmony_ci  });
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  if (process.versions.openssl >= '1.1.1f') {
2171cb0ef41Sopenharmony_ci    // This is possible and allowed (but makes little sense).
2181cb0ef41Sopenharmony_ci    assert.strictEqual(generatePrimeSync(4, {
2191cb0ef41Sopenharmony_ci      add: 15n,
2201cb0ef41Sopenharmony_ci      rem: 13n,
2211cb0ef41Sopenharmony_ci      bigint: true
2221cb0ef41Sopenharmony_ci    }), 13n);
2231cb0ef41Sopenharmony_ci  }
2241cb0ef41Sopenharmony_ci}
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci[1, 'hello', {}, []].forEach((i) => {
2271cb0ef41Sopenharmony_ci  assert.throws(() => checkPrime(i), {
2281cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
2291cb0ef41Sopenharmony_ci  });
2301cb0ef41Sopenharmony_ci});
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_cifor (const checks of ['hello', {}, []]) {
2331cb0ef41Sopenharmony_ci  assert.throws(() => checkPrime(2n, { checks }, common.mustNotCall()), {
2341cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
2351cb0ef41Sopenharmony_ci    message: /checks/
2361cb0ef41Sopenharmony_ci  });
2371cb0ef41Sopenharmony_ci  assert.throws(() => checkPrimeSync(2n, { checks }), {
2381cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
2391cb0ef41Sopenharmony_ci    message: /checks/
2401cb0ef41Sopenharmony_ci  });
2411cb0ef41Sopenharmony_ci}
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_cifor (const checks of [-(2 ** 31), -1, 2 ** 31, 2 ** 32 - 1, 2 ** 32, 2 ** 50]) {
2441cb0ef41Sopenharmony_ci  assert.throws(() => checkPrime(2n, { checks }, common.mustNotCall()), {
2451cb0ef41Sopenharmony_ci    code: 'ERR_OUT_OF_RANGE',
2461cb0ef41Sopenharmony_ci    message: /<= 2147483647/
2471cb0ef41Sopenharmony_ci  });
2481cb0ef41Sopenharmony_ci  assert.throws(() => checkPrimeSync(2n, { checks }), {
2491cb0ef41Sopenharmony_ci    code: 'ERR_OUT_OF_RANGE',
2501cb0ef41Sopenharmony_ci    message: /<= 2147483647/
2511cb0ef41Sopenharmony_ci  });
2521cb0ef41Sopenharmony_ci}
2531cb0ef41Sopenharmony_ci
2541cb0ef41Sopenharmony_ciassert(!checkPrimeSync(Buffer.from([0x1])));
2551cb0ef41Sopenharmony_ciassert(checkPrimeSync(Buffer.from([0x2])));
2561cb0ef41Sopenharmony_ciassert(checkPrimeSync(Buffer.from([0x3])));
2571cb0ef41Sopenharmony_ciassert(!checkPrimeSync(Buffer.from([0x4])));
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ciassert(
2601cb0ef41Sopenharmony_ci  !checkPrimeSync(
2611cb0ef41Sopenharmony_ci    Buffer.from([0x1]),
2621cb0ef41Sopenharmony_ci    {
2631cb0ef41Sopenharmony_ci      fast: true,
2641cb0ef41Sopenharmony_ci      trialDivision: true,
2651cb0ef41Sopenharmony_ci      checks: 10
2661cb0ef41Sopenharmony_ci    }));
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ci(async function() {
2691cb0ef41Sopenharmony_ci  const prime = await pgeneratePrime(36);
2701cb0ef41Sopenharmony_ci  assert(await pCheckPrime(prime));
2711cb0ef41Sopenharmony_ci})().then(common.mustCall());
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ciassert.throws(() => {
2741cb0ef41Sopenharmony_ci  generatePrimeSync(32, { bigint: '' });
2751cb0ef41Sopenharmony_ci}, { code: 'ERR_INVALID_ARG_TYPE' });
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_ciassert.throws(() => {
2781cb0ef41Sopenharmony_ci  generatePrime(32, { bigint: '' }, common.mustNotCall());
2791cb0ef41Sopenharmony_ci}, { code: 'ERR_INVALID_ARG_TYPE' });
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci{
2821cb0ef41Sopenharmony_ci  const prime = generatePrimeSync(3, { bigint: true });
2831cb0ef41Sopenharmony_ci  assert.strictEqual(typeof prime, 'bigint');
2841cb0ef41Sopenharmony_ci  assert.strictEqual(prime, 7n);
2851cb0ef41Sopenharmony_ci  assert(checkPrimeSync(prime));
2861cb0ef41Sopenharmony_ci  checkPrime(prime, common.mustSucceed(assert));
2871cb0ef41Sopenharmony_ci}
2881cb0ef41Sopenharmony_ci
2891cb0ef41Sopenharmony_ci{
2901cb0ef41Sopenharmony_ci  generatePrime(3, { bigint: true }, common.mustSucceed((prime) => {
2911cb0ef41Sopenharmony_ci    assert.strictEqual(typeof prime, 'bigint');
2921cb0ef41Sopenharmony_ci    assert.strictEqual(prime, 7n);
2931cb0ef41Sopenharmony_ci    assert(checkPrimeSync(prime));
2941cb0ef41Sopenharmony_ci    checkPrime(prime, common.mustSucceed(assert));
2951cb0ef41Sopenharmony_ci  }));
2961cb0ef41Sopenharmony_ci}
297