This commit is contained in:
Mike Hamburg 2011-04-19 13:13:44 -07:00
commit 393b4d17d0
4 changed files with 17 additions and 16 deletions

View File

@ -136,13 +136,13 @@ sjcl.mode.ccm = {
// mac the data itself
macData = w.concat(macData, adata);
for (i=0; i<macData.length; i += 4) {
mac = prf.encrypt(xor(mac, macData.slice(i,i+4)));
mac = prf.encrypt(xor(mac, macData.slice(i,i+4).concat([0,0,0])));
}
}
// mac the plaintext
for (i=0; i<plaintext.length; i+=4) {
mac = prf.encrypt(xor(mac, plaintext.slice(i,i+4)));
mac = prf.encrypt(xor(mac, plaintext.slice(i,i+4).concat([0,0,0])));
}
return w.clamp(mac, tlen * 8);

View File

@ -59,10 +59,10 @@ sjcl.mode.ocb2 = {
bi = plaintext.slice(i);
bl = w.bitLength(bi);
pad = prp.encrypt(xor(delta,[0,0,0,bl]));
bi = w.clamp(xor(bi,pad), bl);
bi = w.clamp(xor(bi.concat([0,0,0]),pad), bl);
/* Checksum the final block, and finalize the checksum */
checksum = xor(checksum,xor(bi,pad));
checksum = xor(checksum,xor(bi.concat([0,0,0]),pad));
checksum = prp.encrypt(xor(checksum,xor(delta,times2(delta))));
/* MAC the header */
@ -113,7 +113,7 @@ sjcl.mode.ocb2 = {
/* Chop out and decrypt the final block */
bl = len-i*32;
pad = prp.encrypt(xor(delta,[0,0,0,bl]));
bi = xor(pad, w.clamp(ciphertext.slice(i),bl));
bi = xor(pad, w.clamp(ciphertext.slice(i),bl).concat([0,0,0]));
/* Checksum the final block, and finalize the checksum */
checksum = xor(checksum, bi);
@ -154,7 +154,7 @@ sjcl.mode.ocb2 = {
bi = adata.slice(i);
if (w.bitLength(bi) < 128) {
delta = xor(delta,times2(delta));
bi = w.concat(bi,[0x80000000|0]);
bi = w.concat(bi,[0x80000000|0,0,0,0]);
}
checksum = xor(checksum, bi);
return prp.encrypt(xor(times2(xor(delta,times2(delta))), checksum));

View File

@ -56,10 +56,10 @@ var sjcl = {
this.toString = function() { return "BUG: "+this.message; };
this.message = message;
},
/** @class Bug or missing feature in SJCL. */
/** @class Something isn't ready. */
notReady: function(message) {
this.toString = function() { return "GENERATOR NOT READY: "+this.message; };
this.toString = function() { return "NOT READY: "+this.message; };
this.message = message;
}
}

15
sjcl.js
View File

@ -1,4 +1,4 @@
"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}}};
"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"NOT READY: "+this.message};this.message=a}}};
sjcl.cipher.aes=function(a){this.m[0][0][0]||this.I();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.Q(a,0)},decrypt:function(a){return this.Q(a,1)},m:[[[],[],[],[],[]],[[],[],[],[],[]]],I: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=
@ -16,15 +16,16 @@ sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.s=this.X.slice(0
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.P(a,b,c,d,e,f);g=sjcl.mode.ccm.R(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.R(a,i,c,j,e,b);a=sjcl.mode.ccm.P(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},P: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<g.length;d+=4)f=a.encrypt(i(f,g.slice(d,d+4)))}for(d=0;d<b.length;d+=4)f=a.encrypt(i(f,b.slice(d,d+4)));return h.clamp(f,e*8)},R:function(a,b,c,d,e,f){var g,h=sjcl.bitArray;g=h.i;var i=b.length,j=h.bitLength(b);c=h.concat([h.partial(8,f-1)],c).concat([0,
0,0]).slice(0,4);d=h.bitSlice(g(d,a.encrypt(c)),0,e);if(!i)return{tag:d,data:[]};for(g=0;g<i;g+=4){c[3]++;e=a.encrypt(c);b[g]^=e[0];b[g+1]^=e[1];b[g+2]^=e[2];b[g+3]^=e[3]}return{tag:d,data:h.clamp(b,j)}}};if(sjcl.beware===undefined)sjcl.beware={};
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<g.length;d+=4)f=a.encrypt(i(f,g.slice(d,d+4).concat([0,0,0])))}for(d=0;d<b.length;d+=4)f=a.encrypt(i(f,b.slice(d,d+4).concat([0,0,0])));return h.clamp(f,e*8)},R:function(a,b,c,d,e,f){var g,h=sjcl.bitArray;g=h.i;var i=b.length,j=h.bitLength(b);c=h.concat([h.partial(8,
f-1)],c).concat([0,0,0]).slice(0,4);d=h.bitSlice(g(d,a.encrypt(c)),0,e);if(!i)return{tag:d,data:[]};for(g=0;g<i;g+=4){c[3]++;e=a.encrypt(c);b[g]^=e[0];b[g+1]^=e[1];b[g+2]^=e[2];b[g+3]^=e[3]}return{tag:d,data:h.clamp(b,j)}}};if(sjcl.beware===undefined)sjcl.beware={};
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]=function(){sjcl.mode.cbc={name:"cbc",encrypt: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");var e=sjcl.bitArray,f=e.i,g=e.bitLength(b),h=0,i=[];if(g&7)throw new sjcl.exception.invalid("pkcs#5 padding only works for multiples of a byte");for(d=0;h+128<=g;d+=4,h+=128){c=a.encrypt(f(c,
b.slice(d,d+4)));i.splice(d,0,c[0],c[1],c[2],c[3])}g=(16-(g>>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;d<b.length;d+=4){g=b.slice(d,d+4);c=f(c,a.decrypt(g));h.splice(d,0,c[0],c[1],c[2],c[3]);c=g}g=h[d-1]&255;if(g==0||g>16)throw new sjcl.exception.corrupt("pkcs#5 padding corrupt");c=g*0x1010101;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.K,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<b.length;g+=4){l=b.slice(g,g+4);k=j(k,l);l=j(c,a.encrypt(j(c,l)));m.splice(g,0,l[0],l[1],l[2],l[3]);c=h(c)}l=b.slice(g);b=i.bitLength(l);g=a.encrypt(j(c,[0,0,0,b]));l=i.clamp(j(l,g),b);k=j(k,j(l,g));k=a.encrypt(j(k,j(c,h(c))));if(d.length)k=
j(k,f?d:sjcl.mode.ocb2.pmac(a,d));return m.concat(i.concat(l,i.clamp(k,e)))},decrypt:function(a,b,c,d,e,f){if(sjcl.bitArray.bitLength(c)!==128)throw new sjcl.exception.invalid("ocb iv must be 128 bits");e=e||64;var g=sjcl.mode.ocb2.K,h=sjcl.bitArray,i=h.i,j=[0,0,0,0],k=g(a.encrypt(c)),l,m,n=sjcl.bitArray.bitLength(b)-e,o=[];d=d||[];for(c=0;c+4<n/32;c+=4){l=i(k,a.decrypt(i(k,b.slice(c,c+4))));j=i(j,l);o.splice(c,0,l[0],l[1],l[2],l[3]);k=g(k)}m=n-c*32;l=a.encrypt(i(k,[0,0,0,m]));l=i(l,h.clamp(b.slice(c),
m));j=i(j,l);j=a.encrypt(i(j,i(k,g(k))));if(d.length)j=i(j,f?d:sjcl.mode.ocb2.pmac(a,d));if(!h.equal(h.clamp(j,e),h.bitSlice(b,n)))throw new sjcl.exception.corrupt("ocb: tag doesn't match");return o.concat(h.clamp(l,m))},pmac:function(a,b){var c,d=sjcl.mode.ocb2.K,e=sjcl.bitArray,f=e.i,g=[0,0,0,0],h=a.encrypt([0,0,0,0]);h=f(h,d(d(h)));for(c=0;c+4<b.length;c+=4){h=d(h);g=f(g,a.encrypt(f(h,b.slice(c,c+4))))}b=b.slice(c);if(e.bitLength(b)<128){h=f(h,d(h));b=e.concat(b,[2147483648|0])}g=f(g,b);return a.encrypt(f(d(f(h,
d(h))),g))},K:function(a){return[a[0]<<1^a[1]>>>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.W=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;b<d;b++){c[0][b]=a[b]^909522486;c[1][b]=a[b]^1549556828}this.p[0].update(c[0]);this.p[1].update(c[1])};sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a,b){a=(new this.W(this.p[0])).update(a,b).finalize();return(new this.W(this.p[1])).update(a).finalize()};
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.K,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<b.length;g+=4){l=b.slice(g,g+4);k=j(k,l);l=j(c,a.encrypt(j(c,l)));m.splice(g,0,l[0],l[1],l[2],l[3]);c=h(c)}l=b.slice(g);b=i.bitLength(l);g=a.encrypt(j(c,[0,0,0,b]));l=i.clamp(j(l.concat([0,0,0]),g),b);k=j(k,j(l.concat([0,0,0]),g));
k=a.encrypt(j(k,j(c,h(c))));if(d.length)k=j(k,f?d:sjcl.mode.ocb2.pmac(a,d));return m.concat(i.concat(l,i.clamp(k,e)))},decrypt:function(a,b,c,d,e,f){if(sjcl.bitArray.bitLength(c)!==128)throw new sjcl.exception.invalid("ocb iv must be 128 bits");e=e||64;var g=sjcl.mode.ocb2.K,h=sjcl.bitArray,i=h.i,j=[0,0,0,0],k=g(a.encrypt(c)),l,m,n=sjcl.bitArray.bitLength(b)-e,o=[];d=d||[];for(c=0;c+4<n/32;c+=4){l=i(k,a.decrypt(i(k,b.slice(c,c+4))));j=i(j,l);o.splice(c,0,l[0],l[1],l[2],l[3]);k=g(k)}m=n-c*32;l=a.encrypt(i(k,
[0,0,0,m]));l=i(l,h.clamp(b.slice(c),m).concat([0,0,0]));j=i(j,l);j=a.encrypt(i(j,i(k,g(k))));if(d.length)j=i(j,f?d:sjcl.mode.ocb2.pmac(a,d));if(!h.equal(h.clamp(j,e),h.bitSlice(b,n)))throw new sjcl.exception.corrupt("ocb: tag doesn't match");return o.concat(h.clamp(l,m))},pmac:function(a,b){var c,d=sjcl.mode.ocb2.K,e=sjcl.bitArray,f=e.i,g=[0,0,0,0],h=a.encrypt([0,0,0,0]);h=f(h,d(d(h)));for(c=0;c+4<b.length;c+=4){h=d(h);g=f(g,a.encrypt(f(h,b.slice(c,c+4))))}b=b.slice(c);if(e.bitLength(b)<128){h=f(h,
d(h));b=e.concat(b,[2147483648|0,0,0,0])}g=f(g,b);return a.encrypt(f(d(f(h,d(h))),g))},K:function(a){return[a[0]<<1^a[1]>>>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.W=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;b<d;b++){c[0][b]=a[b]^909522486;c[1][b]=a[b]^1549556828}this.p[0].update(c[0]);this.p[1].update(c[1])};
sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a,b){a=(new this.W(this.p[0])).update(a,b).finalize();return(new this.W(this.p[1])).update(a).finalize()};
sjcl.misc.pbkdf2=function(a,b,c,d,e){c=c||1E3;if(d<0||c<0)throw sjcl.exception.invalid("invalid params to pbkdf2");if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,i,j=[],k=sjcl.bitArray;for(i=1;32*j.length<(d||1);i++){e=f=a.encrypt(k.concat(b,[i]));for(g=1;g<c;g++){f=a.encrypt(f);for(h=0;h<f.length;h++)e[h]^=f[h]}j=j.concat(e)}if(d)j=k.clamp(j,d);return j};
sjcl.random={randomWords:function(a,b){var c=[];b=this.isReady(b);var d;if(b===0)throw new sjcl.exception.notReady("generator isn't seeded");else b&2&&this.fa(!(b&1));for(b=0;b<a;b+=4){(b+1)%0x10000===0&&this.V();d=this.F();c.push(d[0],d[1],d[2],d[3])}this.V();return c.slice(0,a)},setDefaultParanoia:function(a){this.C=a},addEntropy:function(a,b,c){c=c||"user";var d,e,f=(new Date).valueOf(),g=this.w[c],h=this.isReady();d=this.O[c];if(d===undefined)d=this.O[c]=this.ca++;if(g===undefined)g=this.w[c]=0;
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;c<a.length;c++)for(e=a[c];e>0;){b++;e>>>=1}this.f[g].update([d,this.T++,2,b,f,a.length].concat(a));break;case "string":if(b===undefined)b=a.length;this.f[g].update([d,this.T++,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.U("seeded",