Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto.privateDecrypt keeps failing after "Passphrase required" error #32240

Closed
nahuel opened this issue Mar 12, 2020 · 2 comments
Closed

crypto.privateDecrypt keeps failing after "Passphrase required" error #32240

nahuel opened this issue Mar 12, 2020 · 2 comments
Labels
confirmed-bug Issues with confirmed bugs. crypto Issues and PRs related to the crypto subsystem.

Comments

@nahuel
Copy link

nahuel commented Mar 12, 2020

  • Version: v13.10.1
  • Platform: Ubuntu 18.04
  • Subsystem: crypto

If you call crypto.privateDecrypt(...) with an passphrase-encrypted private RSA key PEM but without providing a passphrase, it correctly raises TypeError: Passphrase required for encrypted key. But after that, if you try to call it again with an unencrypted private RSA key PEM, then the same error is raised. It seems like the first call corrupts some internal state (maybe openssl one) breaking subsequent calls. Example follows:

// 1- Generate RSA key pair
const crypto = require('crypto')
const pair = crypto.generateKeyPairSync('rsa', { modulusLength : 1024 })

// 2- Create a PEM uncrypted and the same one but encrypted with a passphrase
const privPEM        = pair.privateKey.export({ type : 'pkcs1', format : 'pem'})
const privPEMcrypted = pair.privateKey.export({ type : 'pkcs1', format : 'pem', 
                                                cipher : 'aes128', passphrase : 'mysecret'})

// 3- Encrypt some data with public Key, works OK.
const dataEncrypted = crypto.publicEncrypt(pair.publicKey, Buffer.from("raw data"))

// 4- Try to decrypt it using the uncrypted Priv PEM (FIRST TIME)
const decrypt = (pem) => crypto.privateDecrypt(pem, dataEncrypted).toString()

// As expected, this works ok:
console.log('decrypt privPEM 1:', decrypt(privPEM)) 

// 5- Now try to decrypt it using the crypted Priv PEM but WITHOUT specifing a
// passphrase. This will expectedly fail raising an exception:
try { 
    decrypt(privPEMcrypted)
    // => TypeError: Passphrase required for encrypted key
} catch(e) {
    console.log('Ok, I expected this error:', e)
}

// 6- Now repeat the SAME step 4, this will FAIL with the same 'Passphrase
// required for encrypted key' error from step 5, but this PEM is uncrypted, so
// we found a bug.
console.log("\n\nNow this must not fail... but it does:")

console.log('decrypt privPEM 2:', decrypt(privPEM))
// => TypeError: Passphrase required for encrypted key

Output:

$ node test-crypto-bug.js 
decrypt privPEM 1: raw data
Ok, I expected this error: TypeError: Passphrase required for encrypted key
    at Object.privateDecrypt (internal/crypto/cipher.js:63:12)
    at decrypt (/tmp/test-crypto-bug.js:14:33)
    at Object.<anonymous> (/tmp/test-crypto-bug.js:22:5)
    at Module._compile (internal/modules/cjs/loader.js:1147:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1167:10)
    at Module.load (internal/modules/cjs/loader.js:996:32)
    at Function.Module._load (internal/modules/cjs/loader.js:896:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47 {
  code: 'ERR_MISSING_PASSPHRASE'
}


Now this must not fail... but it does:
internal/crypto/cipher.js:63
    return method(data, format, type, passphrase, buffer, padding, oaepHash,
           ^

TypeError: Passphrase required for encrypted key
    at Object.privateDecrypt (internal/crypto/cipher.js:63:12)
    at decrypt (/tmp/test-crypto-bug.js:14:33)
    at Object.<anonymous> (/tmp/test-crypto-bug.js:33:35)
    at Module._compile (internal/modules/cjs/loader.js:1147:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1167:10)
    at Module.load (internal/modules/cjs/loader.js:996:32)
    at Function.Module._load (internal/modules/cjs/loader.js:896:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47 {
  code: 'ERR_MISSING_PASSPHRASE'
}
/tmp$ 
bnoordhuis added a commit to bnoordhuis/io.js that referenced this issue Mar 13, 2020
The publicEncrypt/privateDecrypt/etc. family of functions didn't clear
OpenSSL's error stack on early return.

Notably, trying to use an encrypted key with the wrong passphrase left
an error on the stack that made subsequent encrypt or decrypt operations
fail, even with an unencrypted key.

Fixes: nodejs#32240
@bnoordhuis bnoordhuis added confirmed-bug Issues with confirmed bugs. crypto Issues and PRs related to the crypto subsystem. labels Mar 13, 2020
@bnoordhuis
Copy link
Member

Thanks for the bug report. #32248 should fix that.

addaleax pushed a commit that referenced this issue Mar 30, 2020
The publicEncrypt/privateDecrypt/etc. family of functions didn't clear
OpenSSL's error stack on early return.

Notably, trying to use an encrypted key with the wrong passphrase left
an error on the stack that made subsequent encrypt or decrypt operations
fail, even with an unencrypted key.

Fixes: #32240

PR-URL: #32248
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
targos pushed a commit that referenced this issue Apr 22, 2020
The publicEncrypt/privateDecrypt/etc. family of functions didn't clear
OpenSSL's error stack on early return.

Notably, trying to use an encrypted key with the wrong passphrase left
an error on the stack that made subsequent encrypt or decrypt operations
fail, even with an unencrypted key.

Fixes: #32240

PR-URL: #32248
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
@tada5hi
Copy link

tada5hi commented Nov 12, 2021

This is still a problem in v16.7.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug Issues with confirmed bugs. crypto Issues and PRs related to the crypto subsystem.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants