Skip to content

Commit e8cb644

Browse files
committed
crypto: reconcile oneshot sign/verify sync and async implementations
PR-URL: #37816 Reviewed-By: Daniel Bevenius <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent d861324 commit e8cb644

File tree

9 files changed

+270
-255
lines changed

9 files changed

+270
-255
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
'use strict';
2+
3+
constcommon=require('../common.js');
4+
constcrypto=require('crypto');
5+
constfs=require('fs');
6+
constpath=require('path');
7+
constfixtures_keydir=path.resolve(__dirname,'../../test/fixtures/keys/');
8+
constkeyFixtures={
9+
publicKey: fs.readFileSync(`${fixtures_keydir}/ec_p256_public.pem`)
10+
.toString(),
11+
privateKey: fs.readFileSync(`${fixtures_keydir}/ec_p256_private.pem`)
12+
.toString()
13+
};
14+
15+
constdata=crypto.randomBytes(256);
16+
17+
letpems;
18+
letkeyObjects;
19+
20+
functiongetKeyObject({ privateKey, publicKey }){
21+
return{
22+
privateKey: crypto.createPrivateKey(privateKey),
23+
publicKey: crypto.createPublicKey(publicKey)
24+
};
25+
}
26+
27+
constbench=common.createBenchmark(main,{
28+
mode: ['sync','async-serial','async-parallel'],
29+
keyFormat: ['pem','keyObject','pem.unique','keyObject.unique'],
30+
n: [1e3],
31+
});
32+
33+
functionmeasureSync(n,privateKey,publicKey,keys){
34+
bench.start();
35+
for(leti=0;i<n;++i){
36+
crypto.verify(
37+
'sha256',
38+
data,
39+
{key: publicKey||keys[i].publicKey,dsaEncoding: 'ieee-p1363'},
40+
crypto.sign(
41+
'sha256',
42+
data,
43+
{key: privateKey||keys[i].privateKey,dsaEncoding: 'ieee-p1363'}));
44+
}
45+
bench.end(n);
46+
}
47+
48+
functionmeasureAsyncSerial(n,privateKey,publicKey,keys){
49+
letremaining=n;
50+
functiondone(){
51+
if(--remaining===0)
52+
bench.end(n);
53+
else
54+
one();
55+
}
56+
57+
functionone(){
58+
crypto.sign(
59+
'sha256',
60+
data,
61+
{
62+
key: privateKey||keys[n-remaining].privateKey,
63+
dsaEncoding: 'ieee-p1363'
64+
},
65+
(err,signature)=>{
66+
crypto.verify(
67+
'sha256',
68+
data,
69+
{
70+
key: publicKey||keys[n-remaining].publicKey,
71+
dsaEncoding: 'ieee-p1363'
72+
},
73+
signature,
74+
done);
75+
});
76+
}
77+
bench.start();
78+
one();
79+
}
80+
81+
functionmeasureAsyncParallel(n,privateKey,publicKey,keys){
82+
letremaining=n;
83+
functiondone(){
84+
if(--remaining===0)
85+
bench.end(n);
86+
}
87+
bench.start();
88+
for(leti=0;i<n;++i){
89+
crypto.sign(
90+
'sha256',
91+
data,
92+
{key: privateKey||keys[i].privateKey,dsaEncoding: 'ieee-p1363'},
93+
(err,signature)=>{
94+
crypto.verify(
95+
'sha256',
96+
data,
97+
{key: publicKey||keys[i].publicKey,dsaEncoding: 'ieee-p1363'},
98+
signature,
99+
done);
100+
});
101+
}
102+
}
103+
104+
functionmain({ n, mode, keyFormat }){
105+
pems||=[...Buffer.alloc(n)].map(()=>({
106+
privateKey: keyFixtures.privateKey,
107+
publicKey: keyFixtures.publicKey
108+
}));
109+
keyObjects||=pems.map(getKeyObject);
110+
111+
letprivateKey,publicKey,keys;
112+
113+
switch(keyFormat){
114+
case'keyObject':
115+
({ publicKey, privateKey }=keyObjects[0]);
116+
break;
117+
case'pem':
118+
({ publicKey, privateKey }=pems[0]);
119+
break;
120+
case'pem.unique':
121+
keys=pems;
122+
break;
123+
case'keyObject.unique':
124+
keys=keyObjects;
125+
break;
126+
default:
127+
thrownewError('not implemented');
128+
}
129+
130+
switch(mode){
131+
case'sync':
132+
measureSync(n,privateKey,publicKey,keys);
133+
break;
134+
case'async-serial':
135+
measureAsyncSerial(n,privateKey,publicKey,keys);
136+
break;
137+
case'async-parallel':
138+
measureAsyncParallel(n,privateKey,publicKey,keys);
139+
break;
140+
}
141+
}

‎lib/internal/crypto/dsa.js‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,12 +251,15 @@ function dsaSignVerify(key, data, algorithm, signature){
251251
kCryptoJobAsync,
252252
signature===undefined ? kSignJobModeSign : kSignJobModeVerify,
253253
key[kKeyObject][kHandle],
254+
undefined,
255+
undefined,
256+
undefined,
254257
data,
255258
normalizeHashName(key.algorithm.hash.name),
256259
undefined,// Salt-length is not used in DSA
257260
undefined,// Padding is not used in DSA
258-
signature,
259-
kSigEncDER));
261+
kSigEncDER,
262+
signature));
260263
}
261264

