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']);
}
Hello!
Thank you for analysis.
Even if it was a whole key, the
digest
function generates the same output for the key, which the user provides during client instantiation and won't change between function calls.The most important thing to note from the start is that the server doesn't take part in the encryption / decryption process, and all is done on the client side.
Encryption relies on a key generated by this function and a random initialization vector, which changes for each message.
The decryption process requires a key to be known, so data will be properly decrypted.
In this gist title HIPAA mentioned, is there a specific requirement which potentially has been violated?