crypto: support Ed448 and ML-DSA context parameter in node:crypto · nodejs/node@7a8e2c2
@@ -9,7 +9,7 @@ const exec = require('child_process').exec;
99const crypto = require('crypto');
1010const fixtures = require('../common/fixtures');
1111const {
12-hasOpenSSL3,
12+hasOpenSSL,
1313 opensslCli,
1414} = require('../common/crypto');
1515@@ -66,7 +66,7 @@ const keySize = 2048;
6666key: keyPem,
6767padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
6868});
69-}, { message: hasOpenSSL3 ?
69+}, { message: hasOpenSSL(3) ?
7070'error:1C8000A5:Provider routines::illegal or unsupported padding mode' :
7171'bye, bye, error stack' });
7272@@ -344,7 +344,7 @@ assert.throws(
344344key: keyPem,
345345padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
346346});
347-}, hasOpenSSL3 ? {
347+}, hasOpenSSL(3) ? {
348348code: 'ERR_OSSL_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE',
349349message: /illegal or unsupported padding mode/,
350350} : {
@@ -426,6 +426,7 @@ assert.throws(
426426{ private: fixtures.readKey('ed448_private.pem', 'ascii'),
427427public: fixtures.readKey('ed448_public.pem', 'ascii'),
428428algo: null,
429+supportsContext: true,
429430sigLen: 114 },
430431{ private: fixtures.readKey('rsa_private_2048.pem', 'ascii'),
431432public: fixtures.readKey('rsa_public_2048.pem', 'ascii'),
@@ -473,6 +474,55 @@ assert.throws(
473474assert.strictEqual(crypto.verify(algo, data, pair.private, sig),
474475true);
475476});
477+478+if (pair.supportsContext && hasOpenSSL(3, 2)) {
479+const data = Buffer.from('Hello world');
480+{
481+const context = new Uint8Array();
482+const sig = crypto.sign(algo, data, { key: pair.private, context });
483+assert.strictEqual(crypto.verify(algo, data, { key: pair.public }, sig), true);
484+assert.strictEqual(crypto.verify(algo, data, { key: pair.public, context }, sig), true);
485+assert.strictEqual(crypto.verify(algo, data, { key: pair.public, context: crypto.randomBytes(30) }, sig), false);
486+}
487+488+{
489+const context = new Uint8Array(32);
490+const sig = crypto.sign(algo, data, { key: pair.private, context });
491+assert.strictEqual(crypto.verify(algo, data, { key: pair.public }, sig), false);
492+assert.strictEqual(crypto.verify(algo, data, { key: pair.public, context }, sig), true);
493+assert.strictEqual(crypto.verify(algo, data, { key: pair.public, context: crypto.randomBytes(30) }, sig), false);
494+}
495+496+assert.throws(() => crypto.sign(algo, data, { key: pair.private, context: new Uint8Array(256) }), {
497+code: 'ERR_OUT_OF_RANGE',
498+message: 'context string must be at most 255 bytes',
499+});
500+501+assert.throws(() => {
502+crypto.verify(algo, data, { key: pair.public, context: new Uint8Array(256) }, new Uint8Array());
503+}, {
504+code: 'ERR_OUT_OF_RANGE',
505+message: 'context string must be at most 255 bytes',
506+});
507+} else if (pair.supportsContext) {
508+const data = Buffer.from('Hello world');
509+{
510+const context = new Uint8Array();
511+const sig = crypto.sign(algo, data, { key: pair.private, context });
512+assert.strictEqual(crypto.verify(algo, data, { key: pair.public }, sig), true);
513+assert.strictEqual(crypto.verify(algo, data, { key: pair.public, context }, sig), true);
514+}
515+516+{
517+const context = new Uint8Array(32);
518+assert.throws(() => {
519+crypto.sign(algo, data, { key: pair.private, context });
520+}, { message: 'Context parameter is unsupported' });
521+assert.throws(() => {
522+crypto.verify(algo, data, { key: pair.public, context: crypto.randomBytes(30) }, crypto.randomBytes(32));
523+}, { message: 'Context parameter is unsupported' });
524+}
525+}
476526});
477527478528[1, {}, [], true, Infinity].forEach((input) => {