diff --git a/doc/api/crypto.md b/doc/api/crypto.md
index 72488a6581bba3..9462cf0ef43ecc 100644
--- a/doc/api/crypto.md
+++ b/doc/api/crypto.md
@@ -1972,14 +1972,14 @@ added: REPLACEME
* `options` {Object}
* `checks` {number} The number of Miller-Rabin probabilistic primality
iterations to perform. When the value is `0` (zero), a number of checks
- is used that yields a false positive rate of at most 2^-64 for random
- input. Care must be used when selecting a number of checks. Refer to the
- OpenSSL documentation for the [`BN_is_prime_ex`][] function `nchecks`
+ is used that yields a false positive rate of at most 2-64 for
+ random input. Care must be used when selecting a number of checks. Refer
+ to the OpenSSL documentation for the [`BN_is_prime_ex`][] function `nchecks`
options for more details. **Defaults**: `0`
* `callback` {Function}
* `err` {Error} Set to an {Error} object if an error occured during check.
* `result` {boolean} `true` if the candidate is a prime with an error
- probability less than `0.25^options.checks`.
+ probability less than `0.25 ** options.checks`.
Checks the primality of the `candidate`.
@@ -1994,12 +1994,12 @@ added: REPLACEME
* `options` {Object}
* `checks` {number} The number of Miller-Rabin probabilistic primality
iterations to perform. When the value is `0` (zero), a number of checks
- is used that yields a false positive rate of at most 2^-64 for random
- input. Care must be used when selecting a number of checks. Refer to the
- OpenSSL documentation for the [`BN_is_prime_ex`][] function `nchecks`
+ is used that yields a false positive rate of at most 2-64 for
+ random input. Care must be used when selecting a number of checks. Refer
+ to the OpenSSL documentation for the [`BN_is_prime_ex`][] function `nchecks`
options for more details. **Defaults**: `0`
* Returns: {boolean} `true` if the candidate is a prime with an error
- probability less than `0.25^options.checks`.
+ probability less than `0.25 ** options.checks`.
Checks the primality of the `candidate`.
@@ -2743,9 +2743,9 @@ added: REPLACEME
* `size` {number} The size (in bits) of the prime to generate.
* `options` {Object}
- * `add` {ArrayBuffer|SharedArrayBuffer|TypedArray|Buffer|DataView}
- * `rem` {ArrayBuffer|SharedArrayBuffer|TypedArray|Buffer|DataView}
- * `safe` {boolean}
+ * `add` {ArrayBuffer|SharedArrayBuffer|TypedArray|Buffer|DataView|bigint}
+ * `rem` {ArrayBuffer|SharedArrayBuffer|TypedArray|Buffer|DataView|bigint}
+ * `safe` {boolean} **Defaults**: `false`.
* `bigint` {boolean} When `true`, the generated prime is returned
as a `bigint`.
* `callback` {Function}
@@ -2754,7 +2754,7 @@ added: REPLACEME
Generates a pseudo-random prime of `size` bits.
-If `options.safe` is true, the prime will be a safe prime -- that is,
+If `options.safe` is `true`, the prime will be a safe prime -- that is,
`(prime - 1) / 2` will also be a prime.
If `options.add` and `options.rem` are set, the prime will satisfy the
@@ -2765,6 +2765,10 @@ will satisfy the condition `prime % add = 3`. Otherwise if `options.safe`
is `false` and `options.rem` is `undefined`, `options.add` will be
ignored.
+Both `options.add` and `options.rem` must be encoded as big-endian sequences
+if given as an `ArrayBuffer`, `SharedArrayBuffer`, `TypedArray`, `Buffer`, or
+`DataView`.
+
By default, the prime is encoded as a big-endian sequence of octets
in an {ArrayBuffer}. If the `bigint` option is `true`, then a {bigint}
is provided.
@@ -2776,16 +2780,16 @@ added: REPLACEME
* `size` {number} The size (in bits) of the prime to generate.
* `options` {Object}
- * `add` {ArrayBuffer|SharedArrayBuffer|TypedArray|Buffer|DataView}
- * `rem` {ArrayBuffer|SharedArrayBuffer|TypedArray|Buffer|DataView}
- * `safe` {boolean}
+ * `add` {ArrayBuffer|SharedArrayBuffer|TypedArray|Buffer|DataView|bigint}
+ * `rem` {ArrayBuffer|SharedArrayBuffer|TypedArray|Buffer|DataView|bigint}
+ * `safe` {boolean} **Defaults**: `false`.
* `bigint` {boolean} When `true`, the generated prime is returned
as a `bigint`.
* Returns: {ArrayBuffer|bigint}
Generates a pseudo-random prime of `size` bits.
-If `options.safe` is true, the prime will be a safe prime -- that is,
+If `options.safe` is `true`, the prime will be a safe prime -- that is,
`(prime - 1)` / 2 will also be a prime.
If `options.add` and `options.rem` are set, the prime will satisfy the
@@ -2796,6 +2800,10 @@ will satisfy the condition `prime % add = 3`. Otherwise if `options.safe`
is `false` and `options.rem` is `undefined`, `options.add` will be
ignored.
+Both `options.add` and `options.rem` must be encoded as big-endian sequences
+if given as an `ArrayBuffer`, `SharedArrayBuffer`, `TypedArray`, `Buffer`, or
+`DataView`.
+
By default, the prime is encoded as a big-endian sequence of octets
in an {ArrayBuffer}. If the `bigint` option is `true`, then a {bigint}
is provided.
diff --git a/lib/internal/crypto/random.js b/lib/internal/crypto/random.js
index c68e77c226bfd3..485989067b7337 100644
--- a/lib/internal/crypto/random.js
+++ b/lib/internal/crypto/random.js
@@ -401,35 +401,46 @@ function generatePrime(size, options, callback) {
validateObject(options, 'options');
const {
safe = false,
+ bigint = false,
+ } = options;
+ let {
add,
rem,
- bigint = false,
} = options;
+
validateBoolean(safe, 'options.safe');
validateBoolean(bigint, 'options.bigint');
- if (add !== undefined && !isAnyArrayBuffer(add) && !isArrayBufferView(add)) {
- throw new ERR_INVALID_ARG_TYPE(
- 'options.add',
- [
- 'ArrayBuffer',
- 'TypedArray',
- 'Buffer',
- 'DataView'
- ],
- add);
+ if (add !== undefined) {
+ if (typeof add === 'bigint') {
+ add = Buffer.from(toHexPadded(add), 'hex');
+ } else if (!isAnyArrayBuffer(add) && !isArrayBufferView(add)) {
+ throw new ERR_INVALID_ARG_TYPE(
+ 'options.add',
+ [
+ 'ArrayBuffer',
+ 'TypedArray',
+ 'Buffer',
+ 'DataView'
+ ],
+ add);
+ }
}
- if (rem !== undefined && !isAnyArrayBuffer(rem) && !isArrayBufferView(rem)) {
- throw new ERR_INVALID_ARG_TYPE(
- 'options.rem',
- [
- 'ArrayBuffer',
- 'TypedArray',
- 'Buffer',
- 'DataView'
- ],
- rem);
+ if (rem !== undefined) {
+ if (typeof rem === 'bigint') {
+ rem = Buffer.from(toHexPadded(rem), 'hex');
+ } else if (!isAnyArrayBuffer(rem) && !isArrayBufferView(rem)) {
+ throw new ERR_INVALID_ARG_TYPE(
+ 'options.rem',
+ [
+ 'ArrayBuffer',
+ 'TypedArray',
+ 'Buffer',
+ 'DataView'
+ ],
+ rem);
+ }
}
const job = new RandomPrimeJob(kCryptoJobAsync, size, safe, add, rem);
@@ -453,35 +464,45 @@ function generatePrimeSync(size, options = {}) {
validateObject(options, 'options');
const {
safe = false,
+ bigint = false,
+ } = options;
+ let {
add,
rem,
- bigint = false,
} = options;
validateBoolean(safe, 'options.safe');
validateBoolean(bigint, 'options.bigint');
- if (add !== undefined && !isAnyArrayBuffer(add) && !isArrayBufferView(add)) {
- throw new ERR_INVALID_ARG_TYPE(
- 'options.add',
- [
- 'ArrayBuffer',
- 'TypedArray',
- 'Buffer',
- 'DataView'
- ],
- add);
+ if (add !== undefined) {
+ if (typeof add === 'bigint') {
+ add = Buffer.from(toHexPadded(add), 'hex');
+ } else if (!isAnyArrayBuffer(add) && !isArrayBufferView(add)) {
+ throw new ERR_INVALID_ARG_TYPE(
+ 'options.add',
+ [
+ 'ArrayBuffer',
+ 'TypedArray',
+ 'Buffer',
+ 'DataView'
+ ],
+ add);
+ }
}
- if (rem !== undefined && !isAnyArrayBuffer(rem) && !isArrayBufferView(rem)) {
- throw new ERR_INVALID_ARG_TYPE(
- 'options.rem',
- [
- 'ArrayBuffer',
- 'TypedArray',
- 'Buffer',
- 'DataView'
- ],
- rem);
+ if (rem !== undefined) {
+ if (typeof rem === 'bigint') {
+ rem = Buffer.from(toHexPadded(rem), 'hex');
+ } else if (!isAnyArrayBuffer(rem) && !isArrayBufferView(rem)) {
+ throw new ERR_INVALID_ARG_TYPE(
+ 'options.rem',
+ [
+ 'ArrayBuffer',
+ 'TypedArray',
+ 'Buffer',
+ 'DataView'
+ ],
+ rem);
+ }
}
const job = new RandomPrimeJob(kCryptoJobSync, size, safe, add, rem);
diff --git a/src/crypto/crypto_random.cc b/src/crypto/crypto_random.cc
index 690f9061bfa950..01f32832b29843 100644
--- a/src/crypto/crypto_random.cc
+++ b/src/crypto/crypto_random.cc
@@ -104,7 +104,7 @@ Maybe RandomPrimeTraits::AdditionalConfig(
bool safe = args[offset + 1]->IsTrue();
if (!args[offset + 2]->IsUndefined()) {
- params->add.reset(BN_new());
+ params->add.reset(BN_secure_new());
if (!params->add) {
THROW_ERR_CRYPTO_OPERATION_FAILED(env, "could not generate prime");
return Nothing();
@@ -118,7 +118,7 @@ Maybe RandomPrimeTraits::AdditionalConfig(
}
if (!args[offset + 3]->IsUndefined()) {
- params->rem.reset(BN_new());
+ params->rem.reset(BN_secure_new());
if (!params->rem) {
THROW_ERR_CRYPTO_OPERATION_FAILED(env, "could not generate prime");
return Nothing();
@@ -139,7 +139,7 @@ Maybe RandomPrimeTraits::AdditionalConfig(
params->bits = bits;
params->safe = safe;
- params->prime.reset(BN_new());
+ params->prime.reset(BN_secure_new());
if (!params->prime) {
THROW_ERR_CRYPTO_OPERATION_FAILED(env, "could not generate prime");
return Nothing();
diff --git a/test/parallel/test-crypto-prime.js b/test/parallel/test-crypto-prime.js
index 209d7413768c08..4d26c46eb5411a 100644
--- a/test/parallel/test-crypto-prime.js
+++ b/test/parallel/test-crypto-prime.js
@@ -107,10 +107,8 @@ generatePrime(32, { safe: true }, common.mustSucceed((prime) => {
const add = 12;
const rem = 11;
-const add_buf = Buffer.alloc(4);
-const rem_buf = Buffer.alloc(4);
-add_buf.writeUInt32BE(add);
-rem_buf.writeUInt32BE(rem);
+const add_buf = Buffer.from([add]);
+const rem_buf = Buffer.from([rem]);
generatePrime(
32,
{ add: add_buf, rem: rem_buf },
@@ -129,6 +127,14 @@ generatePrime(
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);
+}
+
[1, 'hello', {}, []].forEach((i) => {
assert.throws(() => checkPrime(i), {
code: 'ERR_INVALID_ARG_TYPE'