diff options
author | Torben <torben.letorbi@gmail.com> | 2015-12-06 19:41:13 +0100 |
---|---|---|
committer | Torben <torben.letorbi@gmail.com> | 2015-12-06 19:42:25 +0100 |
commit | 82d0b3e7f98a16c48e65e898c95dbf71d0456bd3 (patch) | |
tree | 6a8a0d093f65151452f71ee910b58971a31349b1 | |
parent | 040eb03dd0f7a9d5799b5c0c3f8c32212ab6b489 (diff) | |
download | sjcl-82d0b3e7f98a16c48e65e898c95dbf71d0456bd3.zip sjcl-82d0b3e7f98a16c48e65e898c95dbf71d0456bd3.tar.gz sjcl-82d0b3e7f98a16c48e65e898c95dbf71d0456bd3.tar.bz2 |
Add AES mode of operation: CTR
-rw-r--r-- | core/ctr.js | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/core/ctr.js b/core/ctr.js new file mode 100644 index 0000000..e6c5510 --- /dev/null +++ b/core/ctr.js @@ -0,0 +1,84 @@ +/** @fileOverview CTR mode implementation + * + * @author Torben Haase + */ + +if (sjcl.beware === undefined) { + sjcl.beware = {}; +} +sjcl.beware["CTR mode is dangerous because it doesn't protect message integrity." +] = function() { + /** @namespace + * Dangerous: CTR mode. + * + * @author Torben Haase + */ + sjcl.mode.ctr = { + /** The name of the mode. + * @constant + */ + name: "ctr", + + /** Encrypt in CTR mode. + * @param {Object} prf The pseudorandom function. It must have a block size of 16 bytes. + * @param {bitArray} plaintext The plaintext data. + * @param {bitArray} iv The initialization value. It must be 128 bits. + * @param {bitArray} [adata=[]] The authenticated data. Must be empty. + * @return The encrypted data, an array of bytes. + * @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits, or if any adata is specified. + */ + encrypt: function(prf, plaintext, iv, adata) { + if (adata && adata.length) { + throw new sjcl.exception.invalid("ctr can't authenticate data"); + } + if (sjcl.bitArray.bitLength(iv) !== 128) { + throw new sjcl.exception.invalid("ctr iv must be 128 bits"); + } + return sjcl.mode.ctr._calculate(prf, plaintext, iv); + }, + + /** Decrypt in CTR mode. + * @param {Object} prf The pseudorandom function. It must have a block size of 16 bytes. + * @param {bitArray} ciphertext The ciphertext data. + * @param {bitArray} iv The initialization value. It must be 128 bits. + * @param {bitArray} [adata=[]] The authenticated data. It must be empty. + * @return The decrypted data, an array of bytes. + * @throws {sjcl.exception.invalid} if the IV isn't exactly 128 bits, or if any adata is specified. + * @throws {sjcl.exception.corrupt} if if the message is corrupt. + */ + decrypt: function(prf, ciphertext, iv, adata) { + if (adata && adata.length) { + throw new sjcl.exception.invalid("ctr can't authenticate data"); + } + if (sjcl.bitArray.bitLength(iv) !== 128) { + throw new sjcl.exception.invalid("ctr iv must be 128 bits"); + } + return sjcl.mode.ctr._calculate(prf, ciphertext, iv); + }, + + /** Calculate CTR. + * Encrypt or decrypt data with CTR mode. + * @param {Object} prf The pseudorandom function. + * @param {bitArray} data The data to be encrypted or decrypted. + * @param {bitArray} iv The initialization vector. + * @return {Object} The en/decryption of the data values. + * @private + */ + _calculate: function(prf, data, iv) { + var l, bl, ctr, enc, i; + if (!(l = data.length)) + return []; + bl = sjcl.bitArray.bitLength(data); + ctr = iv.slice(0); + for (i=0; i<l; i+=4) { + enc = prf.encrypt(ctr); + data[i] ^= enc[0]; + data[i+1] ^= enc[1]; + data[i+2] ^= enc[2]; + data[i+3] ^= enc[3]; + ctr[3]++; + } + return sjcl.bitArray.clamp(data, bl); + } + }; +}; |