0

I have in my backend a simple system for encrypting and compressing data.

Backend NodeJS

export const aesEncrypt = (text: string, key: string = ENCRYPTION_KEY) => {
    let iv = randomBytes(IV_LENGTH);
    let cipher = createCipheriv('aes-256-cbc', Buffer.from(key), iv);
    let encrypted = cipher.update(text);
    encrypted = Buffer.concat([encrypted, cipher.final()]);
    return iv.toString('hex') + ':' + encrypted.toString('hex');
}

export const textCompressToBase64Url = (text: string) => {
    return deflateSync(text).toString('base64url')
}

export const packDataForUrl = (data: string, key: string = ENCRYPTION_KEY) => {
    return textCompressToBase64Url(aesEncrypt(data, key))
}

Result string:

eJwVU8cRxDAIbIkowXUjUv8lHP55BoM2Bp_W59hmGWH0DrxKpMlumMlfgAKD2DBKEx0gJs9j2ll-D7Gfl2PAgn1dPN696eDor3dWdR4iHH3hGQRKqKVy790Dneo7VZMEelNVag-n4rKAjhn4NNCiMmqwQ7QHMjgfkk0Rd3GlyviJuxz2zJWh6-_oAd4z9WHQPMhXgQ7P3LkegZHMt9-8h_IA-qSfm5LVIxn3PMJ0DEZSefcNW4CVKMluHkfhqjdIyXSPPWdeJGeJUWjInVq4E3tCClEQq2NSDFfA1QjSi71twSRRoMMk7GtceDIzTCHm9iqjFcB3D0U-N6tTIdnnkpnf_VpHDBJ5VnVZas7DQMVUrUu5TWXZV81j378DjVsYsGhdI7j7my6mFT6HH5dxxusT6_CiKpISF-u3A8U4O-aguJbnMapTBa0R8qEf6iK_GsZoZ89ZuTkBNoCazYWwUR8nQ0jBq9xu6Vr70nMKwAHeXWSNhI4qOS6QjSvtDg_iLoQVRmfAy_RVv3yN7buUFS6MiKCf0yVsgqr8KqYYXf0zR56utsdzXLFGauMhJ7QggHSphe0bwH1DyuQJT-DGAyfgUltmP4JcPUJ0akPPB0NTW6bV-61OIGcSV7N1zcik1_67QIH1c6i3An5X41WgZZfugnkWRxYF-2LxMuskueL8dNV_z7Ub5StKPVmZ2e52Y5M3I905SlaVdG2rF9X5dFg307uxiak2vgYSruvggU07bhP5wV273c6-Z65Zd_mjb0HXXs7pe-mrA-lsHzQZNvp8z2jt4rrID89spGGlyLdsagOyWd-eX13TX1DmNhnRdkMzt0NRHivqORe3nH_9zDtg

I then try to use Pako (port of zlib for browser) in the frontend to deflate before doing a AES decrypt however i keep getting various errors:

export const textDecompressFromBase64Url = (text: string) => {
    //@ts-ignore
    const sanitizedbase64 = text.replace(/_/g, '/').replace(/-/g, '+')
    const testData = convertDataURIToBinary(sanitizedbase64)
    const inflated = inflate(testData).toLocaleString()
    return inflated
}

const convertDataURIToBinary = (base64Data: string) => {
    const raw = window.atob(base64Data);
    const rawLength = raw.length;
    let array = new Uint8Array(new ArrayBuffer(rawLength));
    for (let i = 0; i < rawLength; i++) {
        array[i] = raw.charCodeAt(i);
    }
    return array;
}

If I don't use { raw: true } I get the following which is not usable in my aes function in the inflate method:

