From 4ecf95a3551b4abdda677e598ac89fccfe2ab471 Mon Sep 17 00:00:00 2001 From: Mike Hamburg Date: Sat, 16 Oct 2010 13:42:01 -0700 Subject: [PATCH] cbc mode. beware! --- core/cbc.js | 116 +++++++++++ sjcl.js | 37 ++-- test/cbc_test.js | 33 +++ test/cbc_vectors.js | 413 ++++++++++++++++++++++++++++++++++++++ test/run_tests_browser.js | 2 + 5 files changed, 584 insertions(+), 17 deletions(-) create mode 100644 core/cbc.js create mode 100644 test/cbc_test.js create mode 100644 test/cbc_vectors.js diff --git a/core/cbc.js b/core/cbc.js new file mode 100644 index 0000000..ac588cc --- /dev/null +++ b/core/cbc.js @@ -0,0 +1,116 @@ +/** @fileOverview CBC mode implementation + * + * @author Emily Stark + * @author Mike Hamburg + * @author Dan Boneh + */ + +/** @namespace + * Dangerous: CBC mode with PKCS#5 padding. + * + * @author Emily Stark + * @author Mike Hamburg + * @author Dan Boneh + */ +if (sjcl.beware === undefined) { + sjcl.beware = {}; +} +sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity." +] = function() { + sjcl.mode.cbc = { + /** The name of the mode. + * @constant + */ + name: "cbc", + + /** Encrypt in CBC mode with PKCS#5 padding. + * @param {Object} prp The block cipher. It must have a block size of 16 bytes. + * @param {bitArray} plaintext The plaintext data. + * @param {bitArray} iv The initialization value. + * @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(prp, plaintext, iv, adata) { + if (adata && adata.length) { + throw new sjcl.exception.invalid("cbc can't authenticate data"); + } + if (sjcl.bitArray.bitLength(iv) !== 128) { + throw new sjcl.exception.invalid("cbc iv must be 128 bits"); + } + var i, + w = sjcl.bitArray, + xor = w._xor4, + bl = w.bitLength(plaintext), + bp = 0, + output = []; + + if (bl&7) { + throw new sjcl.exception.invalid("pkcs#5 padding only works for multiples of a byte"); + } + + for (i=0; bp+128 <= bl; i+=4, bp+=128) { + /* Encrypt a non-final block */ + iv = prp.encrypt(xor(iv, plaintext.slice(i,i+4))); + output.splice(i,0,iv[0],iv[1],iv[2],iv[3]); + } + + /* Construct the pad. */ + bl = (16 - ((bl >> 3) & 15)) * 0x1010101; + + /* Pad and encrypt. */ + iv = prp.encrypt(xor(iv,w.concat(plaintext,[bl,bl,bl,bl]).slice(i,i+4))); + output.splice(i,0,iv[0],iv[1],iv[2],iv[3]); + return output; + }, + + /** Decrypt in CBC mode. + * @param {Object} prp The block cipher. It must have a block size of 16 bytes. + * @param {bitArray} ciphertext The ciphertext data. + * @param {bitArray} iv The initialization value. + * @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(prp, ciphertext, iv, adata) { + if (adata && adata.length) { + throw new sjcl.exception.invalid("cbc can't authenticate data"); + } + if (sjcl.bitArray.bitLength(iv) !== 128) { + throw new sjcl.exception.invalid("cbc iv must be 128 bits"); + } + if ((sjcl.bitArray.bitLength(ciphertext) & 127) || !ciphertext.length) { + throw new sjcl.exception.corrupt("cbc ciphertext must be a positive multiple of the block size"); + } + var i, + w = sjcl.bitArray, + xor = w._xor4, + bi, bo, + output = []; + + adata = adata || []; + + for (i=0; i 16) { + throw new sjcl.exception.corrupt("pkcs#5 padding corrupt"); + } + bo = bi * 0x1010101; + FOOOO = output; + if (!w.equal(w.bitSlice([bo,bo,bo,bo], 0, bi*8), + w.bitSlice(output, output.length*32 - bi*8, output.length*32))) { + throw new sjcl.exception.corrupt("pkcs#5 padding corrupt"); + } + + return w.bitSlice(output, 0, output.length*32 - bi*8); + } + }; +}; diff --git a/sjcl.js b/sjcl.js index 77abfde..7bbb02b 100644 --- a/sjcl.js +++ b/sjcl.js @@ -1,34 +1,37 @@ "use strict";var sjcl={cipher:{},hash:{},mode:{},misc:{},codec:{},exception:{corrupt:function(a){this.toString=function(){return"CORRUPT: "+this.message};this.message=a},invalid:function(a){this.toString=function(){return"INVALID: "+this.message};this.message=a},bug:function(a){this.toString=function(){return"BUG: "+this.message};this.message=a},notReady:function(a){this.toString=function(){return"GENERATOR NOT READY: "+this.message};this.message=a}}}; -sjcl.cipher.aes=function(a){this.l[0][0][0]||this.F();var b,c,d,e,f=this.l[0][4],g=this.l[1];b=a.length;var h=1;if(b!==4&&b!==6&&b!==8)throw new sjcl.exception.invalid("invalid aes key size");this.c=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(a%b===0||b===8&&a%b===4){c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255];if(a%b===0){c=c<<8^c>>>24^h<<24;h=h<<1^(h>>7)*283}}d[a]=d[a-b]^c}for(b=0;a;b++,a--){c=d[b&3?a:a-4];e[b]=a<=4||b<4?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^ +sjcl.cipher.aes=function(a){this.m[0][0][0]||this.F();var b,c,d,e,f=this.m[0][4],g=this.m[1];b=a.length;var h=1;if(b!==4&&b!==6&&b!==8)throw new sjcl.exception.invalid("invalid aes key size");this.c=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(a%b===0||b===8&&a%b===4){c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255];if(a%b===0){c=c<<8^c>>>24^h<<24;h=h<<1^(h>>7)*283}}d[a]=d[a-b]^c}for(b=0;a;b++,a--){c=d[b&3?a:a-4];e[b]=a<=4||b<4?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^ g[3][f[c&255]]}}; -sjcl.cipher.aes.prototype={encrypt:function(a){return this.O(a,0)},decrypt:function(a){return this.O(a,1)},l:[[[],[],[],[],[]],[[],[],[],[],[]]],F:function(){var a=this.l[0],b=this.l[1],c=a[4],d=b[4],e,f,g,h=[],i=[],j,k,l,m;for(e=0;e<0x100;e++)i[(h[e]=e<<1^(e>>7)*283)^e]=e;for(f=g=0;!c[f];f^=j||1,g=i[g]||1){l=g^g<<1^g<<2^g<<3^g<<4;l=l>>8^l&255^99;c[f]=l;d[l]=f;k=h[e=h[j=h[f]]];m=k*0x1010101^e*0x10001^j*0x101^f*0x1010100;k=h[l]*0x101^l*0x1010100;for(e=0;e<4;e++){a[e][f]=k=k<<24^k>>>8;b[e][l]=m=m<<24^m>>>8}}for(e= -0;e<5;e++){a[e]=a[e].slice(0);b[e]=b[e].slice(0)}},O:function(a,b){if(a.length!==4)throw new sjcl.exception.invalid("invalid aes block size");var c=this.c[b],d=a[0]^c[0],e=a[b?3:1]^c[1],f=a[2]^c[2];a=a[b?1:3]^c[3];var g,h,i,j=c.length/4-2,k,l=4,m=[0,0,0,0];g=this.l[b];var n=g[0],o=g[1],p=g[2],q=g[3],r=g[4];for(k=0;k>>24]^o[e>>16&255]^p[f>>8&255]^q[a&255]^c[l];h=n[e>>>24]^o[f>>16&255]^p[a>>8&255]^q[d&255]^c[l+1];i=n[f>>>24]^o[a>>16&255]^p[d>>8&255]^q[e&255]^c[l+2];a=n[a>>>24]^o[d>>16& +sjcl.cipher.aes.prototype={encrypt:function(a){return this.O(a,0)},decrypt:function(a){return this.O(a,1)},m:[[[],[],[],[],[]],[[],[],[],[],[]]],F:function(){var a=this.m[0],b=this.m[1],c=a[4],d=b[4],e,f,g,h=[],i=[],j,k,l,m;for(e=0;e<0x100;e++)i[(h[e]=e<<1^(e>>7)*283)^e]=e;for(f=g=0;!c[f];f^=j||1,g=i[g]||1){l=g^g<<1^g<<2^g<<3^g<<4;l=l>>8^l&255^99;c[f]=l;d[l]=f;k=h[e=h[j=h[f]]];m=k*0x1010101^e*0x10001^j*0x101^f*0x1010100;k=h[l]*0x101^l*0x1010100;for(e=0;e<4;e++){a[e][f]=k=k<<24^k>>>8;b[e][l]=m=m<<24^m>>>8}}for(e= +0;e<5;e++){a[e]=a[e].slice(0);b[e]=b[e].slice(0)}},O:function(a,b){if(a.length!==4)throw new sjcl.exception.invalid("invalid aes block size");var c=this.c[b],d=a[0]^c[0],e=a[b?3:1]^c[1],f=a[2]^c[2];a=a[b?1:3]^c[3];var g,h,i,j=c.length/4-2,k,l=4,m=[0,0,0,0];g=this.m[b];var n=g[0],o=g[1],p=g[2],q=g[3],r=g[4];for(k=0;k>>24]^o[e>>16&255]^p[f>>8&255]^q[a&255]^c[l];h=n[e>>>24]^o[f>>16&255]^p[a>>8&255]^q[d&255]^c[l+1];i=n[f>>>24]^o[a>>16&255]^p[d>>8&255]^q[e&255]^c[l+2];a=n[a>>>24]^o[d>>16& 255]^p[e>>8&255]^q[f&255]^c[l+3];l+=4;d=g;e=h;f=i}for(k=0;k<4;k++){m[b?3&-k:k]=r[d>>>24]<<24^r[e>>16&255]<<16^r[f>>8&255]<<8^r[a&255]^c[l++];g=d;d=e;e=f;f=a;a=g}return m}}; sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.$(a.slice(b/32),32-(b&31)).slice(1);return c===undefined?a:sjcl.bitArray.clamp(a,c-b)},extract:function(a,b,c){var d=Math.floor(-b-c&31);return((b+c-1^b)&-32?a[b/32|0]<<32-d^a[b/32+1|0]>>>d:a[b/32|0]>>>d)&(1<0&&b)a[c-1]=sjcl.bitArray.partial(b,a[c-1]&2147483648>>b-1,1);return a},partial:function(a,b,c){if(a===32)return b;return(c?b|0:b<<32-a)+a*0x10000000000},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return false;var c=0,d;for(d=0;d=32;b-=32){d.push(c);c=0}if(b===0)return d.concat(a);for(e=0;e>>b);c=a[e]<<32-b}e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,b+a>32?c:d.pop(),1));return d},o:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]}}; +a[d]^b[d];return c===0},$:function(a,b,c,d){var e;e=0;if(d===undefined)d=[];for(;b>=32;b-=32){d.push(c);c=0}if(b===0)return d.concat(a);for(e=0;e>>b);c=a[e]<<32-b}e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,b+a>32?c:d.pop(),1));return d},i:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]}}; sjcl.codec.utf8String={fromBits:function(a){var b="",c=sjcl.bitArray.bitLength(a),d,e;for(d=0;d>>24);e<<=8}return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c>>e)>>>26);if(e<6){g=a[d]<<6-e;e+=26;d++}else{g<<=6;e-=6}}for(;c.length&3&&!b;)c+="=";return c},toBits:function(a){a=a.replace(/\s|=/g,"");var b=[],c,d=0,e=sjcl.codec.base64.L,f=0,g;for(c=0;c26){d-=26;b.push(f^g>>>d);f=g<<32-d}else{d+=6;f^=g<<32-d}}d&56&&b.push(sjcl.bitArray.partial(d&56,f,1));return b}};sjcl.hash.sha256=function(a){this.c[0]||this.F();if(a){this.s=a.s.slice(0);this.m=a.m.slice(0);this.i=a.i}else this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()}; -sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.s=this.W.slice(0);this.m=[];this.i=0;return this},update:function(a){if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);var b,c=this.m=sjcl.bitArray.concat(this.m,a);b=this.i;a=this.i=b+sjcl.bitArray.bitLength(a);for(b=512+b&-512;b<=a;b+=512)this.K(c.splice(0,16));return this},finalize:function(){var a,b=this.m,c=this.s;b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0);b.push(Math.floor(this.i/ -4294967296));for(b.push(this.i|0);b.length;)this.K(b.splice(0,16));this.reset();return c},W:[],c:[],F:function(){function a(e){return(e-Math.floor(e))*0x100000000|0}var b=0,c=2,d;a:for(;b<64;c++){for(d=2;d*d<=c;d++)if(c%d===0)continue a;if(b<8)this.W[b]=a(Math.pow(c,0.5));this.c[b]=a(Math.pow(c,1/3));b++}},K:function(a){var b,c,d=a.slice(0),e=this.s,f=this.c,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=e[6],n=e[7];for(a=0;a<64;a++){if(a<16)b=d[a];else{b=d[a+1&15];c=d[a+14&15];b=d[a&15]=(b>>>7^b>>>18^ +if(d>26){d-=26;b.push(f^g>>>d);f=g<<32-d}else{d+=6;f^=g<<32-d}}d&56&&b.push(sjcl.bitArray.partial(d&56,f,1));return b}};sjcl.hash.sha256=function(a){this.c[0]||this.F();if(a){this.s=a.s.slice(0);this.n=a.n.slice(0);this.j=a.j}else this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()}; +sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.s=this.W.slice(0);this.n=[];this.j=0;return this},update:function(a){if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);var b,c=this.n=sjcl.bitArray.concat(this.n,a);b=this.j;a=this.j=b+sjcl.bitArray.bitLength(a);for(b=512+b&-512;b<=a;b+=512)this.K(c.splice(0,16));return this},finalize:function(){var a,b=this.n,c=this.s;b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0);b.push(Math.floor(this.j/ +4294967296));for(b.push(this.j|0);b.length;)this.K(b.splice(0,16));this.reset();return c},W:[],c:[],F:function(){function a(e){return(e-Math.floor(e))*0x100000000|0}var b=0,c=2,d;a:for(;b<64;c++){for(d=2;d*d<=c;d++)if(c%d===0)continue a;if(b<8)this.W[b]=a(Math.pow(c,0.5));this.c[b]=a(Math.pow(c,1/3));b++}},K:function(a){var b,c,d=a.slice(0),e=this.s,f=this.c,g=e[0],h=e[1],i=e[2],j=e[3],k=e[4],l=e[5],m=e[6],n=e[7];for(a=0;a<64;a++){if(a<16)b=d[a];else{b=d[a+1&15];c=d[a+14&15];b=d[a&15]=(b>>>7^b>>>18^ b>>>3^b<<25^b<<14)+(c>>>17^c>>>19^c>>>10^c<<15^c<<13)+d[a&15]+d[a+9&15]|0}b=b+n+(k>>>6^k>>>11^k>>>25^k<<26^k<<21^k<<7)+(m^k&(l^m))+f[a];n=m;m=l;l=k;k=j+b|0;j=i;i=h;h=g;g=b+(h&i^j&(h^i))+(h>>>2^h>>>13^h>>>22^h<<30^h<<19^h<<10)|0}e[0]=e[0]+g|0;e[1]=e[1]+h|0;e[2]=e[2]+i|0;e[3]=e[3]+j|0;e[4]=e[4]+k|0;e[5]=e[5]+l|0;e[6]=e[6]+m|0;e[7]=e[7]+n|0}}; sjcl.mode.ccm={name:"ccm",encrypt:function(a,b,c,d,e){var f,g=b.slice(0),h=sjcl.bitArray,i=h.bitLength(c)/8,j=h.bitLength(g)/8;e=e||64;d=d||[];if(i<7)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(f=2;f<4&&j>>>8*f;f++);if(f<15-i)f=15-i;c=h.clamp(c,8*(15-f));b=sjcl.mode.ccm.N(a,b,c,d,e,f);g=sjcl.mode.ccm.P(a,g,c,b,e,f);return h.concat(g.data,g.tag)},decrypt:function(a,b,c,d,e){e=e||64;d=d||[];var f=sjcl.bitArray,g=f.bitLength(c)/8,h=f.bitLength(b),i=f.clamp(b,h-e),j=f.bitSlice(b, -h-e);h=(h-e)/8;if(g<7)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(b=2;b<4&&h>>>8*b;b++);if(b<15-g)b=15-g;c=f.clamp(c,8*(15-b));i=sjcl.mode.ccm.P(a,i,c,j,e,b);a=sjcl.mode.ccm.N(a,i.data,c,d,e,b);if(!f.equal(i.tag,a))throw new sjcl.exception.corrupt("ccm: tag doesn't match");return i.data},N:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,i=h.o;e/=8;if(e%2||e<4||e>16)throw new sjcl.exception.invalid("ccm: invalid tag length");if(d.length>0xffffffff||b.length>0xffffffff)throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data"); -f=[h.partial(8,(d.length?64:0)|e-2<<2|f-1)];f=h.concat(f,c);f[3]|=h.bitLength(b)/8;f=a.encrypt(f);if(d.length){c=h.bitLength(d)/8;if(c<=65279)g=[h.partial(16,c)];else if(c<=0xffffffff)g=h.concat([h.partial(16,65534)],[c]);g=h.concat(g,d);for(d=0;d>>8*b;b++);if(b<15-g)b=15-g;c=f.clamp(c,8*(15-b));i=sjcl.mode.ccm.P(a,i,c,j,e,b);a=sjcl.mode.ccm.N(a,i.data,c,d,e,b);if(!f.equal(i.tag,a))throw new sjcl.exception.corrupt("ccm: tag doesn't match");return i.data},N:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,i=h.i;e/=8;if(e%2||e<4||e>16)throw new sjcl.exception.invalid("ccm: invalid tag length");if(d.length>0xffffffff||b.length>0xffffffff)throw new sjcl.exception.bug("ccm: can't deal with 4GiB or more data"); +f=[h.partial(8,(d.length?64:0)|e-2<<2|f-1)];f=h.concat(f,c);f[3]|=h.bitLength(b)/8;f=a.encrypt(f);if(d.length){c=h.bitLength(d)/8;if(c<=65279)g=[h.partial(16,c)];else if(c<=0xffffffff)g=h.concat([h.partial(16,65534)],[c]);g=h.concat(g,d);for(d=0;d>3&15))*0x1010101;c=a.encrypt(f(c,e.concat(b,[g,g,g,g]).slice(d,d+4)));i.splice(d,0,c[0],c[1],c[2],c[3]);return i},decrypt:function(a,b,c,d){if(d&&d.length)throw new sjcl.exception.invalid("cbc can't authenticate data");if(sjcl.bitArray.bitLength(c)!==128)throw new sjcl.exception.invalid("cbc iv must be 128 bits");if(sjcl.bitArray.bitLength(b)&127||!b.length)throw new sjcl.exception.corrupt("cbc ciphertext must be a positive multiple of the block size"); +var e=sjcl.bitArray,f=e.i,g,h=[];for(d=0;d16)throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");c=g*0x1010101;FOOOO=h;if(!e.equal(e.bitSlice([c,c,c,c],0,g*8),e.bitSlice(h,h.length*32-g*8,h.length*32)))throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");return e.bitSlice(h,0,h.length*32-g*8)}}}; +sjcl.mode.ocb2={name:"ocb2",encrypt:function(a,b,c,d,e,f){if(sjcl.bitArray.bitLength(c)!==128)throw new sjcl.exception.invalid("ocb iv must be 128 bits");var g,h=sjcl.mode.ocb2.I,i=sjcl.bitArray,j=i.i,k=[0,0,0,0];c=h(a.encrypt(c));var l,m=[];d=d||[];e=e||64;for(g=0;g+4>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^(a[0]>>>31)*135]}};sjcl.misc.hmac=function(a,b){this.V=b=b||sjcl.hash.sha256;var c=[[],[]],d=b.prototype.blockSize/32;this.p=[new b,new b];if(a.length>d)a=b.hash(a);for(b=0;b0;){b++;e>>>=1}this.f[g].update([d,this.R++,2,b,f,a.length].concat(a));break;case "string":if(b===undefined)b=a.length;this.f[g].update([d,this.R++,3,b,f,a.length]);this.f[g].update(a);break;default:throw new sjcl.exception.bug("random: addEntropy only supports number, array or string");}this.n[g]+=b;this.j+=b;if(h===0){this.isReady()!==0&&this.T("seeded", -Math.max(this.k,this.j));this.T("progress",this.getProgress())}},isReady:function(a){a=this.J[a!==undefined?a:this.C];return this.k&&this.k>=a?this.n[0]>80&&(new Date).valueOf()>this.Y?3:1:this.j>=a?2:0},getProgress:function(a){a=this.J[a?a:this.C];return this.k>=a?1["0"]:this.j>a?1["0"]:this.j/a},startCollectors:function(){if(!this.q){if(window.addEventListener){window.addEventListener("load",this.t,false);window.addEventListener("mousemove",this.u,false)}else if(document.attachEvent){document.attachEvent("onload", +this.w[c]=(this.w[c]+1)%this.f.length;switch(typeof a){case "number":break;case "object":if(b===undefined)for(c=b=0;c0;){b++;e>>>=1}this.f[g].update([d,this.R++,2,b,f,a.length].concat(a));break;case "string":if(b===undefined)b=a.length;this.f[g].update([d,this.R++,3,b,f,a.length]);this.f[g].update(a);break;default:throw new sjcl.exception.bug("random: addEntropy only supports number, array or string");}this.o[g]+=b;this.k+=b;if(h===0){this.isReady()!==0&&this.T("seeded", +Math.max(this.l,this.k));this.T("progress",this.getProgress())}},isReady:function(a){a=this.J[a!==undefined?a:this.C];return this.l&&this.l>=a?this.o[0]>80&&(new Date).valueOf()>this.Y?3:1:this.k>=a?2:0},getProgress:function(a){a=this.J[a?a:this.C];return this.l>=a?1["0"]:this.k>a?1["0"]:this.k/a},startCollectors:function(){if(!this.q){if(window.addEventListener){window.addEventListener("load",this.t,false);window.addEventListener("mousemove",this.u,false)}else if(document.attachEvent){document.attachEvent("onload", this.t);document.attachEvent("onmousemove",this.u)}else throw new sjcl.exception.bug("can't attach event");this.q=true}},stopCollectors:function(){if(this.q){if(window.removeEventListener){window.removeEventListener("load",this.t);window.removeEventListener("mousemove",this.u)}else if(window.detachEvent){window.detachEvent("onload",this.t);window.detachEvent("onmousemove",this.u)}this.q=false}},addEventListener:function(a,b){this.A[a][this.ba++]=b},removeEventListener:function(a,b){var c;a=this.A[a]; -var d=[];for(c in a)a.hasOwnProperty[c]&&a[c]===b&&d.push(c);for(b=0;b=1<this.k)this.k=c;this.H++;this.ea(b)},u:function(a){sjcl.random.addEntropy([a.x|| +var d=[];for(c in a)a.hasOwnProperty[c]&&a[c]===b&&d.push(c);for(b=0;b=1<this.l)this.l=c;this.H++;this.ea(b)},u:function(a){sjcl.random.addEntropy([a.x|| a.clientX||a.offsetX,a.y||a.clientY||a.offsetY],2,"mouse")},t:function(){sjcl.random.addEntropy(new Date,2,"loadtime")},T:function(a,b){var c;a=sjcl.random.A[a];var d=[];for(c in a)a.hasOwnProperty(c)&&d.push(a[c]);for(c=0;c 4)throw new sjcl.exception.invalid("json encrypt: invalid parameters");if(typeof a==="string"){c=sjcl.misc.cachedPbkdf2(a,f);a=c.key.slice(0,f.ks/32);f.salt=c.salt}if(typeof b==="string")b=sjcl.codec.utf8String.toBits(b);c=new sjcl.cipher[f.cipher](a);e.g(d,f);d.key=a;f.ct=sjcl.mode[f.mode].encrypt(c,b,f.iv,f.adata,f.tag);return e.encode(f)},decrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.g(e.g(e.g({},e.defaults),e.decode(b)),c,true);if(typeof b.salt==="string")b.salt=sjcl.codec.base64.toBits(b.salt); diff --git a/test/cbc_test.js b/test/cbc_test.js new file mode 100644 index 0000000..b57bb8c --- /dev/null +++ b/test/cbc_test.js @@ -0,0 +1,33 @@ +new sjcl.test.TestCase("CBC mode tests", function (cb) { + ((sjcl.beware && + sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]) || + function(){})(); + + if (!sjcl.cipher.aes || !sjcl.mode.cbc) { + this.unimplemented(); + cb && cb(); + return; + } + + var i, kat = sjcl.test.vector.cbc, 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