Search code examples
node.jsencryptionnode-cryptojsencrypt

Node crypto instead of JSEncrypt for encryption with public key


I have some public key which looks like MIIBIjANBgkqhkiG9w0BAQEFAAO... (392 chars). It used in the browser to encrypt some strings with JSEncrypt.

How can I encrypt strings with that public key using NodeJS crypto module?

I tried this:

const crypto = require('crypto')
const encrypted = crypto.publicEncrypt('MIIBIjA....', '111111')
console.log(encrypted.toString('base64'))

But got error:0909006C:PEM routines:get_name:no start line.

I also tried to convert the public key and the string into the buffer, got the same error.


Solution

  • If the key in crypto.publicEncrypt(key, buffer) is passed as a string, then it is interpreted as PEM encoded key by default.
    A PEM encoded key consists of a header line, followed by the Base64 encoded body (i.e. the Base64 encoded data of the DER encoded key), and a footer line.
    In the posted code snippet, the header line is missing (and presumably the footer line as well), which causes the error.

    crypto.publicEncrypt(key, buffer) uses OAEP as padding by default. JSEncrypt on the other hand only supports PKCS#1 v1.5 padding. So if the implementation should be compatible to JSEncrypt, i.e. if the ciphertext should be decryptable with JSEncrypt, then PKCS#1 v1.5 padding must be specified explicitly.

    The following NodeJS code encrypts a message with the crypto module and decrypts the ciphertext with JSEncrypt:

    const crypto = require('crypto')
    const { JSEncrypt } = require('js-encrypt')
    
    const publicKey = `-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNvs/qUMjkfq2E9o0qn03+KJE7
    ASczEbn6q+kkthNBdmTsskikWsykpDPnLWhAVkmjz4alQyqw+mHYP9xhx8qUC4A3
    tXY0ObxANUUKhUvR7zNj4vk4t8F2nP3erWvaG8J+sN3Ubr40ZYIYLS6UHYRFrqRD
    CDhUtyjwERlz8KhLyQIDAQAB
    -----END PUBLIC KEY-----`
    
    const privateKey = `-----BEGIN PRIVATE KEY-----
    MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAM2+z+pQyOR+rYT2
    jSqfTf4okTsBJzMRufqr6SS2E0F2ZOyySKRazKSkM+ctaEBWSaPPhqVDKrD6Ydg/
    3GHHypQLgDe1djQ5vEA1RQqFS9HvM2Pi+Ti3wXac/d6ta9obwn6w3dRuvjRlghgt
    LpQdhEWupEMIOFS3KPARGXPwqEvJAgMBAAECgYADxGqqL7B9/pPOy3TqQuB6tuNx
    4SOGm9x76onqUisoF7LhYqJR4Be/LAKHSR2PkATpKvOcMw6lDvCbtQ+j+rSK2PkN
    4iDi1RYqbLUbZBS8vhrgU0CPlmgSSp1NBsqMK9265CaJox3frxmBK1yuf22RboIK
    pqOzcluuA4aqLegmwQJBAP0+gM/tePzx+53DrxpYQvlfi9UJo7KeqIFL8TjMziKt
    EaRGeOZ6UX/r6CQHojYKnNti7pjAwonsdwCTcv1yy7sCQQDP+/ww49VFHErON/MO
    w5iYCsrM5Lx+Yc2JAjetCDpkMrRT92cgQ0nxR5+jNeh+gE2AmB9iKlNxsHJoRaPQ
    lBRLAkEAl9hiZEp/wStXM8GhvKovfldMAPFGtlNrthtTCDvFXgVoDpgy5f9x3sIU
    74WkPcMfSmyHpA/wlcKzmCTRTicHAQJBALUjq7MQ2tAEIgqUo/W52I6i55mnpZsU
    pyOqcL8cqW5W0sNGd+SbdizTym8lJkX2jIlw8/RVFLOxjxLNhCzGqx0CQQDeUMnw
    7KGP3F7BnbsXCp64YDdihzSO5X/Mfwxw6+S/pyKZ0/X4uwt24kZuoDnFzGWJYlea
    sDQC6enIru+ne5es
    -----END PRIVATE KEY-----`
    
    // Encrypt with crypto module (RSA - PKCS#1 v1.5 Padding)
    var ciphertext = crypto.publicEncrypt(
        {
            key: publicKey,
            padding: crypto.constants.RSA_PKCS1_PADDING
        }, 
        Buffer.from('The quick brown fox jumps over the lazy dog','utf8')
    )
    console.log(ciphertext.toString('base64'))
    
    // Decrypt with JSEncrypt
    var decrypt = new JSEncrypt()
    decrypt.setPrivateKey(privateKey)
    var decrypted = decrypt.decrypt(ciphertext.toString('base64'))
    console.log(decrypted) // The quick brown fox jumps over the lazy dog