Search code examples
node.jsencryptionrsa

Decrypt a base64 string using a RSA private key in nodeJS


NodeJS is not my first language so I'm having trouble decoding a base64-encoded string using a given private key.

The string was encrypted using the Java RSA algorithm with the RSA/ECB/OAEPWithSHA-1AndMGF1Padding transformation.

I managed to get to the following code:

import forge from "node-forge";

function decryptWithPrivateKey(encryptedBase64String: string, privateKeyString: string) {
  try {

    // Remove spaces and newlines from the privateKeyString
    privateKeyString = privateKeyString.replace(/\s/g, '');

    console.log('encryptedBase64String: ' + encryptedBase64String);
    console.log('privateKeyString: ' + privateKeyString);

    const privateKey = forge.pki.privateKeyFromPem(privateKeyString);
    
    const encryptedBuffer = Buffer.from(encryptedBase64String, 'base64');
    const encryptedBytes = forge.util.createBuffer(encryptedBuffer.toString('binary'));

    const decryptedBytes = privateKey.decrypt(encryptedBytes.bytes(), 'RSA-OAEP', {
        md: forge.md.sha1.create(),
        mgf1: {
            md: forge.md.sha1.create()
        }
    });

    return decryptedBytes.toString();
  } catch (error: any) {
    console.log(error.message);
    //throw new Error('Error: ' + error.message);
  }
}

const decryptedString = decryptWithPrivateKey(encryptedPassword, privateKey);
console.log(decryptedString);

But all I get is the error: Invalid PEM formatted message.

I'm sure that my private key is correct and my string is correctly generated. I can use it just fine in Java.

What is wrong with my code?

My string to decode is: FfKZ2sKQO6sCndb4orGYVIPGBNNsh/eWHu8Ay4MOFfess3B7IBaxBIqq6CUbmgwCbl2D0I38h7OEIO4VI1aC0lH4wMESzxPF5N6724e1SAXPEi0f/F3SA8sMy+mApZtWoUUwmeMPmDap7JII0DxuOngWwiRzwBK7KXc1ww2JLv9aPisBeTWme6QxAMgBpHREQJ9ymxVxRdxa3OyiwsrtgUDORp+z8+cvSLBQwEnjc228YJ0P1n/ggX1O6U/ytzogtVjVniw+TbSHNnZhcjHzPHs6sjYTOZFx3yoYfbh08hiUk3l7jRDXeGYNEgiBUAWY/zhn97VEgcuEYS9TQIEePw==

And my private key is the following: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDNZQq9bWwqyFKnheZOhGabLpPDWKbJeIz6YoJNDF8VlzjVnPIgr5ft5iEanvEl7qYBojq1GKzwa7vTxrLt6AHZXCB7ITfhGp4iMtVVtA+vJgBurSKkPBhVoRpewv1YbAsdEKMZ2wkopHEEuRVi5ngUEV6klccuqGiYZHapzbrw06Wpx7+dmMkB56RuWm18kKx9sMclEBk84LyGuVvkR8W86axy3MWTBPq1wHw8YDG77vBFKgOTdwfp+QsYDoZ+Eph0s9RB6Re1kyX97nXthaLJPi44knnA02VmwwDEGjX7cli2TllRwhs9SOdBheA8iNltU7erXGo9MkSLJwu3Xae5AgMBAAECggEBAKMV2KpCKQHrX52+tvifLm2HVTJlwMD2JFJnR3jwGsuk8C7E2IhVhHgUIzLlAysQS+W+L4k914tqr4/fFJHMhzNUcEH0RU9KeEdFP5k2SMHUlcFLXdc0FEphifO2Nb0wxL5GSIsuHR6VO1v5rd6CitO8Wv6qIqaMd8iQ9JutTAMNTjNG/FWCLkjkWBdtulUOrprlNAmJ4KTKG2ZXVMdjuYFq7++w5Bhouo038jZIDfCksan4CNUAccg03cW9OKl3Vkw6jPCBKWxk/fZChzReb3kot1YQEq8+DDlSTT8xEss9FuF6caX6PRFHgNaeHOq3Eza616dgS87uJbZ8uycbU8UCgYEA5ylrb3GVVALsqI3i+yLF+SaKCxTXwZfpbZes9sUiCaDI0GP3EsJAolrBcA3/io08FTUXpqxLEH7VojJa7oPKTSmo75T5amjp3Xx4NbweFVN4R4oxfR9tgJGnnGCOF2EaLVr3ofWMQK5ObU4VqMXbaKe0dX6vvKrYAHETPuBHlBcCgYEA43bYYICjNN51ez7rHe/RsqYbRbgj8eT504OgOQdkqWAcHEe5YQu1k6bAGXfC9bmVw8ZxITLoQmjJ2ph1lJbw/1UD6VvToXwdC0U/sf4+ICdrA7Al3BS74D2caQBBAy9AL5My7PtECCBBcNCPDMg9PDPLtbv6JAiyugfkdLdzdK8CgYAy1mQfTT6HDGGZrCKoEnyxj606RKoylEMs6/eJCc+ziF3Bnsp+oKPwUL9L8ngps2fsThHWgPu9M/etxR9EZ019bNUPY5b6tPoB0NbrEmUXUZUZPqYlm1zMsrvG42E8eQl1whTF1Ke0reDnnw2aYXEgcgl48ZSajIQWjMerw01anwKBgCsag0hOOB81pKeVNbK3llI3PeXJTi5xiJH3WG5WI1IhX1JQmSV1tZPkPnTVCAHOiD3QJfH3lqG2/8FHsMhWjhakgpg/CWyJe2t+VOKi3hzzu0i4oYQB/dQxeKlBHhC/bHdXeogD2VF840nAi8sNSuVUn16x32XirBOqmTUw6lULAoGBAK41Wu99ZlLRpqRuWTSqyuF2H46Vq3fa0spm4OsULMMZZgVYVev11sFtakQUp4AUw/QsgnEjtZdzg05dUZDDOBsYvyUVYUi1AMGDYI3Zw8UsmzqqH9dNjweO1zAGgVAvh1/HIgi8pwpIyaDOPx9NJnXhOO+pUU3C0z1kSBo9uiLM


Solution

  • As noted by @Topaco, my key is a Base64 encoded ASN.1/DER encoded private RSA key (in PKCS#8 format) and I don't want to change it.

    @President Jame K. Polk suggest to use privateKeyFromAsn1() so I change my code to the following:

    function decryptWithPrivateKey(encryptedBase64String: string, privateKeyBase64String: string) {
      try {
    
        // Remove spaces and newlines from the privateKeyBase64
        privateKeyBase64String = privateKeyBase64String.replace(/\s/g, '');
    
        console.log('encryptedBase64String: ' + encryptedBase64String);
        console.log('privateKeyBase64String: ' + privateKeyBase64String);
    
        // Decode Base64 encoded private key to binary
        const privateKeyBinary = forge.util.decode64(privateKeyBase64String);
        
        // Importing the DER encoded key directly
        const privateKey = forge.pki.privateKeyFromAsn1(forge.asn1.fromDer(privateKeyBinary));
        
        const encryptedBuffer = Buffer.from(encryptedBase64String, 'base64');
        const encryptedBytes = forge.util.createBuffer(encryptedBuffer.toString('binary'));
    
        const decryptedBytes = privateKey.decrypt(encryptedBytes.bytes(), 'RSA-OAEP', {
            md: forge.md.sha1.create(),
            mgf1: {
                md: forge.md.sha1.create()
            }
        });
    
        return decryptedBytes.toString();
      } catch (error: any) {
        console.log(error.message);
        //throw new Error('Error: ' + error.message);
      }
    }
    

    That managed to fix my problem!

    Ps: Edited to import the DER encoded key directly, as said by @Topaco on a comment