From 0245ae865f5aab613a58de09f344ca009c57a39b Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Fri, 11 Sep 2026 15:30:33 +0200 Subject: [PATCH] test: fix RSA/DSA wrong-passphrase flake Re-encrypting keys on each FIPS test run can produce ciphertext that decrypts with valid padding under the wrong password, causing a decoder error instead of the expected bad decrypt. Signed-off-by: Filip Skokan Assisted-by: Codex --- test/fixtures/keys/Makefile | 6 +- test/fixtures/keys/dsa_private_encrypted.pem | 41 ++++++------- test/fixtures/keys/rsa_private_encrypted.pem | 60 ++++++++++---------- test/parallel/test-crypto-rsa-dsa.js | 31 ++-------- test/parallel/test-tls-passphrase.js | 45 ++++----------- 5 files changed, 67 insertions(+), 116 deletions(-) diff --git a/test/fixtures/keys/Makefile b/test/fixtures/keys/Makefile index 0960e69f36fd..bad4b6aed3ca 100644 --- a/test/fixtures/keys/Makefile +++ b/test/fixtures/keys/Makefile @@ -844,7 +844,8 @@ dsa_private.pem: dsa_params.pem openssl gendsa -out dsa_private.pem dsa_params.pem dsa_private_encrypted.pem: dsa_private.pem - openssl dsa -aes256 -in dsa_private.pem -passout 'pass:password' -out dsa_private_encrypted.pem + openssl pkcs8 -topk8 -v2 aes-256-cbc -v2prf hmacWithSHA256 -iter 2048 -saltlen 16 \ + -in $< -passout 'pass:password' -out $@ dsa_private_pkcs8.pem: dsa_private.pem openssl pkcs8 -topk8 -inform PEM -outform PEM -in dsa_private.pem -out dsa_private_pkcs8.pem -nocrypt @@ -868,7 +869,8 @@ rsa_private.pem: openssl genrsa -out rsa_private.pem 2048 rsa_private_encrypted.pem: rsa_private.pem - openssl rsa -aes256 -in rsa_private.pem -passout 'pass:password' -out rsa_private_encrypted.pem + openssl pkcs8 -topk8 -v2 aes-256-cbc -v2prf hmacWithSHA256 -iter 2048 -saltlen 16 \ + -in $< -passout 'pass:password' -out $@ rsa_private_pkcs8.pem: rsa_private.pem openssl pkcs8 -topk8 -inform PEM -outform PEM -in rsa_private.pem -out rsa_private_pkcs8.pem -nocrypt diff --git a/test/fixtures/keys/dsa_private_encrypted.pem b/test/fixtures/keys/dsa_private_encrypted.pem index 49b3375baf71..88da77e0a3b7 100644 --- a/test/fixtures/keys/dsa_private_encrypted.pem +++ b/test/fixtures/keys/dsa_private_encrypted.pem @@ -1,23 +1,18 @@ ------BEGIN DSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: AES-256-CBC,FABA263DD471F214EF3E02699B837C20 - -Tj2+4x9MEIaQGFQ4o7hk12MriVYyvLO5aCbqq7LG5uhVk546/+bJc6hewdSwb6oT -MYPbuV+QTdtqshqFESA0McyGlj4w1tOg5TomP84NTKvwTO1EirVLMukfF3dqaguw -C117AZJkGbqgbi6lZ2bG0Hta6HRbhI5+ODFtOp3rKQ2KwVmtL7zw6vt3PCISeMHN -fLqikDc2+YoI9V1FJis9/FATyqV8yrJYYQQpP1RQN+gDY4SSs/eUr+Me7RNy6Lz7 -oH0tDaPGbiafwrZe1okksjxT2JQz1Q3hciBPikgdQIoE2NWTUlOeRYX0T0N2n37S -6Odbcr522e+2XjcLj34Ozthp+Q5mIDcLuakazxkXhq0RyhJ7vo+xA2YiP7Q3vH7g -oAnsJPFNVY6wJhprZi2VofKIUJUiajAXGDVX2yEIG/DOA9rnx0ZP+zopXMi4ptu0 -RzWyAL+P4jn0b8vgPf9CYJmn4VNfOcVmomZ1Bw6hzqTE2FnThJCXU3l2eaC/wcSR -uMRp8c6IM8AR5DUzUBKIckkvXj1m5iSZoKuR8dB7s9BhrRtBAI7K3G254G06sByv -0pnft8r+BkMqgdfG4rJQoQJw7tVYln+pL/gYPDuYsqyJ9kFuHDqtBvlozqXY5AL1 -XQaXoD6xMACEoJSIv5y+TzFzXwFQrDW+G1724YOSbiioUfGD0tRfjj2ei63PThQr -Z50SryfKQQf4UgcJeokMhmRWT2vPXEFWEP1b2FMEQxBy6fyKcqwZBAbhqF6usGEB -nwr/S1HXQAGEsWoc/Z4yynB7uhOwWu/Vpj+V6B98NmC7EUX15Why8zCsT9gzaIgC -M6sZafHhcmjfwc+lL9xFlU/wnAOz0LeKZWry3D0sXZn1r2FRlOJdtLLx01Sve/MU -ZRsgEDTkzv8E9dDltMeq8HQDCgLT1USTMWcY1kMELBj7y7ZdCWjH1QhTq2KlId+o -1X28zJOsOL/XRseUSlpjmSSLRw1QQEypNCY2+tcvViAvn3AifipBbdzUNhvygLhc -a2+5rYsd8BBEFnMJx7lDiyqXGnZkBbhbCSIudppNcjC+akFlFp6fBzkp4mKBuKpc -hwBBdfqdEyzqu6SVHM8nGV/aDoRuu9shV6MX0y/KnIgLedudn8aN2eLgjR5k1+99 ------END DSA PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIC1TBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQUHwLuG5KIFDnU6OC +5ADEzQICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEOrzdylfA3E36eSA +aLsD6C0EggJwrFQCTATMWun5ffHFf42epvxuRH3Dv96gOejJxmItv3fqF7cfn+oB +82gsGwdcjme6eGu7rg4lKi5e85WEImcg+xQdHnEmx62yP73CBfpzCs5KObbBd8ft +EjlqQ+EWQ68+acdHOZ/xDqBiJnkisEVEnsTo9ZE7ZLVBKRP6Hr31eQ/7EKWBb6Ax +oF+6+WgvyH8AuOO17CLjMOGO9pFl2TvJ1wsQtAIb2ZEAmPp0Z/lT9qXaoJfAz4pO +o3+2woDPDm9PA6WXF8zD+zPBwnSBSPjvkwtsMp1CdhrAxaeEo+gbDqJjCI9/2m8j +gAqkP+l7civZ7P7ydOPmlkiSdl4TXfhvfhk4RCSQbg6+YozggJO0ZiroCK7G5ro6 +4T+t2ck206kylOZV1xPrbW+Kt88vIVSxNs8dwHplEtb1VdoAV4EKfh3PEcsuSc4W +NEGvaAEmzckAMG3GJgjZYS8EWfpLsuNRcvRJsbMeQCC4Iex9m4+KJVUmMmIBlBxV +aoFEfYNGpkOdMV7l1Ne77c4HGI7NS6Yy+JcxYoc5kByTxaWOSvPSoQ3YQ+bY3GoT +tAQRvoieBnzkkyjKaS0Qgnfkdfe4Ry7hSjToo3mOnA8wj6sjRtZdIQihTa1jZ3vP +ELJ8lPTVBiPUC/AZ0C12s/JExY3y598Rlt7RQRA6ZN6PP9gnuuqR58sq/XoLnwBQ +tHK8kz5BU4EZ2neMi7noHDmArgh083WGFX6WUAfDu9R8+hydnee86Wm4xThXk5NS +TIGqwBal/5EgrSCbkcwxRw9xB0afMD4+muatKv6NEcRKT/VjhxdWP4gHONrh3tJF +/pn2+4MtHeK8 +-----END ENCRYPTED PRIVATE KEY----- diff --git a/test/fixtures/keys/rsa_private_encrypted.pem b/test/fixtures/keys/rsa_private_encrypted.pem index f1914289ec4f..6a605a055551 100644 --- a/test/fixtures/keys/rsa_private_encrypted.pem +++ b/test/fixtures/keys/rsa_private_encrypted.pem @@ -1,30 +1,30 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: AES-256-CBC,DB3D20E60E8FDC3356BD79712FF8EF7E - -K+vu0U3IFTJBBi6zW5Zng80O1jXq/ZmlOFs/j/SQpPwfW1Do9i/Dwa7ntBlTwrCm -sd3IIPgu2ikfLwxvbxsZN540oCaCqaZ/bmmyzH3MyVDA9MllUu+X8+Q3ATzcYa9R -U5XfF5DAXsSRnstCbmKagWVQpO0oX8k3ratfny6Ixq86Y82tK8+o5YiBFq1kqa+9 -4yat7IWQbqV5ifUtUPCHZwEqBt+WKazX05BqERjkckHdpfaDrBvSSPXTwoLm6uRR -ktkUVpO4tHMZ4VlcTfFtpz8gdYYod0nM6vz26hvbESHSwztSgMhmKdsE5eqmYfgu -F4WkEN4bqAiPjKK3jnUKPt/vg2oKYFQlVYFl9QnBjiRqcQTi3e9lwn1hI7uoMb6g -HuaCc57JJHPN/ZLP3ts4ZxFbwUjTGioh5Zh6WozG3L3+Ujwq/sDrAskRyzdcuP7I -Rs3oLbHY03OHyg8IbxR5Iu89l6FLqnR45yvbxXtZ7ImGOPM5Z9pB1CzDhGDx2F6g -J/Kf/7ZF2DmYUVbVKDfESEDhRfuMAVzhasDPTRqipSA5QvJVQY+J/6QDPrNNmHVB -4e4ouHIDWERUf0t1Be7THvP3X8OJozj2HApzqa5ZCaJDo8eaL8TCD5uH75ID5URJ -VscGHaUXT8/sxfHi1x8BibW5W5J/akFsnrnJU/1BZgGznIxjf5tKfHGppSIVdlKP -3ghYNmEIFPNJ6cxuUA0D2IOV4uO3FTCU6seIzvJhYkmXnticcZYGtmGxXKrodtzS -J1YuaNkkO/YRZah285lQ6QCIhCFo4Oa4ILjgoTQISuw7nQj5ESyncauzLUBXKX0c -XDUej64KNTvVF9UXdG48fYvNmSZWCnTye4UmPu17FmwpVra38U+EdoLyWyMIAI5t -rP6Hhgc9BxOo41Im9QpTcAPfKAknP8Rbm3ACJG5T9FKq/c29d1E//eFR6SL51e/a -yWdCgJN/FJOAX60+erPwoVoRFEttAeDPkklgFGdc8F4LIYAig9gEZ92ykFFz3fWz -jIcUVLrL+IokFbPVUBoMihqVyMQsWH+5Qq9wjxf6EDIf0BVtm9U4BJoOkPStFIfF -Kof7OVv7izyL8R/GIil9VQs9ftwkIUPeXx2Hw0bE3HJ3C8K4+mbLg3tKhGnBDU5Z -Xm5mLHoCRBa3ZRFWZtigX7POszdLAzftYo8o65Be4OtPS+tQAORk9gHsXATv7dDB -OGw61x5KA55LHVHhWaRvu3J8E7nhxw0q/HskyZhDC+Y+Xs6vmQSb4nO4ET4NYX1P -m3PMdgGoqRDJ2jZw4eoQdRKCM0EHSepSAYpO1tcAXhPZS4ITogoRgPpVgOebEQUL -nKNeNu/BxMSH/IH15jjDLF3TiEoguF9xdTaCxIBzE1SFpVO0u9m9vXpWdPThVgsb -VcEI487p7v9iImP3BYPT8ZYvytC26EH0hyOrwhahTvTb4vXghkLIyvPUg1lZHc6e -aPHb2AzYAHLnp/ehDQGKWrCOJ1JE2vBv8ZkLa+XZo7YASXBRZitPOMlvykEyzxmR -QAmNhKGvFmeM2mmHAp0aC03rgF3lxNsXQ1CyfEdq3UV9ReSnttq8gtrJfCwxV+wY ------END RSA PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQ2cq1Ok3DMP2A/RoK +n3/9ZgICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEGRKDlxB0C8WgbEc +enhkuocEggTQQK9exbwIpgV5QRoHDMACpXuWtsZgdpCanhtA53pP8tELYc4MzbIp +90dLQWxqi/mSlqr1ifoMnCFEAKVUV8mDoh0i5uvQhxOC6TB0HBGgb7dEgITIC7NT +PTeHNepQyW97SkTMKoTnOogxgWeAHKYsSALHJw+45q4qARE7vo1O8CHE6v6Liv4F +ZaW/8p2O4qUTRWGshUG6tC4/YN6r/iYtoSXUzOTiTeLckhV/9QsP5pGF3LQXIU9I +5xh+I1BdcSZ/7sGiHED0BB4yF2lOUKKUwCNFUTddhApewYm/yCW8wTYB7vvOI8mz +47V8rfPj40Qzislrc5Sm96XpQp8DrLV4KKkA8F1MPEchHgOcdq+1UKCRW2kfUOWS +T9wSXPHlmuKxHsrXk3pBGdnshbp2d5d4uwVhi9bPA7J2DN25ayIe9H8LbYfPo58C +CiCnjLG02nKYSLjFZR8K/z2j+xmGyXVcHuGZzR02O3G4G89VlxxfazxYbZZvSNbM +w6/TjbSDmvOYLRxRRdbZRWixgyn4QRmg5QmWBbqsS1YmVOG3HafHdAtS2B++DRF3 +S5Waaa/mrqzMesl+TLYJ759gHOqODoppm1iwmVzcBuoDLYNUI0AZZ/pEGs3oGk4M +faNiVMcsFkMWPSzgTv/viWJgJeQdWIos75nyTUgDJiFmxMT6HcWZxEFBM5IMqoZJ +JXfFGIwPo5pjw8kFHh/4Mj3qCuQ1jxrnRFdC3EhSy+JCQf0S4XTYws4GBZ4psRTX +KOb+VqizDL+0A9d88QIQX3BWfCZ6QhFHd4JdLhZt1myjsLu50NaraHBb/9pEcBUb +/hIKTxQCgXZMw1XaJeXRtbObYeB1JjPZYfuaxwvYIQ1CrPVHcCEZYH/GlQ2ppqCf +RIZY6Tp522nQ7l7uOhhJozkXZsbI5/MzaYQguz+dRAWBckQTAgStRJ2UeCP215CN +cSY/nSeIssjov+Rs2twi/AFglET7f0Osg2YXjEl6zRde80D7/74a/YASw/qGP/+q +nxwVmMpcLCfvfvb7JN0YofU5TLbOYt3lneydIe8aZhR15HlamnnZS8cs+2FeiFu2 +I4tH+7FAiB/HuYSTJSKWvTbZX100aCDqsyYW0UF4mrNgcIdjjrmWAJL2thcX5JmW ++PTTbDKGtsnGm5QUqtYHQTWelHNeWXwxveAWReG3d7v5vx+ioY1xWKkEzrRjGtNJ +nmNvFBSjlz28fxhlJ6XV3DO2N3VvPwiXLYKE99idl2mtX0WWSCcnsYEKWRSccxe7 +quwxYxWa1l4t07OUCbMCsTz4weBMc/7DK/xUSKETp/C8IR6o/F8iK49KjpIQFnjQ +abJy1RSNxRRawqDdLqZiLjAZydBq7lJ4R3LTqEdw4zQGpFdGa/YAshkCPsIGCj3q +8ONcd4TQC4qd+tBhvJiyuuwvt+an5n9Axlo93NJweTTVDgR3FLsJL2FGV0FWa9o0 +aiUYdlL1fkAPOvVT97OLjmM/9RBirSUGR+Dwr6O3tRaB1bDmpKUqTz190Lhd3Ee/ +zWOJa6ubhUjls1KY4Rm/f28VheNRp6PQn+QdIdht/1oEqlssv/yPeVe1U6tW2oDW +ksbE0O1JvbUhKKhTD3cFY6x5A7iRflJpSEEoPqbHu8X237gEtgqJcKI= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/test/parallel/test-crypto-rsa-dsa.js b/test/parallel/test-crypto-rsa-dsa.js index 7c56dcd28dc8..6e47d2a18654 100644 --- a/test/parallel/test-crypto-rsa-dsa.js +++ b/test/parallel/test-crypto-rsa-dsa.js @@ -27,42 +27,19 @@ const keyPem = fixtures.readKey('rsa_private.pem'); const rsaKeySize = 2048; const rsaPubPem = fixtures.readKey('rsa_public.pem', 'ascii'); const rsaKeyPem = fixtures.readKey('rsa_private.pem', 'ascii'); -const rsaKeyPemEncryptedLegacy = fixtures.readKey( +// Fixed ciphertexts keep wrong passwords from occasionally producing valid +// padding and a decoder error instead of the expected bad decrypt. +const rsaKeyPemEncrypted = fixtures.readKey( 'rsa_private_encrypted.pem', 'ascii'); -const rsaKeyPemEncrypted = fips3 ? - crypto.createPrivateKey(rsaKeyPem).export({ - type: 'pkcs8', - format: 'pem', - cipher: 'aes-256-cbc', - passphrase: 'password', - }) : rsaKeyPemEncryptedLegacy; const dsaPubPem = fixtures.readKey('dsa_public.pem', 'ascii'); const dsaKeyPem = fixtures.readKey('dsa_private.pem', 'ascii'); -const dsaKeyPemEncryptedLegacy = fixtures.readKey( +const dsaKeyPemEncrypted = fixtures.readKey( 'dsa_private_encrypted.pem', 'ascii'); -const dsaKeyPemEncrypted = fips3 ? - crypto.createPrivateKey(dsaKeyPem).export({ - type: 'pkcs8', - format: 'pem', - cipher: 'aes-256-cbc', - passphrase: 'password', - }) : dsaKeyPemEncryptedLegacy; const rsaPkcs8KeyPem = fixtures.readKey('rsa_private_pkcs8.pem'); const dsaPkcs8KeyPem = fixtures.readKey('dsa_private_pkcs8.pem'); const ec = new TextEncoder(); -if (fips3) { - for (const key of [rsaKeyPemEncryptedLegacy, dsaKeyPemEncryptedLegacy]) { - assert.throws(() => crypto.createPrivateKey({ - key, - passphrase: 'password', - }), { - code: 'ERR_OSSL_EVP_UNSUPPORTED', - }); - } -} - const openssl1DecryptError = { message: 'error:06065064:digital envelope routines:EVP_DecryptFinal_ex:' + 'bad decrypt', diff --git a/test/parallel/test-tls-passphrase.js b/test/parallel/test-tls-passphrase.js index 1fe2c1ec11cf..6e1b50c0bb10 100644 --- a/test/parallel/test-tls-passphrase.js +++ b/test/parallel/test-tls-passphrase.js @@ -38,33 +38,6 @@ assert(Buffer.isBuffer(cert)); assert.strictEqual(typeof passKey.toString(), 'string'); assert.strictEqual(typeof cert.toString(), 'string'); -if (hasFIPS(3)) { - const encryptedKeyOptions = { - key: passKey, - passphrase: 'password', - cert, - }; - assert.throws(() => tls.Server(encryptedKeyOptions), { - code: 'ERR_OSSL_EVP_UNSUPPORTED', - }); - assert.throws(() => tls.connect(encryptedKeyOptions), { - code: 'ERR_OSSL_EVP_UNSUPPORTED', - }); - - const server = tls.Server({ key: rawKey, passphrase: 'ignored', cert }); - server.listen(0, common.mustCall(function() { - const client = tls.connect({ - port: this.address().port, - key: rawKey, - passphrase: 'ignored', - cert, - rejectUnauthorized: false, - }, common.mustCall(() => client.end())); - client.on('close', common.mustCall(() => server.close())); - })); - return; -} - function onSecureConnect() { return common.mustCall(function() { this.end(); }); } @@ -252,6 +225,10 @@ server.listen(0, common.mustCall(function() { })).unref(); const errMessageDecrypt = /bad[ _]decrypt/i; +// TLS supplies an empty password when the passphrase is omitted. OpenSSL 4 +// FIPS rejects it during PBKDF2 password-length checks, before decryption. +const missingPassphraseError = hasFIPS(4) ? + { code: 'ERR_OSSL_PASSWORD_STRENGTH_TOO_WEAK' } : errMessageDecrypt; // Missing passphrase assert.throws(function() { @@ -261,7 +238,7 @@ assert.throws(function() { cert: cert, rejectUnauthorized: false }); -}, errMessageDecrypt); +}, missingPassphraseError); assert.throws(function() { tls.connect({ @@ -270,7 +247,7 @@ assert.throws(function() { cert: cert, rejectUnauthorized: false }); -}, errMessageDecrypt); +}, missingPassphraseError); assert.throws(function() { tls.connect({ @@ -279,14 +256,14 @@ assert.throws(function() { cert: cert, rejectUnauthorized: false }); -}, errMessageDecrypt); +}, missingPassphraseError); // Invalid passphrase assert.throws(function() { tls.connect({ port: server.address().port, key: passKey, - passphrase: 'invalid', + passphrase: 'wrong-password', cert: cert, rejectUnauthorized: false }); @@ -296,7 +273,7 @@ assert.throws(function() { tls.connect({ port: server.address().port, key: [passKey], - passphrase: 'invalid', + passphrase: 'wrong-password', cert: cert, rejectUnauthorized: false }); @@ -306,7 +283,7 @@ assert.throws(function() { tls.connect({ port: server.address().port, key: [{ pem: passKey }], - passphrase: 'invalid', + passphrase: 'wrong-password', cert: cert, rejectUnauthorized: false }); @@ -315,7 +292,7 @@ assert.throws(function() { assert.throws(function() { tls.connect({ port: server.address().port, - key: [{ pem: passKey, passphrase: 'invalid' }], + key: [{ pem: passKey, passphrase: 'wrong-password' }], passphrase: 'password', // Valid but unused cert: cert, rejectUnauthorized: false