Skip to content

Node vs Browser implementations incompatibility? #81

@fredeno

Description

@fredeno

We are opening this new issue following this question on Bad MAC errors occurring sometimes when decrypting data : #63

Indeed we are facing this problem in our application. Sometimes data encrypted in the browser can't be decrypted in Node.js, sometimes data encrypted in Node.js can't be decrypted by the browser. This happens around once for 300 occurrences.

In our case, eccrypto is used classically in a Node.js backend application and also used in a React web application with the help of browserify and Node Buffer API for browser (https://github.com/feross/buffer) so that the same code can run on both environments.

We are reaching the step where we think it is an eccrypto incompatibility between browser and Node implementations but that still may be in the way we use it…

We managed to reproduce the behavior with this code :

const key = {
    privateKey: '507e1910e86cb57f66a36ae55660c66c130b60de4c2016a4d548357d054ca1a5',
    publicKey: '0499d72de2a4ac8e980ca664110d295bde3d83c122d07ac4fb6f9f34413e06b0cf20022672373968c0c19956af82864b1799141935965da8fb196348174c95bc1a'
}
const value = 'This is just a string to encrypt'
const iv = "1cb7e5a8f77f19535226730204ca6ef0"

const multipleEncrypt = async (n) => {
    const arrayOfEncrypted = []
    for (let i = 0; i < n; i++) {
        const encrypted = await eccrypto.encrypt(Buffer.from(key.publicKey, "hex"), Buffer.from(value), { iv: Buffer.from(iv, "hex") })
        const result = Buffer.from(encrypted.ephemPublicKey).toString("base64").concat(Buffer.from(encrypted.mac).toString("base64"), Buffer.from(encrypted.ciphertext).toString("base64"))
        arrayOfEncrypted.push(result)
    }
    console.log("array of encrypted values: ")
    const util = require('util')
    console.log(util.inspect(arrayOfEncrypted, { maxArrayLength: null }))
}

const multipleDecrypt = async (encrypted) => {
    for (let i = 0; i < encrypted.length; i++) {
        try {
            const ephemPublicKey = encrypted[i].substr(0, 88)
            const mac = encrypted[i].substr(88, 44)
            const ciphertext = encrypted[i].substr(132, encrypted.length)
            const data = {
                iv: Buffer.from(iv, "hex"),
                ephemPublicKey: Buffer.from(ephemPublicKey, "base64"),
                ciphertext: Buffer.from(ciphertext, "base64"),
                mac: Buffer.from(mac, "base64")
            };
            const result = await eccrypto.decrypt(Buffer.from(key.privateKey, "hex"), data)
            console.log("'" + encrypted[i] + "' decrypted => " + result.toString())
        } catch (e) {
            console.error("Cannot decrypt '" + encrypted[i] + "'", e)
        }
    }
}

First we execute multipleEncrypt(300) in Node.js which encrypts 300 times the same data with the same key and parameters.

Then we inject the resulting array of values in this code to execute it in the web application:

const arrayOfEncrypted = [
        'BIg5dEMKeM8iOm3r0Y0hgdpVRhCLl7pWQp5Rd5FV4uZKd7DMpPPpRMvyKrP7iVOhr7/6EsOvOQi0tO15nHRIap4=/ug6ZlyN07kVgpweJfy7lKKq5dDlxbfNuJ97cfD8ad8=PRG9x9R7ZOHIyLOiA9K0DgkzK7TUyHaKIb63r2PiCHjVMsUBNfFh96cItLgV97Jx',
        'BPKGILr53DScAxO/+LX6dSmDanSwtZtkskKx9MUyu3FG391glc4HUzyfKc+CTM3/jqui8Q+Pj2/nzXq2YtobOUM=NGuVEwasLdMWEQD+4B7FapCbOW2XTworwd7Oih1al4E=luxDF4Sc71d42DBfZaap+gaB3iAsa0LHZOULOaeN6lfEgtRogbGVBnsz98kYmQcE',
        // and 298 other occurrences...
        ]
multipleDecrypt(arrayOfEncrypted)

When run in the browser, all values are decrypted except one (the second one in this example) for which we get a "Bad MAC" error.

We have the same behavior when encrypting in browser and decrypting in Node.js. But when we force to use the eccrypto browser implementation in Node.js, that works perfectly! This is an interesting workaround but not very satisfying and this alternative is only available on Node anyway…

Is there something to fix in eccrypto or in the way we use it?
Thanks in advance for your help.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions