summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTorben <torben.letorbi@gmail.com>2015-12-06 19:41:13 +0100
committerTorben <torben.letorbi@gmail.com>2015-12-06 19:42:25 +0100
commit82d0b3e7f98a16c48e65e898c95dbf71d0456bd3 (patch)
tree6a8a0d093f65151452f71ee910b58971a31349b1
parent040eb03dd0f7a9d5799b5c0c3f8c32212ab6b489 (diff)
downloadsjcl-82d0b3e7f98a16c48e65e898c95dbf71d0456bd3.zip
sjcl-82d0b3e7f98a16c48e65e898c95dbf71d0456bd3.tar.gz
sjcl-82d0b3e7f98a16c48e65e898c95dbf71d0456bd3.tar.bz2
Add AES mode of operation: CTR
-rw-r--r--core/ctr.js84
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);
+ }
+ };
+};