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

Exception when using privateEncrypt/privateDecrypt with certain encrypted keys #40814

Closed
PANCHO7532B opened this issue Nov 15, 2021 · 4 comments · Fixed by #42793
Closed

Exception when using privateEncrypt/privateDecrypt with certain encrypted keys #40814

PANCHO7532B opened this issue Nov 15, 2021 · 4 comments · Fixed by #42793
Labels
confirmed-bug Issues with confirmed bugs. crypto Issues and PRs related to the crypto subsystem.

Comments

@PANCHO7532B
Copy link

Version

v16.13.0

Platform

Linux EURO01 5.4.0-88-generic #99-Ubuntu SMP Thu Sep 23 17:29:00 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Subsystem

crypto

What steps will reproduce the bug?

  1. Create an public/private RSA key-pair by using either aes-128-ecb or aes-128-ocb
  2. Attempt to decrypt/encrypt something

Code:

const crypto = require("crypto");
let {privateKey, publicKey} = crypto.generateKeyPairSync("rsa", {
    modulusLength: 2048,
    publicKeyEncoding: {
        type: "spki",
        format: "pem"
    },
    privateKeyEncoding: {
        type: 'pkcs8',
        format: 'pem',
        cipher: "aes-128-ecb",
        passphrase: "abcdef"
    }
});
const encryptedString = crypto.privateEncrypt({
    key: privateKey,
    passphrase: "abcdef"
}, Buffer.from("The quick brown fox jumps over the lazy dog")).toString("base64");
const decryptedString = crypto.publicDecrypt(publicKey, Buffer.from(encryptedString, "base64")).toString();
console.log(`Encrypted: ${encryptedString}`);
console.log(`Decrypted: ${decryptedString}`);

How often does it reproduce? Is there a required condition?

This only happens with some ciphers, some like aes-128-ccm or aes-128-cbc and other variants works just fine, other ciphers fail with an error

What is the expected behavior?

An successful encryption/decryption with the specified ciphers

What do you see instead?

node:internal/crypto/cipher:79
    return method(data, format, type, passphrase, buffer, padding, oaepHash,
           ^

Error: error:060CC07A:digital envelope routines:EVP_CIPHER_asn1_to_param:cipher parameter error
    at Object.privateEncrypt (node:internal/crypto/cipher:79:12)
    at Object.<anonymous> (/home/pancho7532/Documents/AnotherBotXDDXD/rsaTest.js:25:32)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:17:47 {
  opensslErrorStack: [
    'error:060CC07A:digital envelope routines:EVP_CIPHER_asn1_to_param:cipher parameter error'
  ],
  library: 'digital envelope routines',
  function: 'EVP_CIPHER_asn1_to_param',
  reason: 'cipher parameter error',
  code: 'ERR_OSSL_EVP_CIPHER_PARAMETER_ERROR'
}

Additional information

In v14.17.3 (the version i had previously) Node.JS would crash with a core dump on some ciphers (like GCM based ciphers)

@Mesteery Mesteery added the crypto Issues and PRs related to the crypto subsystem. label Nov 15, 2021
@tniessen tniessen changed the title Exception when using privateEncrypt/privateDecrypt on certain key types Exception when using privateEncrypt/privateDecrypt with certain encrypted keys Nov 16, 2021
@tniessen
Copy link
Member

Thank you for the report. This is an interesting one. I've been debugging this for a while now and something seems very wrong here.

Most spectacularly, in Node.js 17 (both on Windows and Ubuntu), the first attempt to load an aes-128-ecb encrypted key appears to fail, but the second succeeds:

==256055== Memcheck, a memory error detector
==256055== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==256055== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==256055== Command: node
==256055== 
Welcome to Node.js v17.1.0.
Type ".help" for more information.
> let {privateKey, publicKey} = crypto.generateKeyPairSync("rsa", {
...     modulusLength: 2048,
...     publicKeyEncoding: {
.....         type: "spki",
.....         format: "pem"
.....     },
...     privateKeyEncoding: {
.....         type: 'pkcs8',
.....         format: 'pem',
.....         cipher: "aes-128-ecb",
.....         passphrase: "abcdef"
.....     }
... });
undefined
> crypto.createPrivateKey({ key: privateKey, passphrase: 'abcdef' })
Uncaught Error: error:0300007A:digital envelope routines::cipher parameter error
    at Object.createPrivateKey (node:internal/crypto/keys:608:12) {
  library: 'digital envelope routines',
  reason: 'cipher parameter error',
  code: 'ERR_OSSL_EVP_CIPHER_PARAMETER_ERROR'
}
> crypto.createPrivateKey({ key: privateKey, passphrase: 'abcdef' })
PrivateKeyObject { [Symbol(kKeyType)]: 'private' }
> 
(To exit, press Ctrl+C again or Ctrl+D or type .exit)
> 
==256055== 
==256055== HEAP SUMMARY:
==256055==     in use at exit: 1,011,381 bytes in 2,199 blocks
==256055==   total heap usage: 84,213 allocs, 82,014 frees, 51,234,514 bytes allocated
==256055== 
==256055== LEAK SUMMARY:
==256055==    definitely lost: 0 bytes in 0 blocks
==256055==    indirectly lost: 0 bytes in 0 blocks
==256055==      possibly lost: 416 bytes in 3 blocks
==256055==    still reachable: 1,010,965 bytes in 2,196 blocks
==256055==                       of which reachable via heuristic:
==256055==                         stdstring          : 7,429 bytes in 161 blocks
==256055==         suppressed: 0 bytes in 0 blocks
==256055== Rerun with --leak-check=full to see details of leaked memory
==256055== 
==256055== For lists of detected and suppressed errors, rerun with: -s
==256055== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

@tniessen tniessen added the confirmed-bug Issues with confirmed bugs. label Nov 16, 2021
@PhilDay-CT
Copy link

I'm seeing something similar on node 16.3.1 on Ubuntu 20.04, but with a sightly different error:

Error: error:0D0C5006:asn1 encoding routines:ASN1_item_verify:EVP lib
at Object.createPrivateKey (node:internal/crypto/keys:608:12)
at readPrivateKeyBuffer (/opt/ct/node_modules/@configuredthings/sfjs-language/lib/parser/sfjsCrypto.js:51:22)
at readPrivateKeyFile (/opt/ct/node_modules/@configuredthings/sfjs-language/lib/parser/sfjsCrypto.js:43:12)
at decryptDoc (/opt/ct/node_modules/@configuredthings/sfjs-language/lib/parser/sfjsCrypto.js:748:55)
at ConfigGateway. (/opt/ct/node_modules/@configuredthings/sfjs-components/lib/ConfigGateway/ConfigGateway.js:132:66)
at ConfigGateway. (/opt/ct/node_modules/@configuredthings/sfjs-components/lib/ConfigGateway/ConfigGateway.js:59:103)
at FileMonitor. (/opt/ct/node_modules/@configuredthings/sfjs-components/lib/Abstract/FileMonitor.js:185:17)
at FileMonitor. (/opt/ct/node_modules/@configuredthings/sfjs-components/lib/Abstract/FileMonitor.js:166:18)
at FSWatcher.emit (node:events:390:28)
at FSWatcher.emitWithAll (/opt/ct/node_modules/chokidar/index.js:540:8) {
opensslErrorStack: [ 'error:0D0C5006:asn1 encoding routines:ASN1_item_verify:EVP lib' ],
library: 'asn1 encoding routines',
function: 'ASN1_item_verify',
reason: 'EVP lib',
code: 'ERR_OSSL_ASN1_EVP_LIB'
}

It doesn't seem to be a first or second call that always fails, I'm getting this both after a successful call and when this is the fist call.
What I have seen is that catching the exception and retrying the call always seems to work.

    try {
        res = crypto.createPrivateKey(key);
    }
    catch(err) {
        console.log("*** FAILED")
        console.error(err)
        try {
            res = crypto.createPrivateKey(key);
        }
        catch(err) {
            console.log("*** FAILED Again")
            console.error(err)
            throw err;
        }        
    }
    return res;
}

liuxingbaoyu added a commit to liuxingbaoyu/node that referenced this issue Apr 20, 2022
when crypto.generateKeyPairSync comes with certain parameters.
Because the error stack is not cleaned up
when crypto.generateKeyPairSync exits.

Fixes: nodejs#40814
liuxingbaoyu added a commit to liuxingbaoyu/node that referenced this issue Apr 20, 2022
crypto.generateKeyPairSync with certain parameters
Because the error stack is not cleaned up when
crypto.generateKeyPairSync exits.

Fixes: nodejs#40814
liuxingbaoyu added a commit to liuxingbaoyu/node that referenced this issue Apr 20, 2022
crypto.privateEncrypt fails for the first time after
crypto.generateKeyPairSync with certain parameters
Because the error stack is not cleaned up
when crypto.generateKeyPairSync exits.

Fixes: nodejs#40814
liuxingbaoyu added a commit to liuxingbaoyu/node that referenced this issue Apr 20, 2022
crypto.privateEncrypt fails for the first time after
crypto.generateKeyPairSync with certain parameters
Because the error stack is not cleaned up
when crypto.generateKeyPairSync exits.

Fixes: nodejs#40814
aduh95 pushed a commit that referenced this issue Oct 29, 2022
`crypto.privateEncrypt` fails for the first time after
`crypto.generateKeyPairSync` with certain parameters
because the error stack is not cleaned up
when `crypto.generateKeyPairSync` exits.

Fixes: #40814
PR-URL: #42793
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Filip Skokan <[email protected]>
RafaelGSS pushed a commit that referenced this issue Nov 1, 2022
`crypto.privateEncrypt` fails for the first time after
`crypto.generateKeyPairSync` with certain parameters
because the error stack is not cleaned up
when `crypto.generateKeyPairSync` exits.

Fixes: #40814
PR-URL: #42793
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Filip Skokan <[email protected]>
@PANCHO7532B
Copy link
Author

Alright, fix seemingly works, but for only ECB ciphers, other ciphers like -ccm -ctr -ocb -xts variants and other cipher types are still broken with more or less the same error... or a variant of it
I used the following snippet to test all ciphers given by crypto.getCiphers()

const crypto = require("crypto");
crypto.getCiphers().forEach((cipherString) => {
    console.log(`Testing: ${cipherString}`);
    if(cipherString == "des3-wrap" || cipherString == "aes128-wrap" || cipherString == "aes192-wrap" || cipherString == "aes256-wrap" || cipherString == "id-aes128-wrap" || cipherString == "id-aes128-wrap-pad" || cipherString == "id-aes192-wrap" || cipherString == "id-aes192-wrap-pad" || cipherString == "id-aes256-wrap" || cipherString == "id-aes256-wrap-pad") {
        console.log(`\x1b[33m[SKIPPED] ${cipherString} due to segmentation fault`);
        console.log("\x1b[37m"); // turn text back to white
        return;
    }
    try {
        let { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", {
            modulusLength: 2048,
            publicKeyEncoding: {
                type: "spki",
                format: "pem"
            },
            privateKeyEncoding: {
                type: 'pkcs8',
                format: 'pem',
                cipher: cipherString,
                passphrase: "abcdef"
            }
        });
        const encryptedString = crypto.privateEncrypt({
            key: privateKey,
            passphrase: "abcdef"
        }, Buffer.from("The quick brown fox jumps over the lazy dog")).toString("base64");
        const decryptedString = crypto.publicDecrypt(publicKey, Buffer.from(encryptedString, "base64")).toString();
        console.log(`\x1b[32m[PASS]`);
        console.log(`Encrypted: ${encryptedString}`);
        console.log(`Decrypted: ${decryptedString}`);
    } catch(err) {
        console.log(`\x1b[31m[FAILED] ${err.stack}`);
    }
    console.log("\x1b[37m"); // turn text back to white
});

Broken ciphers:

