diff --git a/core/bitArray.js b/core/bitArray.js index 03032ab7..a6d06171 100644 --- a/core/bitArray.js +++ b/core/bitArray.js @@ -50,11 +50,14 @@ sjcl.bitArray = { * @return {Number} The requested slice. */ extract: function(a, bstart, blength) { - var x, sh = (-bstart-blength) & 31; + // FIXME: this Math.floor is not necessary at all, but for some reason + // seems to suppress a bug in the Chromium JIT. + var x, sh = Math.floor((-bstart-blength) & 31); if ((bstart + blength - 1 ^ bstart) & -32) { // it crosses a boundary x = (a[bstart/32|0] << (32 - sh)) ^ (a[bstart/32+1|0] >>> sh); } else { + // within a single word x = a[bstart/32|0] >>> sh; } return x & ((1<= that, or zero otherwise. */ greaterEquals: function(that) { - if (typeof that == "number") { that = new this._class(that); } + if (typeof that === "number") { that = new this._class(that); } var less = 0, greater = 0, i, a, b; i = Math.max(this.limbs.length, that.limbs.length) - 1; for (; i>= 0; i--) { a = this.getLimb(i); b = that.getLimb(i); greater |= (b - a) & ~less; - less |= (a - b) & ~greater + less |= (a - b) & ~greater; } return (greater | ~less) >>> 31; }, @@ -122,7 +122,9 @@ sjcl.bn.prototype = { l[i] = tmp & m; carry = tmp >> r; } - if (carry) l.push(carry); + if (carry) { + l.push(carry); + } return this; }, @@ -134,7 +136,9 @@ sjcl.bn.prototype = { l[i] = (tmp+carry)>>1; carry = (tmp&1) << r; } - if (!l[l.length-1]) l.pop(); + if (!l[l.length-1]) { + l.pop(); + } return this; }, @@ -225,7 +229,7 @@ sjcl.bn.prototype = { /** this * that. Normalizes and reduces. */ mul: function(that) { - if (typeof(that) == "number") { that = new this._class(that); } + if (typeof(that) === "number") { that = new this._class(that); } var i, j, a = this.limbs, b = that.limbs, al = a.length, bl = b.length, out = new this._class(), c = out.limbs, ai, ii=this.maxMul; for (i=0; i < this.limbs.length + that.limbs.length + 1; i++) { @@ -252,12 +256,12 @@ sjcl.bn.prototype = { /** this ^ n. Uses square-and-multiply. Normalizes and reduces. */ power: function(l) { - if (typeof(l) == "number") { + if (typeof(l) === "number") { l = [l]; } else if (l.limbs !== undefined) { l = l.normalize().limbs; } - var j, out = new this._class(1), pow = this; + var i, j, out = new this._class(1), pow = this; for (i=0; i>= 1) { out ++; } @@ -339,7 +345,7 @@ sjcl.bn.prototype = { }; sjcl.bn.fromBits = function(bits) { - var out = new this(), words=[], w=sjcl.bitArray, t = this.prototype, + var Class = this, out = new Class(), words=[], w=sjcl.bitArray, t = this.prototype, l = Math.min(this.bitLength || 0x100000000, w.bitLength(bits)), e = l % t.radix || t.radix; words[0] = w.extract(bits, 0, e); @@ -353,7 +359,7 @@ sjcl.bn.fromBits = function(bits) { -sjcl.bn.prototype.ipv = 1 / (sjcl.bn.prototype.placeVal = Math.pow(2,sjcl.bn.prototype.radix)) +sjcl.bn.prototype.ipv = 1 / (sjcl.bn.prototype.placeVal = Math.pow(2,sjcl.bn.prototype.radix)); sjcl.bn.prototype.radixMask = (1 << sjcl.bn.prototype.radix) - 1; /** @@ -405,7 +411,7 @@ sjcl.bn.pseudoMersennePrime = function(exponent, coeff) { } i--; - if (i == 0) { + if (!i) { limbs.push(0); this.cnormalize(); i = this.minOffset; @@ -416,10 +422,10 @@ sjcl.bn.pseudoMersennePrime = function(exponent, coeff) { return this; }; - ppr._strongReduce = (ppr.fullMask == -1) ? ppr.reduce : function() { - var limbs = this.limbs, i = limbs.length - 1, l; + ppr._strongReduce = (ppr.fullMask === -1) ? ppr.reduce : function() { + var limbs = this.limbs, i = limbs.length - 1, k, l; this.reduce(); - if (i == this.modOffset - 1) { + if (i === this.modOffset - 1) { l = limbs[i] & this.fullMask; limbs[i] -= l; for (k=0; k>>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=[],j=[],n,l,m,o;for(e=0;e<0x100;e++)j[(h[e]=e<<1^(e>>7)*283)^e]=e;for(f=g=0;!c[f];f^=n||1,g=j[g]||1){m=g^g<<1^g<<2^g<<3^g<<4;m=m>>8^m&255^99;c[f]=m;d[m]=f;l=h[e=h[n=h[f]]];o=l*0x1010101^e*0x10001^n*0x101^f*0x1010100;l=h[m]*0x101^m*0x1010100;for(e=0;e<4;e++){a[e][f]=l=l<<24^l>>>8;b[e][m]=o=o<<24^o>>>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,j,n=c.length/4-2,l,m=4,o=[0,0,0,0];g=this.l[b];var q=g[0],r=g[1],s=g[2],t=g[3],u=g[4];for(l=0;l>>24]^r[e>>16&255]^s[f>>8&255]^t[a&255]^c[m];h=q[e>>>24]^r[f>>16&255]^s[a>>8&255]^t[d&255]^c[m+1];j=q[f>>>24]^r[a>>16&255]^s[d>>8&255]^t[e&255]^c[m+2];a=q[a>>>24]^r[d>>16& -255]^s[e>>8&255]^t[f&255]^c[m+3];m+=4;d=g;e=h;f=j}for(l=0;l<4;l++){o[b?3&-l:l]=u[d>>>24]<<24^u[e>>16&255]<<16^u[f>>8&255]<<8^u[a&255]^c[m++];g=d;d=e;e=f;f=a;a=g}return o}}; -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=-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]]}}; +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& +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]]}}; 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],j=e[2],n=e[3],l=e[4],m=e[5],o=e[6],q=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+q+(l>>>6^l>>>11^l>>>25^l<<26^l<<21^l<<7)+(o^l&(m^o))+f[a];q=o;o=m;m=l;l=n+b|0;n=j;j=h;h=g;g=b+(h&j^n&(h^j))+(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]+j|0;e[3]=e[3]+n|0;e[4]=e[4]+l|0;e[5]=e[5]+m|0;e[6]=e[6]+o|0;e[7]=e[7]+q|0}}; -sjcl.mode.ccm={name:"ccm",encrypt:function(a,b,c,d,e){var f,g=b.slice(0),h=sjcl.bitArray,j=h.bitLength(c)/8,n=h.bitLength(g)/8;e=e||64;d=d||[];if(j<7)throw new sjcl.exception.invalid("ccm: iv must be at least 7 bytes");for(f=2;f<4&&n>>>8*f;f++);if(f<15-j)f=15-j;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),j=f.clamp(b,h-e),n=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));j=sjcl.mode.ccm.P(a,j,c,n,e,b);a=sjcl.mode.ccm.N(a,j.data,c,d,e,b);if(!f.equal(j.tag,a))throw new sjcl.exception.corrupt("ccm: tag doesn't match");return j.data},N:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,j=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>>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>>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", @@ -37,33 +37,32 @@ b);d.key=a;return sjcl.codec.utf8String.fromBits(c)},encode:function(a){var b,c= decode:function(a){a=a.replace(/\s/g,"");if(!a.match(/^\{.*\}$/))throw new sjcl.exception.invalid("json decode: this isn't json!");a=a.replace(/^\{|\}$/g,"").split(/,/);var b={},c,d;for(c=0;c=this.limbs.length?0:this.limbs[a]},greaterEquals:function(a){if(typeof a=="number")a=new this.d(a);var b=0,c=0,d,e,f;for(d=Math.max(this.limbs.length,a.limbs.length)-1;d>=0;d--){e=this.getLimb(d);f=a.getLimb(d);c|=f-e&~b;b|=e-f&~c}return(c|~b)>>>31},toString:function(){this.fullReduce();var a="",b,c,d=this.limbs;for(b=0;b=this.limbs.length?0:this.limbs[a]},greaterEquals:function(a){if(typeof a==="number")a=new this.d(a);var b=0,c=0,d,e,f;for(d=Math.max(this.limbs.length,a.limbs.length)-1;d>=0;d--){e=this.getLimb(d);f=a.getLimb(d);c|=f-e&~b;b|=e-f&~c}return(c|~b)>>>31},toString:function(){this.fullReduce();var a="",b,c,d=this.limbs;for(b=0;b>d}b&&f.push(b);return this},halveM:function(){var a,b=0,c,d=this.radix,e=this.limbs;for(a=e.length-1;a>=0;a--){c=e[a];e[a]=c+b>> 1;b=(c&1)<0;c--){a.halveM();b.greaterEquals(a)&&b.subM(a).normalize()}return b.trim()},inverseMod:function(a){var b=new sjcl.bn(1),c=new sjcl.bn(0),d=new sjcl.bn(this), e=new sjcl.bn(a),f,g=1;if(!(a.limbs[0]&1))throw new sjcl.exception.invalid("inverseMod: p must be odd");do{if(d.limbs[0]&1){if(!d.greaterEquals(e)){f=d;d=e;e=f;f=b;b=c;c=f}d.subM(e);d.normalize();b.greaterEquals(c)||b.addM(a);b.subM(c)}d.halveM();b.limbs[0]&1&&b.addM(a);b.normalize();b.halveM();for(f=g=0;f=0;b--)a=c.concat(a,[c.partial(this.radix,this.getLimb(b))]);return a},bitLength:function(){this.fullReduce();for(var a=this.radix*(this.limbs.length-1),b=this.limbs[this.limbs.length- 1];b;b>>=1)a++;return a+7&-8}};sjcl.bn.fromBits=function(a){var b=new this,c=[],d=sjcl.bitArray,e=this.prototype,f=Math.min(this.bitLength||0x100000000,d.bitLength(a)),g=f%e.radix||e.radix;for(c[0]=d.extract(a,0,g);gn;){j=l.pop();r=l.length;for(h=0;hj;){i=k.pop();o=k.length;for(h=0;h=0;b--)for(c=sjcl.bn.prototype.radix-4;c>=0;c-=4)d=d.doubl().doubl().doubl().doubl().add(e[a[b]>>c&15]);return d},mult2:function(a, -b,c,d){if(typeof a=="number")a=[a];else if(a.limbs!==undefined)a=a.normalize().limbs;if(typeof c=="number")c=[c];else if(c.limbs!==undefined)c=c.normalize().limbs;var e,f=(new sjcl.ecc.point(this.curve)).toJac();b=b.multiples();var g=d.multiples(),h,j;for(d=Math.max(a.length,c.length)-1;d>=0;d--){h=a[d]|0;j=c[d]|0;for(e=sjcl.bn.prototype.radix-4;e>=0;e-=4)f=f.doubl().doubl().doubl().doubl().add(b[h>>e&15]).add(g[j>>e&15])}return f},isValid:function(){var a=this.z.square(),b=a.square();a=b.mul(a); -return this.y.square().equals(this.curve.b.mul(a).add(this.x.mul(this.curve.a.mul(b).add(this.x.square()))))}};sjcl.ecc.curve=function(a,b,c,d,e,f){this.field=a;this.r=a.prototype.modulus.sub(b);this.a=new a(c);this.b=new a(d);this.G=new sjcl.ecc.point(this,new a(e),new a(f))}; -sjcl.ecc.curve.prototype.fromBits=function(a){var b=sjcl.bitArray,c=this.field.prototype.exponent+7&-8;p=new sjcl.ecc.point(this,this.field.fromBits(b.bitSlice(a,0,c)),this.field.fromBits(b.bitSlice(a,c,2*c)));if(!p.isValid())throw new sjcl.exception.corrupt("not on the curve!");return p}; +sjcl.ecc.pointJac.prototype={add:function(a){var b,c,d,e;if(this.curve!==a.curve)throw"sjcl['ecc']['add'](): Points must be on the same curve to add them!";if(this.isIdentity)return a.toJac();else if(a.isIdentity)return this;b=this.z.square();c=a.x.mul(b).subM(this.x);if(c.equals(0))return this.y.equals(a.y.mul(b.mul(this.z)))?this.doubl():new sjcl.ecc.pointJac(this.curve);b=a.y.mul(b.mul(this.z)).subM(this.y);d=c.square();a=b.square();e=c.square().mul(c).addM(this.x.add(this.x).mul(d));a=a.subM(e); +b=this.x.mul(d).subM(a).mul(b);d=this.y.mul(c.square().mul(c));b=b.subM(d);c=this.z.mul(c);return new sjcl.ecc.pointJac(this.curve,a,b,c)},doubl:function(){if(this.isIdentity)return this;var a=this.y.square(),b=a.mul(this.x.mul(4)),c=a.square().mul(8);a=this.z.square();var d=this.x.sub(a).mul(3).mul(this.x.add(a));a=d.square().subM(b).subM(b);b=b.sub(a).mul(d).subM(c);c=this.y.add(this.y).mul(this.z);return new sjcl.ecc.pointJac(this.curve,a,b,c)},toAffine:function(){if(this.isIdentity||this.z.equals(0))return new sjcl.ecc.point(this.curve); +var a=this.z.inverse(),b=a.square();return new sjcl.ecc.point(this.curve,this.x.mul(b).fullReduce(),this.y.mul(b.mul(a)).fullReduce())},mult:function(a,b){if(typeof a==="number")a=[a];else if(a.limbs!==undefined)a=a.normalize().limbs;var c,d=(new sjcl.ecc.point(this.curve)).toJac(),e=b.multiples();for(b=a.length-1;b>=0;b--)for(c=sjcl.bn.prototype.radix-4;c>=0;c-=4)d=d.doubl().doubl().doubl().doubl().add(e[a[b]>>c&15]);return d},mult2:function(a,b,c,d){if(typeof a==="number")a=[a];else if(a.limbs!== +undefined)a=a.normalize().limbs;if(typeof c==="number")c=[c];else if(c.limbs!==undefined)c=c.normalize().limbs;var e,f=(new sjcl.ecc.point(this.curve)).toJac();b=b.multiples();var g=d.multiples(),h,i;for(d=Math.max(a.length,c.length)-1;d>=0;d--){h=a[d]|0;i=c[d]|0;for(e=sjcl.bn.prototype.radix-4;e>=0;e-=4)f=f.doubl().doubl().doubl().doubl().add(b[h>>e&15]).add(g[i>>e&15])}return f},isValid:function(){var a=this.z.square(),b=a.square();a=b.mul(a);return this.y.square().equals(this.curve.b.mul(a).add(this.x.mul(this.curve.a.mul(b).add(this.x.square()))))}}; +sjcl.ecc.curve=function(a,b,c,d,e,f){this.field=a;this.r=a.prototype.modulus.sub(b);this.a=new a(c);this.b=new a(d);this.G=new sjcl.ecc.point(this,new a(e),new a(f))};sjcl.ecc.curve.prototype.fromBits=function(a){var b=sjcl.bitArray,c=this.field.prototype.exponent+7&-8;a=new sjcl.ecc.point(this,this.field.fromBits(b.bitSlice(a,0,c)),this.field.fromBits(b.bitSlice(a,c,2*c)));if(!a.isValid())throw new sjcl.exception.corrupt("not on the curve!");return a}; sjcl.ecc.curves={c192:new sjcl.ecc.curve(sjcl.bn.prime.p192,"0x662107c8eb94364e4b2dd7ce",-3,"0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1","0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012","0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"),c224:new sjcl.ecc.curve(sjcl.bn.prime.p224,"0xe95c1f470fc1ec22d6baa3a3d5c4",-3,"0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4","0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21","0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34"), c256:new sjcl.ecc.curve(sjcl.bn.prime.p256,"0x4319055358e8617b0c46353d039cdaae",-3,"0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b","0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296","0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"),c384:new sjcl.ecc.curve(sjcl.bn.prime.p384,"0x389cb27e0bc8d21fa7e5f24cb74f58851313e696333ad68c",-3,"0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef","0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", "0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f")}; -sjcl.ecc.Q=function(a){sjcl.ecc[a]={publicKey:function(b,c){this.e=b;this.Z=c instanceof Array?b.fromBits(c):c},secretKey:function(b,c){this.e=b;this.S=c},generateKeys:function(b,c){if(typeof b=="number"){b=sjcl.ecc.curves["c"+b];if(b===undefined)throw new sjcl.exception.invalid("no such curve");}c=sjcl.bn.random(b.r,c);var d=b.G.mult(c);return{pub:new sjcl.ecc[a].publicKey(b,d),sec:new sjcl.ecc[a].secretKey(b,c)}}}};sjcl.ecc.Q("elGamal"); +sjcl.ecc.Q=function(a){sjcl.ecc[a]={publicKey:function(b,c){this.e=b;this.Z=c instanceof Array?b.fromBits(c):c},secretKey:function(b,c){this.e=b;this.S=c},generateKeys:function(b,c){if(b===undefined)b=0x100;if(typeof b==="number"){b=sjcl.ecc.curves["c"+b];if(b===undefined)throw new sjcl.exception.invalid("no such curve");}c=sjcl.bn.random(b.r,c);var d=b.G.mult(c);return{pub:new sjcl.ecc[a].publicKey(b,d),sec:new sjcl.ecc[a].secretKey(b,c)}}}};sjcl.ecc.Q("elGamal"); sjcl.ecc.elGamal.publicKey.prototype={kem:function(a){a=sjcl.bn.random(this.e.r,a);var b=this.e.G.mult(a).toBits();return{key:sjcl.hash.sha256.hash(this.Z.mult(a).toBits()),tag:b}}};sjcl.ecc.elGamal.secretKey.prototype={unkem:function(a){return sjcl.hash.sha256.hash(this.e.fromBits(a).mult(this.S).toBits())}};sjcl.ecc.Q("ecdsa"); -sjcl.ecc.ecdsa.secretKey.prototype={sign:function(a,b){var c=this.e.r,d=c.bitLength();b=this.e.G.mult(kkkk=sjcl.bn.random(c.sub(1),b).add(1)).x.mod(c);a=sjcl.bn.fromBits(a).add(b.mul(this.S)).inverseMod(c).mul(kkkk).mod(c);return sjcl.bitArray.concat(b.toBits(d),a.toBits(d))}}; -sjcl.ecc.ecdsa.publicKey.prototype={verify:function(a,b){var c=sjcl.bitArray,d=this.e.r,e=d.bitLength(),f=sjcl.bn.fromBits(c.bitSlice(b,0,e));b=sjcl.bn.fromBits(c.bitSlice(b,e,2*e));a=sjcl.bn.fromBits(a).mul(b).mod(d);c=f.mul(b).mod(d);a=this.e.G.mult2(a,c,this.Z).x;c=sjcl.exception.corrupt;if(f.equals(0)||b.equals(0)||f.greaterEquals(d)||b.greaterEquals(d)||!a.equals(f))throw new c("signature didn't check out");return true}}; +sjcl.ecc.ecdsa.secretKey.prototype={sign:function(a,b){var c=this.e.r,d=c.bitLength(),e=sjcl.bn.random(c.sub(1),b).add(1);b=this.e.G.mult(e).x.mod(c);a=sjcl.bn.fromBits(a).add(b.mul(this.S)).inverseMod(c).mul(e).mod(c);return sjcl.bitArray.concat(b.toBits(d),a.toBits(d))}}; +sjcl.ecc.ecdsa.publicKey.prototype={verify:function(a,b){var c=sjcl.bitArray,d=this.e.r,e=d.bitLength(),f=sjcl.bn.fromBits(c.bitSlice(b,0,e));b=sjcl.bn.fromBits(c.bitSlice(b,e,2*e));a=sjcl.bn.fromBits(a).mul(b).mod(d);c=f.mul(b).mod(d);a=this.e.G.mult2(a,c,this.Z).x;if(f.equals(0)||b.equals(0)||f.greaterEquals(d)||b.greaterEquals(d)||!a.equals(f))throw new sjcl.exception.corrupt("signature didn't check out");return true}}; diff --git a/test/ecdh_test.js b/test/ecdh_test.js index 681b3f92..8bcf874e 100644 --- a/test/ecdh_test.js +++ b/test/ecdh_test.js @@ -5,11 +5,14 @@ new sjcl.test.TestCase("ECDH test", function (cb) { return; } - var keys = sjcl.ecc.elGamal.generateKeys(192,0), - keyTag = keys.pub.kem(0), - key2 = keys.sec.unkem(keyTag.tag); - - this.require(sjcl.bitArray.equal(keyTag.key, key2)); - + try { + var keys = sjcl.ecc.elGamal.generateKeys(192,0), + keyTag = keys.pub.kem(0), + key2 = keys.sec.unkem(keyTag.tag); + + this.require(sjcl.bitArray.equal(keyTag.key, key2)); + } catch(e) { + this.fail(e); + } cb && cb(); });