98,51,54,101,53,97,57,49,101,56,56,99,98,98,56,50,97,54,48,97,100,99,49,50,102,99,101,101,48,102,102,99,58,98,48,53,48,51,48,52,56,102,51,49,52,101,50,50,54,48,50,51,50,57,99,54,56,53,101,99,100,57,55,54,50,51,57,54,97,99,102,56,48,51,52,49,101,55,57,52,57,98,97,55,55,99,57,48,57,49,57,97,101,51,57,54,100,100,54,97,49,49,48,54,53,97,98,57,99,98,50,48,53,50,49,53,100,53,52,55,55,55,53,101,99,101,99,53,57,97,49,49,53,56,52,99,48,50,97,102,100,100,100,53,56,97,49,102,100,98,55,51,52,48,53,102,56,56,48,57,102,101,48,50,56,50,97,56,50,101,48,56,54,50,50,50,48,53,99,98,51,99,97,49,50,56,102,100,50,51,101,100,51,100,99,53,52,102,57,54,98,55,57,49,101,52,99,48,55,52,102,50,55,57,97,54,53,54,48,51,98,55,51,100,101,51,57,54,53,99,54,49,51,55,53,48,50,54,51,102,102,55,102,55,57,98,98,49,98,99,51,51,55,101,97,102,97,97,49,52,97,48,48,101,54,99,57,54,55,99,52,99,100,101,102,52,99,98,55,54,97,50,49,99,57,49,98,51,49,50,53,52,97,55,97,102,51,56,98,48,56,100,52,53,50,52,98,99,51,54,57,49,52,51,100,100,97,102,49,50,99,51,50,55,54,56,97,57,51,51,51,100,99,54,53,52,55,50,98,53,98,52,55,102,100,48,56,54,102,98,99,57,49,52,100,49,49,52,49,49,100,101,98,102,99,52,56,49,50,54,48,52,57,98,48,99,57,100,51,57,101,56,55,102,55,99,50,50,98,49,57,48,102,99,48,49,98,51,51,100,49,54,99,99,99,98,56,53,48,98,102,55,101,49,53,56,53,100,98,48,51,55,98,99,57,98,99,97,57,56,56,100,54,100,98,52,99,101,54,55,50,56,56,57,55,52,99,101,50,50,54,56,48,99,49,51,102,55,55,99,52,102,55,57,57,51,102,51,48,50,100,51,50,100,101,53,55,53,48,101,56,53,52,99,54,49,100,100,102,97,51,57,99,101,50,98,49,56,51,101,52,51,48,49,100,50,97,99,102,50,48,55,100,101,53,53,50,54,48,100,53,56,99,102,51,97,51,100,56,51,99,98,97,101,54,98,99,54,56,49,57,48,100,50,52,100,52,57,52,56,101,97,100,56,51,53,49,98,54,56,51,99,51,98,50,98,55,56,99,54,97,51,49,53,57,50,100,98,50,102,100,50,52,99,48,49,98,102,50,101,100,50,57,55,53,98,56,51,49,56,54,99,102,51,56,100,57,56,57,50,48,49,101,48,48,53,56,56,102,55,48,98,56,102,53,57,102,57,50,56,49,48,99,52,49,55,53,51,101,57,56,99,57,53,100,49,57,48,97,57,50,98,48,49,102,48,51,51,49,56,49,51,53,98,99,48,101,98,100,100,52,54,57,52,48,99,101,49,100,99,54,48,49,102,54,49,49,101,57,56,98,56,100,49,98,101,99,98,48,97,99,99,57,51,50,55,100,57,48,50,54,101,55,100,51,50,53,48,55,48,102,52,52,52,49,57,54,54,101,100,52,51,56,52,49,53,53,51,97,100,98,102,100,51,49,57,53,57,52,55,50,98,52,97,53,53,48,98,54,57,99,102,57,53,49,100,102,52,100,57,54,53,52,54,98,53,100,48,98,48,50,53,98,50,98,98,56,101,57,56,48,51,101,55,98,52,100,56,52,97,52,51,102,98,49,48,101,54,49,102,98,48,55,50,101,56,99,99,101,97,50,48,99,97,100,56,98,52,53,102,100,52,49,101,51,54,49,98,53,99,53,101,52,102,101,53,57,101,97,56,51,53,48,52,54,102,99,49,101,97,100,99,57,98,56,50,56,52,101,49,49,100,55,50,55,100,48,51,53,102,55,57,57,101,50,49,53,57,55,101,54,98,49,55,53,101,52,101,53,57,55,99,102,57,97,56,98,54,52,53,100,48,51,57,98,53,100,57,100,56,56,101,99,50,52,55,52,57,51,97,53,56,101,97,97,97,57,53,101,101,49,52,56,52,99,48,100,97,52,100,50,57,51,56,55,57,102,101,54,56,97,102,102,52,101,101,99,102,53,50,56,100,100,99,50,55,56,57,48,57,98,100,101,99,97,53,102,51,53,99,57,54,56,52,99,100,98,52,100,101,56,51,55,56,48,52,98,57,53,56,51,99,54,48,54,99,57,49,53,50,49,51,97,48,55,99,98,97,57,56,54,56,56,101,56,57,53,99,100,55,98,98,56,49,57,100,53,52,54,97,51,51,99,102,101,55,55,50,52,99,98,55,50,53,102,50,49,99,53,99,51,48,54,57,49,51,55,54,102,53,100,55,99,98,49,48,99,51,97,49,54,102,54,48,52,48,102,100,52,99,97,101,52,101,100,51,99,51,100,101,98,48,53,50,55,53,53,56,56,97,98,50,99,99,53,102,56,49,49,56,100,55,99,53,99,99,56,100,52,98,100,57,98,102,98,49,54,54,55,49,51,57,54