aes-128-ccm - error:0300006B:digital envelope routines::unsupported cipher
aes-128-ctr - error:0680006C:asn1 encoding routines::cipher has no object identifier
aes-128-gcm - error:0300007A:digital envelope routines::cipher parameter error
aes-128-ocb - error:0680006C:asn1 encoding routines::cipher has no object identifier
aes-128-xts - error:0300006B:digital envelope routines::unsupported cipher
aes-192-ccm - error:0300006B:digital envelope routines::unsupported cipher
aes-192-ctr - error:0680006C:asn1 encoding routines::cipher has no object identifier
aes-192-gcm - error:0300007A:digital envelope routines::cipher parameter error
aes-192-ocb - error:0680006C:asn1 encoding routines::cipher has no object identifier
aes-256-ccm - error:0300006B:digital envelope routines::unsupported cipher
aes-256-ctr - error:0680006C:asn1 encoding routines::cipher has no object identifier
aes-256-gcm - error:0300007A:digital envelope routines::cipher parameter error
aes-256-ocb - error:0680006C:asn1 encoding routines::cipher has no object identifier
aes-256-xts - error:0300006B:digital envelope routines::unsupported cipher
aria-128-ccm - error:0300006B:digital envelope routines::unsupported cipher
aria-128-cfb1 - error:0680006C:asn1 encoding routines::cipher has no object identifier
aria-128-cfb8 - error:0680006C:asn1 encoding routines::cipher has no object identifier
aria-128-gcm - error:0300007A:digital envelope routines::cipher parameter error
aria-192-ccm - error:0300006B:digital envelope routines::unsupported cipher
aria-192-cfb1 - error:0680006C:asn1 encoding routines::cipher has no object identifier
aria-192-cfb8 - error:0680006C:asn1 encoding routines::cipher has no object identifier
aria-192-gcm - error:0300007A:digital envelope routines::cipher parameter error
aria-256-ccm - error:0300006B:digital envelope routines::unsupported cipher
aria-256-cfb1 - error:0680006C:asn1 encoding routines::cipher has no object identifier
aria-256-cfb8 - error:0680006C:asn1 encoding routines::cipher has no object identifier
aria-256-gcm - error:0300007A:digital envelope routines::cipher parameter error
camellia-128-cfb1 - error:0680006C:asn1 encoding routines::cipher has no object identifier
camellia-128-cfb8 - error:0680006C:asn1 encoding routines::cipher has no object identifier
camellia-192-cfb1 - error:0680006C:asn1 encoding routines::cipher has no object identifier
camellia-192-cfb8 - error:0680006C:asn1 encoding routines::cipher has no object identifier
camellia-256-cfb1 - error:0680006C:asn1 encoding routines::cipher has no object identifier
camellia-256-cfb8 - error:0680006C:asn1 encoding routines::cipher has no object identifier
chacha20 - error:0680006C:asn1 encoding routines::cipher has no object identifier
chacha20-poly1305 - error:0680006C:asn1 encoding routines::cipher has no object identifier
des-ede-cbc - error:0680006C:asn1 encoding routines::cipher has no object identifier
des-ede-cfb - error:0680006C:asn1 encoding routines::cipher has no object identifier
des-ede-ofb - error:0680006C:asn1 encoding routines::cipher has no object identifier
des-ede3 - error:0680006C:asn1 encoding routines::cipher has no object identifier
des-ede3-cfb - error:0308010C:digital envelope routines::unsupported
des-ede3-cfb1 - error:0308010C:digital envelope routines::unsupported
des-ede3-cfb8 - error:0308010C:digital envelope routines::unsupported
des-ede3-ecb - error:0680006C:asn1 encoding routines::cipher has no object identifier
des-ede3-ofb - error:0680006C:asn1 encoding routines::cipher has no object identifier
id-aes128-CCM - error:0300006B:digital envelope routines::unsupported cipher
id-aes128-GCM - error:0300007A:digital envelope routines::cipher parameter error
id-aes192-CCM - error:0300006B:digital envelope routines::unsupported cipher
id-aes192-GCM - error:0300007A:digital envelope routines::cipher parameter error
id-aes256-CCM - error:0300006B:digital envelope routines::unsupported cipher
id-aes256-GCM - error:0300007A:digital envelope routines::cipher parameter error
id-smime-alg-CMS3DESwrap - error:1C800066:Provider routines::cipher operation failed

Additionally, the following ciphers throw an Segmentation fault:

aes128-wrap
aes192-wrap
aes256-wrap
id-aes128-wrap
id-aes128-wrap-pad
id-aes192-wrap
id-aes192-wrap-pad
id-aes256-wrap
id-aes256-wrap-pad

With the exception of des3-wrap who fails with error:1C800066:Provider routines::cipher operation failed before throwing the following as I try a few more times to encrypt:

corrupted size vs. prev_size
Aborted (core dumped)

Versions i tried:

  • v20.0.0-nightly2022110286088ab78e
  • v20.0.0-nightly20221101590cf569fe

I'm not really sure if these would apply for an separate issue, or it should be an continuation of this issue... or even if it should be valid, in my opinion it is since I would expect this to work with all ciphers at crypto.getCiphers() at least.

@aduh95
Copy link
Contributor

aduh95 commented Nov 2, 2022

@PANCHO7532B you should probably open a new issue, or a directly a PR if you know what is the fix.

RafaelGSS pushed a commit that referenced this issue Nov 10, 2022
`crypto.privateEncrypt` fails for the first time after
`crypto.generateKeyPairSync` with certain parameters
because the error stack is not cleaned up
when `crypto.generateKeyPairSync` exits.

Fixes: #40814
PR-URL: #42793
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Filip Skokan <[email protected]>
danielleadams pushed a commit that referenced this issue Dec 30, 2022
`crypto.privateEncrypt` fails for the first time after
`crypto.generateKeyPairSync` with certain parameters
because the error stack is not cleaned up
when `crypto.generateKeyPairSync` exits.

Fixes: #40814
PR-URL: #42793
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Filip Skokan <[email protected]>
danielleadams pushed a commit that referenced this issue Dec 30, 2022
`crypto.privateEncrypt` fails for the first time after
`crypto.generateKeyPairSync` with certain parameters
because the error stack is not cleaned up
when `crypto.generateKeyPairSync` exits.

Fixes: #40814
PR-URL: #42793
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Filip Skokan <[email protected]>
danielleadams pushed a commit that referenced this issue Jan 3, 2023
`crypto.privateEncrypt` fails for the first time after
`crypto.generateKeyPairSync` with certain parameters
because the error stack is not cleaned up
when `crypto.generateKeyPairSync` exits.

Fixes: #40814
PR-URL: #42793
Reviewed-By: Ben Noordhuis <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Filip Skokan <[email protected]>
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.

5 participants