Skip to content

Instantly share code, notes, and snippets.

@stash
Created November 21, 2014 02:15
Show Gist options
  • Select an option

  • Save stash/963809e71e03c36212ef to your computer and use it in GitHub Desktop.

Select an option

Save stash/963809e71e03c36212ef to your computer and use it in GitHub Desktop.
CBC mode bit-flipping of IV
var crypto = require('crypto');
/*
* Pretend you've got something like this stuffed into a JSON blob. Because
* the IV is not authenticated, an attacker can alter the IV to flip arbitrary
* bits in the plaintext.
*
* Solution is to use an AEAD cipher construct,
* e.g. AES-256-GCM or AES + HMAC-SHA512/256
*/
var plaintext = new Buffer(
// v
// 0123456789abcdef0123456789abcdef
'{role:1,name:"norbert"}'
);
var iv = crypto.randomBytes(128/8);
var key = crypto.randomBytes(256/8);
var cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
var ciphertext = Buffer.concat([
iv,
cipher.update(plaintext),
cipher.final()
]);
console.log('want to change role from 1 to 0, know it\'s in byte at index 6');
console.log('index:');
console.log('0123456...');
console.log(' V');
console.log('{role:1,name:"norbert"}');
console.log('\nencrypts to (IV prepended)');
console.log('hex index:');
console.log('0_1_2_3_4_5_6_7_8_9_a_b_c_d_...');
console.log(' VV');
console.log(ciphertext.toString('hex'));
var altered = new Buffer(ciphertext);
altered[6] ^= 1; // XOR to flip
console.log('\naltered to (IV prepended)');
console.log('hex index:');
console.log('0_1_2_3_4_5_6_7_8_9_a_b_c_d_...');
console.log(' VV');
console.log(altered.toString('hex'));
var newIv = altered.slice(0,16);
var rest = altered.slice(16);
var decipher = crypto.createDecipheriv('aes-256-cbc', key, newIv);
var replain = Buffer.concat([
decipher.update(rest),
decipher.final()
]).toString('utf-8');
console.log('\naltered deciphers to');
console.log('index:');
console.log('0123456...');
console.log(' V');
console.log(replain);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment