Skip to content

Instantly share code, notes, and snippets.

@vargad
Created August 5, 2023 05:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vargad/20237094fce7a0a28f0723d7ce395bb0 to your computer and use it in GitHub Desktop.
Save vargad/20237094fce7a0a28f0723d7ce395bb0 to your computer and use it in GitHub Desktop.
PubNub HIPAA compliant instant messaging encryption vulnerability

PubNub is a HIPAA-compliant instant messaging platform that supports message and file encryption using AES-256-CBC.

The provided encryption is flawed, it drops half of the entropy from the encrpytion key, effectively half of the encrpytion key is constant.

The getKey function does an SHA-256 on the provided key string to make it the required 256bit (32byte) length for the AES-256. Then it's hex encoded, doubling the length in bytes then trimmed to 32 bytes. Due to hex encoding and trimming half of the bits in the key are always the same for every encoded message or file.

https://github.com/pubnub/javascript/blob/master/src/crypto/modules/web.js#L70

async getKey(key) {
    const bKey = Buffer.from(key);
    const abHash = await crypto.subtle.digest('SHA-256', bKey.buffer);

    const abKey = Buffer.from(Buffer.from(abHash).toString('hex').slice(0, 32), 'utf8').buffer;

    return crypto.subtle.importKey('raw', abKey, 'AES-CBC', true, ['encrypt', 'decrypt']);
}
@vargad
Copy link
Author

vargad commented Aug 15, 2023

SDK users can use their encryption before sending data to publish methods if built-in encryption doesn't work well for them.

Of course they can! I was referring to HIPAA compliance in that case.
Let's say you remove the encryption from the PubNub API. Can you still advertise PubNub as HIPAA compliant service?
Let's say you keep it like this. PubNub's partner signs a BAA, but then choose not to use the encryption PubNub provides for HIPAA compliance, but do something else. Are they still HIPAA compliant?

Why you should fix this by removing hex encode:

  • PubNub hires an encryption expert and 100% sure it's okay this way, wouldn't it be easier if it's just done properly?
  • Provided this is okay for HIPAA compliance, PubNub is advertised as using AES-256 on the official website, but the provided encrypt function is less secure than AES-256, even if under the hood it's using AES-256.
  • I feel it's embarrassing to have such a mistake in a public repository.

It's a breaking change, and all the other PubNub client libraries should be changed the same way:

async getKey(key) {
    const bKey = Buffer.from(key);
    const abHash = await crypto.subtle.digest('SHA-256', bKey.buffer);

    const abKey = Buffer.from(abHash).buffer;

    return crypto.subtle.importKey('raw', abKey, 'AES-CBC', true, ['encrypt', 'decrypt']);
}

Look, I'm not working for PubNub, nor working for Snyk. I'm not paid to help. I'm just a freelancer, who run into this on a project. I just suggest to have this fixed.

Have a nice day

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment