Skip to content

Commit c1b1f4d

Browse files
committed
crypto: reconsile oneshot sign/verify sync and async implementations
1 parent 43f599b commit c1b1f4d

File tree

3 files changed

+119
-34
lines changed

3 files changed

+119
-34
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
'use strict';
2+
3+
const common = require('../common.js');
4+
const crypto = require('crypto');
5+
const fs = require('fs');
6+
const path = require('path');
7+
const fixtures_keydir = path.resolve(__dirname, '../../test/fixtures/keys/');
8+
const keys = {
9+
publicKey: fs.readFileSync(`${fixtures_keydir}/ed25519_public.pem`),
10+
privateKey: fs.readFileSync(`${fixtures_keydir}/ed25519_private.pem`),
11+
};
12+
13+
const data = crypto.randomBytes(256);
14+
const args = [null, data];
15+
16+
const bench = common.createBenchmark(main, {
17+
mode: ['sync', 'async-serial', 'async-parallel'],
18+
keyFormat: ['pem', 'keyObject'],
19+
n: [1e3],
20+
});
21+
22+
function measureSync(n, keyFormat) {
23+
let { publicKey, privateKey } = keys;
24+
if (keyFormat === 'keyObject') {
25+
publicKey = crypto.createPublicKey(publicKey);
26+
privateKey = crypto.createPrivateKey(privateKey);
27+
}
28+
bench.start();
29+
for (let i = 0; i < n; ++i) {
30+
crypto.verify(...args, publicKey,
31+
crypto.sign(...args, privateKey));
32+
}
33+
bench.end(n);
34+
}
35+
36+
function measureAsyncSerial(n, keyFormat) {
37+
let { publicKey, privateKey } = keys;
38+
if (keyFormat === 'keyObject') {
39+
publicKey = crypto.createPublicKey(publicKey);
40+
privateKey = crypto.createPrivateKey(privateKey);
41+
}
42+
let remaining = n;
43+
44+
function done() {
45+
if (--remaining === 0)
46+
bench.end(n);
47+
else
48+
one();
49+
}
50+
51+
function one() {
52+
crypto.sign(...args, privateKey, (err, signature) => {
53+
crypto.verify(...args, publicKey, signature, done);
54+
});
55+
}
56+
bench.start();
57+
one();
58+
}
59+
60+
function measureAsyncParallel(n, keyFormat) {
61+
let { publicKey, privateKey } = keys;
62+
if (keyFormat === 'keyObject') {
63+
publicKey = crypto.createPublicKey(publicKey);
64+
privateKey = crypto.createPrivateKey(privateKey);
65+
}
66+
let remaining = n;
67+
function done() {
68+
if (--remaining === 0)
69+
bench.end(n);
70+
}
71+
bench.start();
72+
for (let i = 0; i < n; ++i) {
73+
crypto.sign(...args, privateKey, (err, signature) => {
74+
crypto.verify(...args, publicKey, signature, done);
75+
});
76+
}
77+
}
78+
79+
function main({ n, mode, keyFormat }) {
80+
switch (mode) {
81+
case 'sync':
82+
measureSync(n, keyFormat);
83+
break;
84+
case 'async-serial':
85+
measureAsyncSerial(n, keyFormat);
86+
break;
87+
case 'async-parallel':
88+
measureAsyncParallel(n, keyFormat);
89+
break;
90+
}
91+
}

lib/internal/crypto/sig.js

Lines changed: 19 additions & 29 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,
@@ -162,18 +161,6 @@ function signOneShot(algorithm, data, key, callback) {
162161
// Options specific to (EC)DSA
163162
const dsaSigEnc = getDSASignatureEncoding(key);
164163

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-
177164
let keyData;
178165
if (isKeyObject(key) || isCryptoKey(key)) {
179166
({ data: keyData } = preparePrivateKey(key));
@@ -184,7 +171,7 @@ function signOneShot(algorithm, data, key, callback) {
184171
}
185172

186173
const job = new SignJob(
187-
kCryptoJobAsync,
174+
callback ? kCryptoJobAsync : kCryptoJobSync,
188175
kSignJobModeSign,
189176
keyData,
190177
data,
@@ -194,6 +181,14 @@ function signOneShot(algorithm, data, key, callback) {
194181
undefined,
195182
dsaSigEnc);
196183

184+
if (!callback) {
185+
const { 0: err, 1: signature } = job.run();
186+
if (err !== undefined)
187+
throw err;
188+
189+
return Buffer.from(signature);
190+
}
191+
197192
job.ondone = (error, signature) => {
198193
if (error) return FunctionPrototypeCall(callback, job, error);
199194
FunctionPrototypeCall(callback, job, null, Buffer.from(signature));
@@ -272,19 +267,6 @@ function verifyOneShot(algorithm, data, key, signature, callback) {
272267
);
273268
}
274269

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-
288270
let keyData;
289271
if (isKeyObject(key) || isCryptoKey(key)) {
290272
({ data: keyData } = preparePublicOrPrivateKey(key));
@@ -295,7 +277,7 @@ function verifyOneShot(algorithm, data, key, signature, callback) {
295277
}
296278

297279
const job = new SignJob(
298-
kCryptoJobAsync,
280+
callback ? kCryptoJobAsync : kCryptoJobSync,
299281
kSignJobModeVerify,
300282
keyData,
301283
data,
@@ -305,6 +287,14 @@ function verifyOneShot(algorithm, data, key, signature, callback) {
305287
signature,
306288
dsaSigEnc);
307289

290+
if (!callback) {
291+
const { 0: err, 1: result } = job.run();
292+
if (err !== undefined)
293+
throw err;
294+
295+
return result;
296+
}
297+
308298
job.ondone = (error, result) => {
309299
if (error) return FunctionPrototypeCall(callback, job, error);
310300
FunctionPrototypeCall(callback, job, null, result);

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -528,11 +528,15 @@ assert.throws(
528528
// Test invalid signature lengths.
529529
for (const i of [-2, -1, 1, 2, 4, 8]) {
530530
sig = crypto.randomBytes(length + i);
531-
assert.throws(() => {
532-
crypto.verify('sha1', data, opts, sig);
533-
}, {
534-
message: 'Malformed signature'
535-
});
531+
let result;
532+
try {
533+
result = crypto.verify('sha1', data, opts, sig);
534+
} catch (err) {
535+
assert.match(err.message, /asn1 encoding/);
536+
assert.strictEqual(err.library, 'asn1 encoding routines');
537+
continue;
538+
}
539+
assert.strictEqual(result, false);
536540
}
537541
}
538542

0 commit comments

Comments
 (0)