简体   繁体   中英

how do i reencrypt a aes encrypted private key generated using nodejs crypto

I tried to decrypt a private AES encrypted RSA key and re-encrypt it with the same AES algorithm, but a different password. I used this method to create an RSA keypair:

crypto.generateKeyPairSync('rsa', {
        modulusLength: 2048,
        publicKeyEncoding: {
          type: 'pkcs1',
          format: 'pem',
        },
        privateKeyEncoding: {
            type: 'pkcs1',
            format: 'pem',
            cipher: 'aes-256-cbc',
            passphrase: secret
        }
      });

This is an example private key generated by this method:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,B25B895829F89685570676A6C53B4E9F

xb/IOI6S1rXqxo+N1Aba1M4xCqDG8u5OGBiF/zvDnKzZ/rV7/TTVIhQouZKdq+26
XMQDWGlRx1YQqWajJUZzbvixdWR3pacRpR1Mli1WPIU3rtWwOlYVgL3TqtN19IK+
NEMMrGpbnUQmXM1M5ZExRrKYw9qPI3VJwmCuE0j19+FoYZJT/5v861RcNs18v8hz
[...]
-----END RSA PRIVATE KEY-----

I want to decrypt the private key that was encrypted using aes-256-cbc and a password and re-encrypt it using another password and the same AES algorithm.

I have already tried the following method but I did not manage to get it working:

const decryptRsaPrivateKey = (privateKey, oldPassword, newPassword) => {
    const keyLines = privateKey.split('\n');

    // Extract the DEK-Info line
    var dekInfoLine = keyLines[2]

    // Extract the encryption algorithm and IV from the DEK-Info line
    const [, algorithm, ivHex] = dekInfoLine.match(/DEK-Info: (.+),(.+)/);
    const iv = Buffer.from(ivHex, 'hex');

    // Remove the DEK-Info line and the header/footer lines
    keyLines.splice(2, 1);
    keyLines.splice(0, 1);
    keyLines.splice(-1, 1);

    // Join the remaining lines and base64-decode the key
    const encodedKey = keyLines.join('');
    const decipher = crypto.createDecipheriv(algorithm, Buffer.from(oldPassword), iv);
    let decryptedKey = decipher.update(encodedKey, 'base64', 'binary');
    decryptedKey += decipher.final('binary');

    // Encrypt the key with the new password
    const cipher = crypto.createCipheriv(algorithm, Buffer.from(newPassword), iv);
    let encryptedKey = cipher.update(decryptedKey, 'binary', 'base64');
    encryptedKey += cipher.final('base64');

    // Add the DEK-Info line and the header/footer lines
    const dekInfo = `DEK-Info: ${algorithm},${iv.toString('hex')}`;
    return `-----BEGIN RSA PRIVATE KEY-----\n${dekInfo}\n\n${encryptedKey}\n-----END RSA PRIVATE KEY-----`;
}

This was the error I got from this method:

node:internal/crypto/cipher:116
    this[kHandle].initiv(cipher, credential, iv, authTagLength);
                  ^

RangeError: Invalid key length
    at Decipheriv.createCipherBase (node:internal/crypto/cipher:116:19)
    at Decipheriv.createCipherWithIV (node:internal/crypto/cipher:135:3)
    at new Decipheriv (node:internal/crypto/cipher:289:3)
    at Object.createDecipheriv (node:crypto:149:10)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Module._load (node:internal/modules/cjs/loader:878:12) {
  code: 'ERR_CRYPTO_INVALID_KEYLEN'
}

I also read the documentation from node, but I found nothing that could help me.

Thank you in advance.

A key is usually imported with crypto.createPrivateKey() . This is also true for an encrypted key, for which the password must be specified.
The export is possible withkeyObject.export() . If the key is to be encrypted, the password and algorithm must be specified.

If a password of an existing encrypted key is to be changed, the procedure is analogous: Import with the old password, export with the new password.

Example:

var crypto = require('crypto');

// Generate keypair
var secret ='secret';
var keyPair = crypto.generateKeyPairSync(
    'rsa', 
    {
        modulusLength: 2048,
        publicKeyEncoding: {type: 'pkcs1', format: 'pem'},
        privateKeyEncoding: {type: 'pkcs1', format: 'pem', cipher: 'aes-256-cbc', passphrase: secret}
    }
);

var encPkcs1Pem = keyPair.privateKey;
console.log(encPkcs1Pem);

// Import
var privateKey = crypto.createPrivateKey({key: encPkcs1Pem, type: 'pkcs1', format: 'pem', passphrase: secret});
//var privateKey = crypto.createPrivateKey({key: encPkcs1Pem, passphrase: secret}); // works also

// Export with new passphrase
var secret_2 ='another secret';
var encPkcs1Pem_2 = privateKey.export({type: 'pkcs1', format: 'pem', cipher: 'aes-256-cbc', passphrase: secret_2});
console.log(encPkcs1Pem_2);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM