Skip to content

Commit

Permalink
Merge pull request #263 from letorbi/ctr-mode
Browse files Browse the repository at this point in the history
Add CTR mode
  • Loading branch information
Nilos committed Jan 4, 2016
2 parents 01f0eed + b09d177 commit d17529b
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 1 deletion.
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -63,6 +63,7 @@ TEST_SCRIPTS= $(TEST_COMMON) \
test/bitArray_vectors.js test/bitArray_test.js \
test/bn_vectors.js test/bn_test.js \
test/cbc_vectors.js test/cbc_test.js \
test/ctr_vectors.js test/ctr_test.js \
test/ccm_vectors.js test/ccm_test.js \
test/ecc_vectors.js test/ecc_test.js \
test/ecc_conv.js \
Expand Down
3 changes: 2 additions & 1 deletion configure
Expand Up @@ -4,7 +4,7 @@ use strict;

my ($arg, $i, $j, $targ);

my @targets = qw/sjcl aes bitArray codecString codecHex codecBase32 codecBase64 codecBytes sha256 sha512 sha1 ccm cbc ocb2 ocb2progressive gcm hmac pbkdf2 scrypt random convenience bn ecc srp ccmArrayBuffer codecArrayBuffer ripemd160/;
my @targets = qw/sjcl aes bitArray codecString codecHex codecBase32 codecBase64 codecBytes sha256 sha512 sha1 ccm ctr cbc ocb2 ocb2progressive gcm hmac pbkdf2 scrypt random convenience bn ecc srp ccmArrayBuffer codecArrayBuffer ripemd160/;
my %deps = ('aes'=>'sjcl',
'bitArray'=>'sjcl',
'codecString'=>'bitArray',
Expand All @@ -17,6 +17,7 @@ my %deps = ('aes'=>'sjcl',
'sha1'=>'codecString',
'ripemd160' => 'codecString',
'ccm'=>'bitArray,aes',
'ctr'=>'bitArray,aes',
'ocb2'=>'bitArray,aes',
'ocb2progressive'=>'ocb2',
'gcm'=>'bitArray,aes',
Expand Down
72 changes: 72 additions & 0 deletions core/ctr.js
@@ -0,0 +1,72 @@
/** @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) {
return sjcl.mode.ctr._calculate(prf, plaintext, iv, adata);
},

/** 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) {
return sjcl.mode.ctr._calculate(prf, ciphertext, iv, adata);
},

_calculate: function(prf, data, iv, adata) {
var l, bl, res, c, d, e, i;
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");
}
if (!(l = data.length)) {
return [];
}
c = iv.slice(0);
d = data.slice(0);
bl = sjcl.bitArray.bitLength(d);
for (i=0; i<l; i+=4) {
e = prf.encrypt(c);
d[i] ^= e[0];
d[i+1] ^= e[1];
d[i+2] ^= e[2];
d[i+3] ^= e[3];
c[3]++;
}
return sjcl.bitArray.clamp(d, bl);
}
};
};
36 changes: 36 additions & 0 deletions test/ctr_test.js
@@ -0,0 +1,36 @@
new sjcl.test.TestCase("CTR mode tests", function (cb) {
((sjcl.beware &&
sjcl.beware["CTR mode is dangerous because it doesn't protect message integrity."]) ||
function(){})();

if (!sjcl.cipher.aes || !sjcl.mode.ctr) {
this.unimplemented();
cb && cb();
return;
}

var i, kat = sjcl.test.vector.ctr, tv, iv, ct, aes, len, thiz=this, w=sjcl.bitArray, pt, h=sjcl.codec.hex;
browserUtil.cpsIterate(function (j, cbb) {
for (i=100*j; i<kat.length && i<100*(j+1); i++) {
tv = kat[i];
len = 4 * tv.key.length;
aes = new sjcl.cipher.aes(h.toBits(tv.key));
iv = h.toBits(tv.iv);
pt = h.toBits(tv.pt);
ct = h.toBits(tv.ct);
try {
r = sjcl.mode.ctr.encrypt(aes, pt, iv);
thiz.require(w.equal(r, ct), "aes-"+len+"-ctr-encrypt #"+i+" failed");
try {
r = sjcl.mode.ctr.decrypt(aes, ct, iv);
thiz.require(w.equal(r, pt), "aes-"+len+"-ctr-decrypt #"+i+" failed");
} catch (e) {
thiz.fail("aes-ctr-decrypt #"+i+" exception: "+e);
}
} catch (e) {
thiz.fail("aes-ctr-encrypt #"+i+" exception: "+e);
}
}
cbb();
}, 0, kat.length / 100, true, cb);
});
92 changes: 92 additions & 0 deletions test/ctr_vectors.js
@@ -0,0 +1,92 @@
/* Test vectors for CTR mode.
*
* Generated with opensll. Example line:
* echo "89b7" | xxd -r -p | openssl enc -aes-128-ctr -e -K edd235a58a408e0fc2334cac942c21af -iv d2e730833f975086589ff5ba1c956984 | xxd -p
*
*/
sjcl.test.vector.ctr = [
{ key: 'edd235a58a408e0fc2334cac942c21af',
iv: 'd2e730833f975086589ff5ba1c956984',
pt: '',
ct: '' },
{ key: 'edd235a58a408e0fc2334cac942c21af',
iv: 'd2e730833f975086589ff5ba1c956984',
pt: '00',
ct: '98'},
{ key: 'edd235a58a408e0fc2334cac942c21af',
iv: 'd2e730833f975086589ff5ba1c956984',
pt: '89b7',
ct: '1128'},
{ key: 'edd235a58a408e0fc2334cac942c21af',
iv: 'd2e730833f975086589ff5ba1c956984',
pt: 'b7fc937d',
ct: '2f63973a'},
{ key: 'edd235a58a408e0fc2334cac942c21af',
iv: 'd2e730833f975086589ff5ba1c956984',
pt: '40dc5b866923cd98',
ct: 'd8435fc18f7ad4ab'},
{ key: 'edd235a58a408e0fc2334cac942c21af',
iv: 'd2e730833f975086589ff5ba1c956984',
pt: 'e5b641941eeb811335bbc80f3b507899',
ct: '7d2945d3f8b2982069b934fc312ecb9f'},
{ key: 'edd235a58a408e0fc2334cac942c21af',
iv: 'd2e730833f975086589ff5ba1c956984',
pt: '3f8cea6d9ebd3039dddb96b0a50dc5056b84794a81cd9b455c68f2d5bd7dc9d1',
ct: 'a713ee2a78e4290a81d96a43af737603a066c110b49a6cf1b0526d26e5af39ae'},
{ key: 'a48beaa956ed4a76522e622bce69555b0defc0ad2867dd6a',
iv: '4ab495fe424477345f0eb55818566ec1',
pt: '',
ct: ''},
{ key: 'a48beaa956ed4a76522e622bce69555b0defc0ad2867dd6a',
iv: '4ab495fe424477345f0eb55818566ec1',
pt: '00',
ct: '42'},
{ key: 'a48beaa956ed4a76522e622bce69555b0defc0ad2867dd6a',
iv: '4ab495fe424477345f0eb55818566ec1',
pt: '1b35',
ct: '59a5'},
{ key: 'a48beaa956ed4a76522e622bce69555b0defc0ad2867dd6a',
iv: '4ab495fe424477345f0eb55818566ec1',
pt: '3f7c67f5',
ct: '7deca29c'},
{ key: 'a48beaa956ed4a76522e622bce69555b0defc0ad2867dd6a',
iv: '4ab495fe424477345f0eb55818566ec1',
pt: '6d4b04f72c780d0a',
ct: '2fdbc19e2bf1bbac'},
{ key: 'a48beaa956ed4a76522e622bce69555b0defc0ad2867dd6a',
iv: '4ab495fe424477345f0eb55818566ec1',
pt: '07857574e029d46eb93f0759a378a9af',
ct: '4515b01de7a062c8bbb36f7180e60b74'},
{ key: 'a48beaa956ed4a76522e622bce69555b0defc0ad2867dd6a',
iv: '4ab495fe424477345f0eb55818566ec1',
pt: '2fb8d075ac4c663b8b62436cfad3d0bef8c59aea55d1fb031f0b66e35580c570',
ct: '6d28151cabc5d09d89ee2b44d94d72659c539154de0f9e91534656c55224ec5b'},
{ key: '3d25c893d44c4a831b5df70dd4796e31da1511fbcc01050ed3136a3546587448',
iv: '6d794b58f8f72cc5176fea41d7b8103e',
pt: '',
ct: ''},
{ key: '3d25c893d44c4a831b5df70dd4796e31da1511fbcc01050ed3136a3546587448',
iv: '6d794b58f8f72cc5176fea41d7b8103e',
pt: '00',
ct: 'ec'},
{ key: '3d25c893d44c4a831b5df70dd4796e31da1511fbcc01050ed3136a3546587448',
iv: '6d794b58f8f72cc5176fea41d7b8103e',
pt: 'f619',
ct: '1aef'},
{ key: '3d25c893d44c4a831b5df70dd4796e31da1511fbcc01050ed3136a3546587448',
iv: '6d794b58f8f72cc5176fea41d7b8103e',
pt: '1612e835',
ct: 'fae40ffe'},
{ key: '3d25c893d44c4a831b5df70dd4796e31da1511fbcc01050ed3136a3546587448',
iv: '6d794b58f8f72cc5176fea41d7b8103e',
pt: '1f45ee1012d3d3dc',
ct: 'f3b309db0b75b3d5'},
{ key: '3d25c893d44c4a831b5df70dd4796e31da1511fbcc01050ed3136a3546587448',
iv: '6d794b58f8f72cc5176fea41d7b8103e',
pt: '1629613b412b367b9cf8080bb6c594b0',
ct: 'fadf86f0588d56720abc8861ffae5d78'},
{ key: '3d25c893d44c4a831b5df70dd4796e31da1511fbcc01050ed3136a3546587448',
iv: '6d794b58f8f72cc5176fea41d7b8103e',
pt: '77f1a3c4e2abe13f46e978d37eef76eca76561cbb8b5ad55a07300b32e6df3fe',
ct: '9b07440ffb0d8136d0adf8b93784bf24fbabc75def9806b33a7d06887204151e'}
];

0 comments on commit d17529b

Please sign in to comment.