262265
module.exports={

‎lib/internal/crypto/ec.js‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,12 +467,15 @@ function ecdsaSignVerify(key, data,{name, hash }, signature){
467467
kCryptoJobAsync,
468468
mode,
469469
key[kKeyObject][kHandle],
470+
undefined,
471+
undefined,
472+
undefined,
470473
data,
471474
hashname,
472475
undefined,// Salt length, not used with ECDSA
473476
undefined,// PSS Padding, not used with ECDSA
474-
signature,
475-
kSigEncP1363));
477+
kSigEncP1363,
478+
signature));
476479
}
477480

478481
module.exports={

‎lib/internal/crypto/rsa.js‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,14 @@ function rsaSignVerify(key, data,{saltLength }, signature){
356356
kCryptoJobAsync,
357357
signature===undefined ? kSignJobModeSign : kSignJobModeVerify,
358358
key[kKeyObject][kHandle],
359+
undefined,
360+
undefined,
361+
undefined,
359362
data,
360363
normalizeHashName(key.algorithm.hash.name),
361364
saltLength,
362365
padding,
366+
undefined,
363367
signature));
364368
}
365369

‎lib/internal/crypto/sig.js‎

Lines changed: 39 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ const{
2424
Sign: _Sign,
2525
SignJob,
2626
Verify: _Verify,
27-
signOneShot: _signOneShot,
28-
verifyOneShot: _verifyOneShot,
2927
kCryptoJobAsync,
28+
kCryptoJobSync,
3029
kSigEncDER,
3130
kSigEncP1363,
3231
kSignJobModeSign,
@@ -40,10 +39,6 @@ const{
4039
}=require('internal/crypto/util');
4140

4241
const{
43-
createPrivateKey,
44-
createPublicKey,
45-
isCryptoKey,
46-
isKeyObject,
4742
preparePrivateKey,
4843
preparePublicOrPrivateKey,
4944
}=require('internal/crypto/keys');
@@ -162,38 +157,34 @@ function signOneShot(algorithm, data, key, callback){
162157
// Options specific to (EC)DSA
163158
constdsaSigEnc=getDSASignatureEncoding(key);
164159

165-
if(!callback){
166-
const{
167-
data: keyData,
168-
format: keyFormat,
169-
type: keyType,
170-
passphrase: keyPassphrase
171-
}=preparePrivateKey(key);
172-
173-
return_signOneShot(keyData,keyFormat,keyType,keyPassphrase,data,
174-
algorithm,rsaPadding,pssSaltLength,dsaSigEnc);
175-
}
176-
177-
letkeyData;
178-
if(isKeyObject(key)||isCryptoKey(key)){
179-
({data: keyData}=preparePrivateKey(key));
180-
}elseif(isKeyObject(key.key)||isCryptoKey(key.key)){
181-
({data: keyData}=preparePrivateKey(key.key));
182-
}else{
183-
keyData=createPrivateKey(key)[kHandle];
184-
}
160+
const{
161+
data: keyData,
162+
format: keyFormat,
163+
type: keyType,
164+
passphrase: keyPassphrase
165+
}=preparePrivateKey(key);
185166

186167
constjob=newSignJob(
187-
kCryptoJobAsync,
168+
callback ? kCryptoJobAsync : kCryptoJobSync,
188169
kSignJobModeSign,
189170
keyData,
171+
keyFormat,
172+
keyType,
173+
keyPassphrase,
190174
data,
191175
algorithm,
192176
pssSaltLength,
193177
rsaPadding,
194-
undefined,
195178
dsaSigEnc);
196179

180+
if(!callback){
181+
const{0: err,1: signature}=job.run();
182+
if(err!==undefined)
183+
throwerr;
184+
185+
returnBuffer.from(signature);
186+
}
187+
197188
job.ondone=(error,signature)=>{
198189
if(error)returnFunctionPrototypeCall(callback,job,error);
199190
FunctionPrototypeCall(callback,job,null,Buffer.from(signature));
@@ -272,38 +263,34 @@ function verifyOneShot(algorithm, data, key, signature, callback){
272263
);
273264
}
274265

275-
if(!callback){
276-
const{
277-
data: keyData,
278-
format: keyFormat,
279-
type: keyType,
280-
passphrase: keyPassphrase
281-
}=preparePublicOrPrivateKey(key);
282-
283-
return_verifyOneShot(keyData,keyFormat,keyType,keyPassphrase,
284-
signature,data,algorithm,rsaPadding,
285-
pssSaltLength,dsaSigEnc);
286-
}
287-
288-
letkeyData;
289-
if(isKeyObject(key)||isCryptoKey(key)){
290-
({data: keyData}=preparePublicOrPrivateKey(key));
291-
}elseif(key!=null&&(isKeyObject(key.key)||isCryptoKey(key.key))){
292-
({data: keyData}=preparePublicOrPrivateKey(key.key));
293-
}else{
294-
keyData=createPublicKey(key)[kHandle];
295-
}
266+
const{
267+
data: keyData,
268+
format: keyFormat,
269+
type: keyType,
270+
passphrase: keyPassphrase
271+
}=preparePublicOrPrivateKey(key);
296272

297273
constjob=newSignJob(
298-
kCryptoJobAsync,
274+
callback ? kCryptoJobAsync : kCryptoJobSync,
299275
kSignJobModeVerify,
300276
keyData,
277+
keyFormat,
278+
keyType,
279+
keyPassphrase,
301280
data,
302281
algorithm,
303282
pssSaltLength,
304283
rsaPadding,
305-
signature,
306-
dsaSigEnc);
284+
dsaSigEnc,
285+
signature);
286+
287+
if(!callback){
288+
const{0: err,1: result}=job.run();
289+
if(err!==undefined)
290+
throwerr;
291+
292+
returnresult;
293+
}
307294

308295
job.ondone=(error,result)=>{
309296
if(error)returnFunctionPrototypeCall(callback,job,error);

0 commit comments

Comments
(0)