Skip to content

Commit 344592d

Browse files
joyeecheungtargos
authored andcommitted
test: split test-crypto-keygen.js
To avoid timing out on ARM machines in the CI. PR-URL: #49221 Refs: #49202 Refs: #41206 Reviewed-By: Luigi Pinca <[email protected]>
1 parent 11fbd92 commit 344592d

32 files changed

+1456
-1042
lines changed

‎test/common/crypto.js‎

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ if (!common.hasCrypto)
66

77
constassert=require('assert');
88
constcrypto=require('crypto');
9+
const{
10+
createSign,
11+
createVerify,
12+
publicEncrypt,
13+
privateDecrypt,
14+
sign,
15+
verify,
16+
}=crypto;
917

1018
// The values below (modp2/modp2buf) are for a 1024 bits long prime from
1119
// RFC 2412 E.2, see https://tools.ietf.org/html/rfc2412. */
@@ -42,7 +50,83 @@ function testDH({publicKey: alicePublicKey, privateKey: alicePrivateKey },
4250
assert.deepStrictEqual(buf1,expectedValue);
4351
}
4452

53+
// Asserts that the size of the given key (in chars or bytes) is within 10% of
54+
// the expected size.
55+
functionassertApproximateSize(key,expectedSize){
56+
constu=typeofkey==='string' ? 'chars' : 'bytes';
57+
constmin=Math.floor(0.9*expectedSize);
58+
constmax=Math.ceil(1.1*expectedSize);
59+
assert(key.length>=min,
60+
`Key (${key.length}${u}) is shorter than expected (${min}${u})`);
61+
assert(key.length<=max,
62+
`Key (${key.length}${u}) is longer than expected (${max}${u})`);
63+
}
64+
65+
// Tests that a key pair can be used for encryption / decryption.
66+
functiontestEncryptDecrypt(publicKey,privateKey){
67+
constmessage='Hello Node.js world!';
68+
constplaintext=Buffer.from(message,'utf8');
69+
for(constkeyof[publicKey,privateKey]){
70+
constciphertext=publicEncrypt(key,plaintext);
71+
constreceived=privateDecrypt(privateKey,ciphertext);
72+
assert.strictEqual(received.toString('utf8'),message);
73+
}
74+
}
75+
76+
// Tests that a key pair can be used for signing / verification.
77+
functiontestSignVerify(publicKey,privateKey){
78+
constmessage=Buffer.from('Hello Node.js world!');
79+
80+
functionoldSign(algo,data,key){
81+
returncreateSign(algo).update(data).sign(key);
82+
}
83+
84+
functionoldVerify(algo,data,key,signature){
85+
returncreateVerify(algo).update(data).verify(key,signature);
86+
}
87+
88+
for(constsignFnof[sign,oldSign]){
89+
constsignature=signFn('SHA256',message,privateKey);
90+
for(constverifyFnof[verify,oldVerify]){
91+
for(constkeyof[publicKey,privateKey]){
92+
constokay=verifyFn('SHA256',message,key,signature);
93+
assert(okay);
94+
}
95+
}
96+
}
97+
}
98+
99+
// Constructs a regular expression for a PEM-encoded key with the given label.
100+
functiongetRegExpForPEM(label,cipher){
101+
consthead=`\\-\\-\\-\\-\\-BEGIN ${label}\\-\\-\\-\\-\\-`;
102+
constrfc1421Header=cipher==null ? '' :
103+
`\nProc-Type: 4,ENCRYPTED\nDEK-Info: ${cipher},[^\n]+\n`;
104+
constbody='([a-zA-Z0-9\\+/=]{64}\n)*[a-zA-Z0-9\\+/=]{1,64}';
105+
constend=`\\-\\-\\-\\-\\-END ${label}\\-\\-\\-\\-\\-`;
106+
returnnewRegExp(`^${head}${rfc1421Header}\n${body}\n${end}\n$`);
107+
}
108+
109+
constpkcs1PubExp=getRegExpForPEM('RSA PUBLIC KEY');
110+
constpkcs1PrivExp=getRegExpForPEM('RSA PRIVATE KEY');
111+
constpkcs1EncExp=(cipher)=>getRegExpForPEM('RSA PRIVATE KEY',cipher);
112+
constspkiExp=getRegExpForPEM('PUBLIC KEY');
113+
constpkcs8Exp=getRegExpForPEM('PRIVATE KEY');
114+
constpkcs8EncExp=getRegExpForPEM('ENCRYPTED PRIVATE KEY');
115+
constsec1Exp=getRegExpForPEM('EC PRIVATE KEY');
116+
constsec1EncExp=(cipher)=>getRegExpForPEM('EC PRIVATE KEY',cipher);
117+
45118
module.exports={
46119
modp2buf,
47120
testDH,
121+
assertApproximateSize,
122+
testEncryptDecrypt,
123+
testSignVerify,
124+
pkcs1PubExp,
125+
pkcs1PrivExp,
126+
pkcs1EncExp,// used once
127+
spkiExp,
128+
pkcs8Exp,// used once
129+
pkcs8EncExp,// used once
130+
sec1Exp,
131+
sec1EncExp,
48132
};
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use strict';
2+
3+
constcommon=require('../common');
4+
if(!common.hasCrypto)
5+
common.skip('missing crypto');
6+
7+
constassert=require('assert');
8+
const{
9+
generateKeyPair,
10+
}=require('crypto');
11+
12+
// Test async DSA key object generation.
13+
{
14+
generateKeyPair('dsa',{
15+
modulusLength: common.hasOpenSSL3 ? 2048 : 512,
16+
divisorLength: 256
17+
},common.mustSucceed((publicKey,privateKey)=>{
18+
assert.strictEqual(publicKey.type,'public');
19+
assert.strictEqual(publicKey.asymmetricKeyType,'dsa');
20+
assert.deepStrictEqual(publicKey.asymmetricKeyDetails,{
21+
modulusLength: common.hasOpenSSL3 ? 2048 : 512,
22+
divisorLength: 256
23+
});
24+
25+
assert.strictEqual(privateKey.type,'private');
26+
assert.strictEqual(privateKey.asymmetricKeyType,'dsa');
27+
assert.deepStrictEqual(privateKey.asymmetricKeyDetails,{
28+
modulusLength: common.hasOpenSSL3 ? 2048 : 512,
29+
divisorLength: 256
30+
});
31+
}));
32+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
'use strict';
2+
3+
constcommon=require('../common');
4+
if(!common.hasCrypto)
5+
common.skip('missing crypto');
6+
7+
constassert=require('assert');
8+
const{
9+
generateKeyPair,
10+
}=require('crypto');
11+
const{
12+
assertApproximateSize,
13+
testSignVerify,
14+
spkiExp,
15+
}=require('../common/crypto');
16+
17+
// Test async DSA key generation.
18+
{
19+
constprivateKeyEncoding={
20+
type: 'pkcs8',
21+
format: 'der'
22+
};
23+
24+
generateKeyPair('dsa',{
25+
modulusLength: common.hasOpenSSL3 ? 2048 : 512,
26+
divisorLength: 256,
27+
publicKeyEncoding: {
28+
type: 'spki',
29+
format: 'pem'
30+
},
31+
privateKeyEncoding: {
32+
cipher: 'aes-128-cbc',
33+
passphrase: 'secret',
34+
...privateKeyEncoding
35+
}
36+
},common.mustSucceed((publicKey,privateKeyDER)=>{
37+
assert.strictEqual(typeofpublicKey,'string');
38+
assert.match(publicKey,spkiExp);
39+
// The private key is DER-encoded.
40+
assert(Buffer.isBuffer(privateKeyDER));
41+
42+
assertApproximateSize(publicKey,common.hasOpenSSL3 ? 1194 : 440);
43+
assertApproximateSize(privateKeyDER,common.hasOpenSSL3 ? 721 : 336);
44+
45+
// Since the private key is encrypted, signing shouldn't work anymore.
46+
assert.throws(()=>{
47+
returntestSignVerify(publicKey,{
48+
key: privateKeyDER,
49+
...privateKeyEncoding
50+
});
51+
},{
52+
name: 'TypeError',
53+
code: 'ERR_MISSING_PASSPHRASE',
54+
message: 'Passphrase required for encrypted key'
55+
});
56+
57+
// Signing should work with the correct password.
58+
testSignVerify(publicKey,{
59+
key: privateKeyDER,
60+
...privateKeyEncoding,
61+
passphrase: 'secret'
62+
});
63+
}));
64+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
'use strict';
2+
3+
constcommon=require('../common');
4+
if(!common.hasCrypto)
5+
common.skip('missing crypto');
6+
7+
constassert=require('assert');
8+
const{
9+
generateKeyPair,
10+
}=require('crypto');
11+
12+
// Test async elliptic curve key generation with 'jwk' encoding
13+
{
14+
[
15+
['ec',['P-384','P-256','P-521','secp256k1']],
16+
['rsa'],
17+
['ed25519'],
18+
['ed448'],
19+
['x25519'],
20+
['x448'],
21+
].forEach((types)=>{
22+
const[type,options]=types;
23+
switch(type){
24+
case'ec': {
25+
returnoptions.forEach((curve)=>{
26+
generateKeyPair(type,{
27+
namedCurve: curve,
28+
publicKeyEncoding: {
29+
format: 'jwk'
30+
},
31+
privateKeyEncoding: {
32+
format: 'jwk'
33+
}
34+
},common.mustSucceed((publicKey,privateKey)=>{
35+
assert.strictEqual(typeofpublicKey,'object');
36+
assert.strictEqual(typeofprivateKey,'object');
37+
assert.strictEqual(publicKey.x,privateKey.x);
38+
assert.strictEqual(publicKey.y,privateKey.y);
39+
assert(!publicKey.d);
40+
assert(privateKey.d);
41+
assert.strictEqual(publicKey.kty,'EC');
42+
assert.strictEqual(publicKey.kty,privateKey.kty);
43+
assert.strictEqual(publicKey.crv,curve);
44+
assert.strictEqual(publicKey.crv,privateKey.crv);
45+
}));
46+
});
47+
}
48+
case'rsa': {
49+
returngenerateKeyPair(type,{
50+
modulusLength: 4096,
51+
publicKeyEncoding: {
52+
format: 'jwk'
53+
},
54+
privateKeyEncoding: {
55+
format: 'jwk'
56+
}
57+
},common.mustSucceed((publicKey,privateKey)=>{
58+
assert.strictEqual(typeofpublicKey,'object');
59+
assert.strictEqual(typeofprivateKey,'object');
60+
assert.strictEqual(publicKey.kty,'RSA');
61+
assert.strictEqual(publicKey.kty,privateKey.kty);
62+
assert.strictEqual(typeofpublicKey.n,'string');
63+
assert.strictEqual(publicKey.n,privateKey.n);
64+
assert.strictEqual(typeofpublicKey.e,'string');
65+
assert.strictEqual(publicKey.e,privateKey.e);
66+
assert.strictEqual(typeofprivateKey.d,'string');
67+
assert.strictEqual(typeofprivateKey.p,'string');
68+
assert.strictEqual(typeofprivateKey.q,'string');
69+
assert.strictEqual(typeofprivateKey.dp,'string');
70+
assert.strictEqual(typeofprivateKey.dq,'string');
71+
assert.strictEqual(typeofprivateKey.qi,'string');
72+
}));
73+
}
74+
case'ed25519':
75+
case'ed448':
76+
case'x25519':
77+
case'x448': {
78+
generateKeyPair(type,{
79+
publicKeyEncoding: {
80+
format: 'jwk'
81+
},
82+
privateKeyEncoding: {
83+
format: 'jwk'
84+
}
85+
},common.mustSucceed((publicKey,privateKey)=>{
86+
assert.strictEqual(typeofpublicKey,'object');
87+
assert.strictEqual(typeofprivateKey,'object');
88+
assert.strictEqual(publicKey.x,privateKey.x);
89+
assert(!publicKey.d);
90+
assert(privateKey.d);
91+
assert.strictEqual(publicKey.kty,'OKP');
92+
assert.strictEqual(publicKey.kty,privateKey.kty);
93+
constexpectedCrv=`${type.charAt(0).toUpperCase()}${type.slice(1)}`;
94+
assert.strictEqual(publicKey.crv,expectedCrv);
95+
assert.strictEqual(publicKey.crv,privateKey.crv);
96+
}));
97+
}
98+
}
99+
});
100+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
'use strict';
2+
3+
constcommon=require('../common');
4+
if(!common.hasCrypto)
5+
common.skip('missing crypto');
6+
7+
constassert=require('assert');
8+
const{
9+
generateKeyPair,
10+
}=require('crypto');
11+
const{
12+
assertApproximateSize,
13+
testEncryptDecrypt,
14+
testSignVerify,
15+
}=require('../common/crypto');
16+
17+
// Test async RSA key generation with an encrypted private key, but encoded as DER.
18+
{
19+
generateKeyPair('rsa',{
20+
publicExponent: 0x10001,
21+
modulusLength: 512,
22+
publicKeyEncoding: {
23+
type: 'pkcs1',
24+
format: 'der'
25+
},
26+
privateKeyEncoding: {
27+
type: 'pkcs8',
28+
format: 'der'
29+
}
30+
},common.mustSucceed((publicKeyDER,privateKeyDER)=>{
31+
assert(Buffer.isBuffer(publicKeyDER));
32+
assertApproximateSize(publicKeyDER,74);
33+
34+
assert(Buffer.isBuffer(privateKeyDER));
35+
36+
constpublicKey={
37+
key: publicKeyDER,
38+
type: 'pkcs1',
39+
format: 'der',
40+
};
41+
constprivateKey={
42+
key: privateKeyDER,
43+
format: 'der',
44+
type: 'pkcs8',
45+
passphrase: 'secret'
46+
};
47+
testEncryptDecrypt(publicKey,privateKey);
48+
testSignVerify(publicKey,privateKey);
49+
}));
50+
}

0 commit comments

Comments
(0)