Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7a8e2c2

Browse files
panvatargos
authored andcommitted
crypto: support Ed448 and ML-DSA context parameter in node:crypto
PR-URL:#59570Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent4b631be commit7a8e2c2

File tree

4 files changed

+98
-5
lines changed

4 files changed

+98
-5
lines changed

‎doc/api/crypto.md‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5712,6 +5712,9 @@ Throws an error if FIPS mode is not available.
57125712
<!-- YAML
57135713
added: v12.0.0
57145714
changes:
5715+
- version: REPLACEME
5716+
pr-url: https://github.com/nodejs/node/pull/59570
5717+
description: Add support for ML-DSA, Ed448, and SLH-DSA context parameter.
57155718
- version: REPLACEME
57165719
pr-url: https://github.com/nodejs/node/pull/59537
57175720
description: Add support for SLH-DSA signing.
@@ -5772,6 +5775,9 @@ additional properties can be passed:
57725775
`crypto.constants.RSA_PSS_SALTLEN_DIGEST` sets the salt length to the digest
57735776
size,`crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN` (default) sets it to the
57745777
maximum permissible value.
5778+
*`context` {ArrayBuffer|Buffer|TypedArray|DataView} For Ed448, ML-DSA, and SLH-DSA,
5779+
this option specifies the optional context to differentiate signatures generated
5780+
for different purposes with the same key.
57755781

57765782
If the`callback` function is provided this function uses libuv's threadpool.
57775783

@@ -5831,6 +5837,9 @@ not introduce timing vulnerabilities.
58315837
<!-- YAML
58325838
added: v12.0.0
58335839
changes:
5840+
- version: REPLACEME
5841+
pr-url: https://github.com/nodejs/node/pull/59570
5842+
description: Add support for ML-DSA, Ed448, and SLH-DSA context parameter.
58345843
- version: REPLACEME
58355844
pr-url: https://github.com/nodejs/node/pull/59537
58365845
description: Add support for SLH-DSA signature verification.
@@ -5897,6 +5906,9 @@ additional properties can be passed:
58975906
`crypto.constants.RSA_PSS_SALTLEN_DIGEST` sets the salt length to the digest
58985907
size,`crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN` (default) sets it to the
58995908
maximum permissible value.
5909+
*`context` {ArrayBuffer|Buffer|TypedArray|DataView} For Ed448, ML-DSA, and SLH-DSA,
5910+
this option specifies the optional context to differentiate signatures generated
5911+
for different purposes with the same key.
59005912

59015913
The`signature` argument is the previously calculated signature for the`data`.
59025914

‎lib/internal/crypto/sig.js‎

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,19 @@ function getDSASignatureEncoding(options) {
101101
returnkSigEncDER;
102102
}
103103