I have try to convert this to hex as I do in the backend but it is not working

If I pass the {raw: true} I get the following:

invalid code lengths set

In the backend however i'm able to inflate and decrypt with zlib with no issue:

export const textDecompressFromBase64Url = (text: string) => {
    return inflateSync(Buffer.from(text, 'base64')).toString()
}

export const aesDecrypt = (text: string, key: string = ENCRYPTION_KEY) => {
    let textParts = text.split(':');
    let iv = Buffer.from(textParts.shift(), 'hex');
    let encryptedText = Buffer.from(textParts.join(':'), 'hex');
    let decipher = createDecipheriv('aes-256-cbc', Buffer.from(key), iv);
    let decrypted = decipher.update(encryptedText);
    decrypted = Buffer.concat([decrypted, decipher.final()]);
    return decrypted.toString();
}

From the comments it is said that this is impossible to make it work but here is a working example in nodejs of the full circle:

https://jdoodle.com/ia/s5Y

TIMELINE:

  1. Stringify object
  2. AES encrypt the string + add the IV in front in format of hex string
  3. Deflate the string with zlib and output as base64url
  4. Inflate the string with zlib
  5. Decrypt the string with AES

The issue is using pako I'm not able to execute step 4

Mederic
  • 1,949
  • 4
  • 19
  • 36
  • If you compressed and then encrypted (which is the correct order), then on the other end you need to decrypt _before_ you decompress. – Mark Adler Jun 09 '22 at 22:58
  • In the code I put I first encrypt then I compress as i just want to reduce the size of the base64url – Mederic Jun 10 '22 at 02:47
  • You can't compress encrypted data, so there's no point in trying. – Mark Adler Jun 10 '22 at 03:08
  • Oh really ? since when a base64 string can't be compressed? It literally works in the backend with no issues I decompress a string and decrypt it with no issues. Here you go a working example https://jdoodle.com/ia/s5Y – Mederic Jun 10 '22 at 05:40
  • That's not encrypted data. That's base64 encoded encrypted data. It's absurd to base64 encode encrypted data and _then_ compress it! Just don't base64 encode it in the first place, and you already have as compact a binary representation as you can get. – Mark Adler Jun 10 '22 at 05:54
  • i'm only reducing the size or the base64 string as that is what is url friendly and passable as a param in url. So the question persists on how to make pako work the same way as zlib. – Mederic Jun 10 '22 at 06:58
  • It looks like you're _not_ compressing base64. You're compressing hexadecimal? Is that right? So encrypt : convert to hex : compress : convert to base64? If so, just leave out the conversion to hex and the compression. Simply apply base64 to the encrypted data. The only way compression might be useful here is if you compress your data _before_ encryption. Otherwise there is no need for compression. – Mark Adler Jun 10 '22 at 18:53
  • basically the zlib.inflate and the pako.zlid just dont give the same output. how can I get pako.inflate to give the same output as zlib.inflate – Mederic Jun 12 '22 at 09:08

0 Answers0