aboutsummaryrefslogtreecommitdiff
path: root/test/parallel/test-crypto-keygen.js
diff options
context:
space:
mode:
authorTobias Nießen <tniessen@tnie.de>2018-09-28 23:06:00 +0200
committerTobias Nießen <tniessen@tnie.de>2018-10-02 11:32:16 +0200
commit0a1c65079a4bcf76cf4ebf47aa24384f62a022e7 (patch)
treec85234039de9164e541cca1d9618af9888cccb3c /test/parallel/test-crypto-keygen.js
parent6117af349041834bfe844d32beeac86152031023 (diff)
downloadandroid-node-v8-0a1c65079a4bcf76cf4ebf47aa24384f62a022e7.tar.gz
android-node-v8-0a1c65079a4bcf76cf4ebf47aa24384f62a022e7.tar.bz2
android-node-v8-0a1c65079a4bcf76cf4ebf47aa24384f62a022e7.zip
crypto: add support for PEM-level encryption
This adds support for PEM-level encryption as defined in RFC 1421. PEM-level encryption is intentionally unsupported for PKCS#8 private keys since PKCS#8 defines a newer encryption format. PR-URL: https://github.com/nodejs/node/pull/23151 Refs: https://github.com/nodejs/node/pull/22660 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'test/parallel/test-crypto-keygen.js')
-rw-r--r--test/parallel/test-crypto-keygen.js78
1 files changed, 74 insertions, 4 deletions
diff --git a/test/parallel/test-crypto-keygen.js b/test/parallel/test-crypto-keygen.js
index 08e37e2ac0..af60c662f9 100644
--- a/test/parallel/test-crypto-keygen.js
+++ b/test/parallel/test-crypto-keygen.js
@@ -47,19 +47,23 @@ function testSignVerify(publicKey, privateKey) {
}
// Constructs a regular expression for a PEM-encoded key with the given label.
-function getRegExpForPEM(label) {
+function getRegExpForPEM(label, cipher) {
const head = `\\-\\-\\-\\-\\-BEGIN ${label}\\-\\-\\-\\-\\-`;
+ const rfc1421Header = cipher == null ? '' :
+ `\nProc-Type: 4,ENCRYPTED\nDEK-Info: ${cipher},[^\n]+\n`;
const body = '([a-zA-Z0-9\\+/=]{64}\n)*[a-zA-Z0-9\\+/=]{1,64}';
const end = `\\-\\-\\-\\-\\-END ${label}\\-\\-\\-\\-\\-`;
- return new RegExp(`^${head}\n${body}\n${end}\n$`);
+ return new RegExp(`^${head}${rfc1421Header}\n${body}\n${end}\n$`);
}
const pkcs1PubExp = getRegExpForPEM('RSA PUBLIC KEY');
const pkcs1PrivExp = getRegExpForPEM('RSA PRIVATE KEY');
+const pkcs1EncExp = (cipher) => getRegExpForPEM('RSA PRIVATE KEY', cipher);
const spkiExp = getRegExpForPEM('PUBLIC KEY');
const pkcs8Exp = getRegExpForPEM('PRIVATE KEY');
const pkcs8EncExp = getRegExpForPEM('ENCRYPTED PRIVATE KEY');
const sec1Exp = getRegExpForPEM('EC PRIVATE KEY');
+const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher);
// Since our own APIs only accept PEM, not DER, we need to convert DER to PEM
// for testing.
@@ -137,6 +141,42 @@ function convertDERToPEM(label, der) {
testEncryptDecrypt(publicKey, privateKey);
testSignVerify(publicKey, privateKey);
}));
+
+ // Now do the same with an encrypted private key.
+ generateKeyPair('rsa', {
+ publicExponent: 0x10001,
+ modulusLength: 4096,
+ publicKeyEncoding: {
+ type: 'pkcs1',
+ format: 'der'
+ },
+ privateKeyEncoding: {
+ type: 'pkcs1',
+ format: 'pem',
+ cipher: 'aes-256-cbc',
+ passphrase: 'secret'
+ }
+ }, common.mustCall((err, publicKeyDER, privateKey) => {
+ assert.ifError(err);
+
+ // The public key is encoded as DER (which is binary) instead of PEM. We
+ // will still need to convert it to PEM for testing.
+ assert(Buffer.isBuffer(publicKeyDER));
+ const publicKey = convertDERToPEM('RSA PUBLIC KEY', publicKeyDER);
+ assertApproximateSize(publicKey, 720);
+
+ assert.strictEqual(typeof privateKey, 'string');
+ assert(pkcs1EncExp('AES-256-CBC').test(privateKey));
+
+ // Since the private key is encrypted, signing shouldn't work anymore.
+ assert.throws(() => {
+ testSignVerify(publicKey, privateKey);
+ }, /bad decrypt|asn1 encoding routines/);
+
+ const key = { key: privateKey, passphrase: 'secret' };
+ testEncryptDecrypt(publicKey, key);
+ testSignVerify(publicKey, key);
+ }));
}
{
@@ -203,6 +243,36 @@ function convertDERToPEM(label, der) {
testSignVerify(publicKey, privateKey);
}));
+
+ // Do the same with an encrypted private key.
+ generateKeyPair('ec', {
+ namedCurve: 'prime256v1',
+ paramEncoding: 'named',
+ publicKeyEncoding: {
+ type: 'spki',
+ format: 'pem'
+ },
+ privateKeyEncoding: {
+ type: 'sec1',
+ format: 'pem',
+ cipher: 'aes-128-cbc',
+ passphrase: 'secret'
+ }
+ }, common.mustCall((err, publicKey, privateKey) => {
+ assert.ifError(err);
+
+ assert.strictEqual(typeof publicKey, 'string');
+ assert(spkiExp.test(publicKey));
+ assert.strictEqual(typeof privateKey, 'string');
+ assert(sec1EncExp('AES-128-CBC').test(privateKey));
+
+ // Since the private key is encrypted, signing shouldn't work anymore.
+ assert.throws(() => {
+ testSignVerify(publicKey, privateKey);
+ }, /bad decrypt|asn1 encoding routines/);
+
+ testSignVerify(publicKey, { key: privateKey, passphrase: 'secret' });
+ }));
}
{
@@ -640,7 +710,7 @@ function convertDERToPEM(label, der) {
});
}
- // Attempting to encrypt a non-PKCS#8 key.
+ // Attempting to encrypt a DER-encoded, non-PKCS#8 key.
for (const type of ['pkcs1', 'sec1']) {
common.expectsError(() => {
generateKeyPairSync(type === 'pkcs1' ? 'rsa' : 'ec', {
@@ -649,7 +719,7 @@ function convertDERToPEM(label, der) {
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: {
type,
- format: 'pem',
+ format: 'der',
cipher: 'aes-128-cbc',
passphrase: 'hello'
}