104+
functiongetContext(options){
105+
if(options?.context===undefined){
106+
returnundefined;
107+
}
108+
109+
if(!isArrayBufferView(options.context)){
110+
thrownewERR_INVALID_ARG_TYPE(
111+
'options.context',['Buffer','TypedArray','DataView'],options.context);
112+
}
113+
114+
returnoptions.context;
115+
}
116+
104117
functiongetIntOption(name,options){
105118
constvalue=options[name];
106119
if(value!==undefined){
@@ -153,6 +166,9 @@ function signOneShot(algorithm, data, key, callback) {
153166
// Options specific to (EC)DSA
154167
constdsaSigEnc=getDSASignatureEncoding(key);
155168

169+
// Options specific to Ed448 and ML-DSA
170+
constcontext=getContext(key);
171+
156172
const{
157173
data:keyData,
158174
format:keyFormat,
@@ -172,7 +188,7 @@ function signOneShot(algorithm, data, key, callback) {
172188
pssSaltLength,
173189
rsaPadding,
174190
dsaSigEnc,
175-
undefined,
191+
context,
176192
undefined);
177193

178194
if(!callback){
@@ -251,6 +267,9 @@ function verifyOneShot(algorithm, data, key, signature, callback) {
251267
// Options specific to (EC)DSA
252268
constdsaSigEnc=getDSASignatureEncoding(key);
253269

270+
// Options specific to Ed448 and ML-DSA
271+
constcontext=getContext(key);
272+
254273
if(!isArrayBufferView(signature)){
255274
thrownewERR_INVALID_ARG_TYPE(
256275
'signature',
@@ -278,7 +297,7 @@ function verifyOneShot(algorithm, data, key, signature, callback) {
278297
pssSaltLength,
279298
rsaPadding,
280299
dsaSigEnc,
281-
undefined,
300+
context,
282301
signature);
283302

284303
if(!callback){

‎src/crypto/crypto_sig.cc‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,18 @@ bool SupportsContextString(const EVPKeyPointer& key) {
246246
case EVP_PKEY_ML_DSA_44:
247247
case EVP_PKEY_ML_DSA_65:
248248
case EVP_PKEY_ML_DSA_87:
249+
case EVP_PKEY_SLH_DSA_SHA2_128F:
250+
case EVP_PKEY_SLH_DSA_SHA2_128S:
251+
case EVP_PKEY_SLH_DSA_SHA2_192F:
252+
case EVP_PKEY_SLH_DSA_SHA2_192S:
253+
case EVP_PKEY_SLH_DSA_SHA2_256F:
254+
case EVP_PKEY_SLH_DSA_SHA2_256S:
255+
case EVP_PKEY_SLH_DSA_SHAKE_128F:
256+
case EVP_PKEY_SLH_DSA_SHAKE_128S:
257+
case EVP_PKEY_SLH_DSA_SHAKE_192F:
258+
case EVP_PKEY_SLH_DSA_SHAKE_192S:
259+
case EVP_PKEY_SLH_DSA_SHAKE_256F:
260+
case EVP_PKEY_SLH_DSA_SHAKE_256S:
249261
#endif
250262
returntrue;
251263
default:

‎test/parallel/test-crypto-sign-verify.js‎

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const exec = require('child_process').exec;
99
constcrypto=require('crypto');
1010
constfixtures=require('../common/fixtures');
1111
const{
12-
hasOpenSSL3,
12+
hasOpenSSL,
1313
opensslCli,
1414
}=require('../common/crypto');
1515

@@ -66,7 +66,7 @@ const keySize = 2048;
6666
key:keyPem,
6767
padding: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(
344344
key:keyPem,
345345
padding:crypto.constants.RSA_PKCS1_OAEP_PADDING
346346
});
347-
},hasOpenSSL3 ?{
347+
},hasOpenSSL(3) ?{
348348
code:'ERR_OSSL_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE',
349349
message:/illegalorunsupportedpaddingmode/,
350350
} :{
@@ -426,6 +426,7 @@ assert.throws(
426426
{private:fixtures.readKey('ed448_private.pem','ascii'),
427427
public:fixtures.readKey('ed448_public.pem','ascii'),
428428
algo:null,
429+
supportsContext:true,
429430
sigLen:114},
430431
{private:fixtures.readKey('rsa_private_2048.pem','ascii'),
431432
public:fixtures.readKey('rsa_public_2048.pem','ascii'),
@@ -473,6 +474,55 @@ assert.throws(
473474
assert.strictEqual(crypto.verify(algo,data,pair.private,sig),
474475
true);
475476
});
477+
478+
if(pair.supportsContext&&hasOpenSSL(3,2)){
479+
constdata=Buffer.from('Hello world');
480+
{
481+
constcontext=newUint8Array();
482+
constsig=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+
constcontext=newUint8Array(32);
490+
constsig=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:newUint8Array(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:newUint8Array(256)},newUint8Array());
503+
},{
504+
code:'ERR_OUT_OF_RANGE',
505+
message:'context string must be at most 255 bytes',
506+
});
507+
}elseif(pair.supportsContext){
508+
constdata=Buffer.from('Hello world');
509+
{
510+
constcontext=newUint8Array();
511+
constsig=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+
constcontext=newUint8Array(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
});
477527

478528
[1,{},[],true,Infinity].forEach((input)=>{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp