faye-authentication 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +43 -32
- data/app/assets/javascripts/faye-authentication.js +22 -7
- data/faye-authentication.gemspec +3 -1
- data/lib/faye/authentication/extension.rb +17 -8
- data/lib/faye/authentication/http_client.rb +2 -1
- data/lib/faye/authentication/version.rb +1 -1
- data/lib/faye/authentication.rb +20 -18
- data/spec/javascripts/faye-authentication_spec.js +2 -3
- data/spec/javascripts/faye-extension_spec.js +35 -5
- data/spec/javascripts/support/jasmine_helper.rb +2 -0
- data/spec/lib/faye/authentication/http_client_spec.rb +2 -1
- data/spec/lib/faye/authentication_spec.rb +44 -10
- data/spec/utils/javascripts/jwt.js +2249 -0
- data/spec/utils/javascripts/query-string.js +66 -0
- metadata +23 -6
- data/spec/utils/javascripts/hmac.js +0 -131
@@ -0,0 +1,2249 @@
|
|
1
|
+
"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}}};
|
2
|
+
sjcl.cipher.aes=function(a){this.h[0][0][0]||this.w();var b,c,d,e,f=this.h[0][4],g=this.h[1];b=a.length;var h=1;if(b!==4&&b!==6&&b!==8)throw new sjcl.exception.invalid("invalid aes key size");this.a=[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]]^
|
3
|
+
g[3][f[c&255]]}};
|
4
|
+
sjcl.cipher.aes.prototype={encrypt:function(a){return this.H(a,0)},decrypt:function(a){return this.H(a,1)},h:[[[],[],[],[],[]],[[],[],[],[],[]]],w:function(){var a=this.h[0],b=this.h[1],c=a[4],d=b[4],e,f,g,h=[],i=[],k,j,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^=k||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;j=h[e=h[k=h[f]]];m=j*0x1010101^e*0x10001^k*0x101^f*0x1010100;j=h[l]*0x101^l*0x1010100;for(e=0;e<4;e++){a[e][f]=j=j<<24^j>>>8;b[e][l]=m=m<<24^m>>>8}}for(e=
|
5
|
+
0;e<5;e++){a[e]=a[e].slice(0);b[e]=b[e].slice(0)}},H:function(a,b){if(a.length!==4)throw new sjcl.exception.invalid("invalid aes block size");var c=this.a[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,k=c.length/4-2,j,l=4,m=[0,0,0,0];g=this.h[b];var n=g[0],o=g[1],p=g[2],q=g[3],r=g[4];for(j=0;j<k;j++){g=n[d>>>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&
|
6
|
+
255]^p[e>>8&255]^q[f&255]^c[l+3];l+=4;d=g;e=h;f=i}for(j=0;j<4;j++){m[b?3&-j:j]=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}};
|
7
|
+
sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.P(a.slice(b/32),32-(b&31)).slice(1);return c===undefined?a:sjcl.bitArray.clamp(a,c-b)},concat:function(a,b){if(a.length===0||b.length===0)return a.concat(b);var c=a[a.length-1],d=sjcl.bitArray.getPartial(c);return d===32?a.concat(b):sjcl.bitArray.P(b,d,c|0,a.slice(0,a.length-1))},bitLength:function(a){var b=a.length;if(b===0)return 0;return(b-1)*32+sjcl.bitArray.getPartial(a[b-1])},clamp:function(a,b){if(a.length*32<b)return a;a=a.slice(0,Math.ceil(b/
|
8
|
+
32));var c=a.length;b&=31;if(c>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<a.length;d++)c|=a[d]^b[d];return c===0},P: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);
|
9
|
+
for(e=0;e<a.length;e++){d.push(c|a[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},k:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]}};
|
10
|
+
sjcl.codec.utf8String={fromBits:function(a){var b="",c=sjcl.bitArray.bitLength(a),d,e;for(d=0;d<c/8;d++){if((d&3)===0)e=a[d/4];b+=String.fromCharCode(e>>>24);e<<=8}return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c<a.length;c++){d=d<<8|a.charCodeAt(c);if((c&3)===3){b.push(d);d=0}}c&3&&b.push(sjcl.bitArray.partial(8*(c&3),d));return b}};
|
11
|
+
sjcl.codec.hex={fromBits:function(a){var b="",c;for(c=0;c<a.length;c++)b+=((a[c]|0)+0xf00000000000).toString(16).substr(4);return b.substr(0,sjcl.bitArray.bitLength(a)/4)},toBits:function(a){var b,c=[],d;a=a.replace(/\s|0x/g,"");d=a.length;a+="00000000";for(b=0;b<a.length;b+=8)c.push(parseInt(a.substr(b,8),16)^0);return sjcl.bitArray.clamp(c,d*4)}};
|
12
|
+
sjcl.codec.base64={D:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(a,b){var c="",d,e=0,f=sjcl.codec.base64.D,g=0,h=sjcl.bitArray.bitLength(a);for(d=0;c.length*6<h;){c+=f.charAt((g^a[d]>>>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.D,f=0,g;for(c=0;c<a.length;c++){g=e.indexOf(a.charAt(c));if(g<0)throw new sjcl.exception.invalid("this isn't base64!");
|
13
|
+
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.a[0]||this.w();if(a){this.n=a.n.slice(0);this.i=a.i.slice(0);this.e=a.e}else this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()};
|
14
|
+
sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.n=this.N.slice(0);this.i=[];this.e=0;return this},update:function(a){if(typeof a==="string")a=sjcl.codec.utf8String.toBits(a);var b,c=this.i=sjcl.bitArray.concat(this.i,a);b=this.e;a=this.e=b+sjcl.bitArray.bitLength(a);for(b=512+b&-512;b<=a;b+=512)this.C(c.splice(0,16));return this},finalize:function(){var a,b=this.i,c=this.n;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.e/
|
15
|
+
4294967296));for(b.push(this.e|0);b.length;)this.C(b.splice(0,16));this.reset();return c},N:[],a:[],w: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.N[b]=a(Math.pow(c,0.5));this.a[b]=a(Math.pow(c,1/3));b++}},C:function(a){var b,c,d=a.slice(0),e=this.n,f=this.a,g=e[0],h=e[1],i=e[2],k=e[3],j=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^
|
16
|
+
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+(j>>>6^j>>>11^j>>>25^j<<26^j<<21^j<<7)+(m^j&(l^m))+f[a];n=m;m=l;l=j;j=k+b|0;k=i;i=h;h=g;g=b+(h&i^k&(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]+k|0;e[4]=e[4]+j|0;e[5]=e[5]+l|0;e[6]=e[6]+m|0;e[7]=e[7]+n|0}};
|
17
|
+
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,k=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&&k>>>8*f;f++);if(f<15-i)f=15-i;c=h.clamp(c,8*(15-f));b=sjcl.mode.ccm.G(a,b,c,d,e,f);g=sjcl.mode.ccm.I(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),k=f.bitSlice(b,
|
18
|
+
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.I(a,i,c,k,e,b);a=sjcl.mode.ccm.G(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},G:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,i=h.k;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");
|
19
|
+
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)},I:function(a,b,c,d,e,f){var g,h=sjcl.bitArray;g=h.k;var i=b.length,k=h.bitLength(b);c=h.concat([h.partial(8,f-1)],c).concat([0,
|
20
|
+
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,k)}}};
|
21
|
+
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.A,i=sjcl.bitArray,k=i.k,j=[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);j=k(j,l);m=m.concat(k(c,a.encrypt(k(c,l))));c=h(c)}l=b.slice(g);b=i.bitLength(l);g=a.encrypt(k(c,[0,0,0,b]));l=i.clamp(k(l,g),b);j=k(j,k(l,g));j=a.encrypt(k(j,k(c,h(c))));if(d.length)j=k(j,f?d:sjcl.mode.ocb2.pmac(a,
|
22
|
+
d));return m.concat(i.concat(l,i.clamp(j,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.A,h=sjcl.bitArray,i=h.k,k=[0,0,0,0],j=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(j,a.decrypt(i(j,b.slice(c,c+4))));k=i(k,l);o=o.concat(l);j=g(j)}m=n-c*32;l=a.encrypt(i(j,[0,0,0,m]));l=i(l,h.clamp(b.slice(c),m));k=i(k,l);k=a.encrypt(i(k,i(j,g(j))));if(d.length)k=
|
23
|
+
i(k,f?d:sjcl.mode.ocb2.pmac(a,d));if(!h.equal(h.clamp(k,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.A,e=sjcl.bitArray,f=e.k,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))},A:function(a){return[a[0]<<
|
24
|
+
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.M=b=b||sjcl.hash.sha256;var c=[[],[]],d=b.prototype.blockSize/32;this.l=[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.l[0].update(c[0]);this.l[1].update(c[1])};sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a,b){a=(new this.M(this.l[0])).update(a,b).finalize();return(new this.M(this.l[1])).update(a).finalize()};
|
25
|
+
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,k=[],j=sjcl.bitArray;for(i=1;32*k.length<(d||1);i++){e=f=a.encrypt(j.concat(b,[i]));for(g=1;g<c;g++){f=a.encrypt(f);for(h=0;h<f.length;h++)e[h]^=f[h]}k=k.concat(e)}if(d)k=j.clamp(k,d);return k};
|
26
|
+
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.U(!(b&1));for(b=0;b<a;b+=4){(b+1)%0x10000===0&&this.L();d=this.u();c.push(d[0],d[1],d[2],d[3])}this.L();return c.slice(0,a)},setDefaultParanoia:function(a){this.t=a},addEntropy:function(a,b,c){c=c||"user";var d,e,f=(new Date).valueOf(),g=this.q[c],h=this.isReady();d=this.F[c];if(d===undefined)d=this.F[c]=this.R++;if(g===undefined)g=this.q[c]=0;this.q[c]=
|
27
|
+
(this.q[c]+1)%this.b.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.b[g].update([d,this.J++,2,b,f,a.length].concat(a));break;case "string":if(b===undefined)b=a.length;this.b[g].update([d,this.J++,3,b,f,a.length]);this.b[g].update(a);break;default:throw new sjcl.exception.bug("random: addEntropy only supports number, array or string");}this.j[g]+=b;this.f+=b;if(h===0){this.isReady()!==0&&this.K("seeded",Math.max(this.g,
|
28
|
+
this.f));this.K("progress",this.getProgress())}},isReady:function(a){a=this.B[a!==undefined?a:this.t];return this.g&&this.g>=a?this.j[0]>80&&(new Date).valueOf()>this.O?3:1:this.f>=a?2:0},getProgress:function(a){a=this.B[a?a:this.t];return this.g>=a?1["0"]:this.f>a?1["0"]:this.f/a},startCollectors:function(){if(!this.m){if(window.addEventListener){window.addEventListener("load",this.o,false);window.addEventListener("mousemove",this.p,false)}else if(document.attachEvent){document.attachEvent("onload",
|
29
|
+
this.o);document.attachEvent("onmousemove",this.p)}else throw new sjcl.exception.bug("can't attach event");this.m=true}},stopCollectors:function(){if(this.m){if(window.removeEventListener){window.removeEventListener("load",this.o);window.removeEventListener("mousemove",this.p)}else if(window.detachEvent){window.detachEvent("onload",this.o);window.detachEvent("onmousemove",this.p)}this.m=false}},addEventListener:function(a,b){this.r[a][this.Q++]=b},removeEventListener:function(a,b){var c;a=this.r[a];
|
30
|
+
var d=[];for(c in a)a.hasOwnProperty[c]&&a[c]===b&&d.push(c);for(b=0;b<d.length;b++){c=d[b];delete a[c]}},b:[new sjcl.hash.sha256],j:[0],z:0,q:{},J:0,F:{},R:0,g:0,f:0,O:0,a:[0,0,0,0,0,0,0,0],d:[0,0,0,0],s:undefined,t:6,m:false,r:{progress:{},seeded:{}},Q:0,B:[0,48,64,96,128,192,0x100,384,512,768,1024],u:function(){for(var a=0;a<4;a++){this.d[a]=this.d[a]+1|0;if(this.d[a])break}return this.s.encrypt(this.d)},L:function(){this.a=this.u().concat(this.u());this.s=new sjcl.cipher.aes(this.a)},T:function(a){this.a=
|
31
|
+
sjcl.hash.sha256.hash(this.a.concat(a));this.s=new sjcl.cipher.aes(this.a);for(a=0;a<4;a++){this.d[a]=this.d[a]+1|0;if(this.d[a])break}},U:function(a){var b=[],c=0,d;this.O=b[0]=(new Date).valueOf()+3E4;for(d=0;d<16;d++)b.push(Math.random()*0x100000000|0);for(d=0;d<this.b.length;d++){b=b.concat(this.b[d].finalize());c+=this.j[d];this.j[d]=0;if(!a&&this.z&1<<d)break}if(this.z>=1<<this.b.length){this.b.push(new sjcl.hash.sha256);this.j.push(0)}this.f-=c;if(c>this.g)this.g=c;this.z++;this.T(b)},p:function(a){sjcl.random.addEntropy([a.x||
|
32
|
+
a.clientX||a.offsetX,a.y||a.clientY||a.offsetY],2,"mouse")},o:function(){sjcl.random.addEntropy(new Date,2,"loadtime")},K:function(a,b){var c;a=sjcl.random.r[a];var d=[];for(c in a)a.hasOwnProperty(c)&&d.push(a[c]);for(c=0;c<d.length;c++)d[c](b)}};
|
33
|
+
sjcl.json={defaults:{v:1,iter:1E3,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},encrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,f=e.c({iv:sjcl.random.randomWords(4,0)},e.defaults);e.c(f,c);if(typeof f.salt==="string")f.salt=sjcl.codec.base64.toBits(f.salt);if(typeof f.iv==="string")f.iv=sjcl.codec.base64.toBits(f.iv);if(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||typeof a==="string"&&f.iter<=100||f.ts!==64&&f.ts!==96&&f.ts!==128||f.ks!==128&&f.ks!==192&&f.ks!==0x100||f.iv.length<2||f.iv.length>
|
34
|
+
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.c(d,f);d.key=a;f.ct=sjcl.mode[f.mode].encrypt(c,b,f.iv,f.adata,f.tag);return e.encode(e.V(f,e.defaults))},decrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.c(e.c(e.c({},e.defaults),e.decode(b)),c,true);if(typeof b.salt==="string")b.salt=
|
35
|
+
sjcl.codec.base64.toBits(b.salt);if(typeof b.iv==="string")b.iv=sjcl.codec.base64.toBits(b.iv);if(!sjcl.mode[b.mode]||!sjcl.cipher[b.cipher]||typeof a==="string"&&b.iter<=100||b.ts!==64&&b.ts!==96&&b.ts!==128||b.ks!==128&&b.ks!==192&&b.ks!==0x100||!b.iv||b.iv.length<2||b.iv.length>4)throw new sjcl.exception.invalid("json decrypt: invalid parameters");if(typeof a==="string"){c=sjcl.misc.cachedPbkdf2(a,b);a=c.key.slice(0,b.ks/32);b.salt=c.salt}c=new sjcl.cipher[b.cipher](a);c=sjcl.mode[b.mode].decrypt(c,
|
36
|
+
b.ct,b.iv,b.adata,b.tag);e.c(d,b);d.key=a;return sjcl.codec.utf8String.fromBits(c)},encode:function(a){var b,c="{",d="";for(b in a)if(a.hasOwnProperty(b)){if(!b.match(/^[a-z0-9]+$/i))throw new sjcl.exception.invalid("json encode: invalid property name");c+=d+b+":";d=",";switch(typeof a[b]){case "number":case "boolean":c+=a[b];break;case "string":c+='"'+escape(a[b])+'"';break;case "object":c+='"'+sjcl.codec.base64.fromBits(a[b],1)+'"';break;default:throw new sjcl.exception.bug("json encode: unsupported type");
|
37
|
+
}}return 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<a.length;c++){if(!(d=a[c].match(/^([a-z][a-z0-9]*):(?:(\d+)|"([a-z0-9+\/%*_.@=\-]*)")$/i)))throw new sjcl.exception.invalid("json decode: this isn't json!");b[d[1]]=d[2]?parseInt(d[2],10):d[1].match(/^(ct|salt|iv)$/)?sjcl.codec.base64.toBits(d[3]):unescape(d[3])}return b},c:function(a,b,c){if(a===
|
38
|
+
undefined)a={};if(b===undefined)return a;var d;for(d in b)if(b.hasOwnProperty(d)){if(c&&a[d]!==undefined&&a[d]!==b[d])throw new sjcl.exception.invalid("required parameter overridden");a[d]=b[d]}return a},V:function(a,b){var c={},d;for(d in a)if(a.hasOwnProperty(d)&&a[d]!==b[d])c[d]=a[d];return c},W:function(a,b){var c={},d;for(d=0;d<b.length;d++)if(a[b[d]]!==undefined)c[b[d]]=a[b[d]];return c}};sjcl.encrypt=sjcl.json.encrypt;sjcl.decrypt=sjcl.json.decrypt;sjcl.misc.S={};
|
39
|
+
sjcl.misc.cachedPbkdf2=function(a,b){var c=sjcl.misc.S,d;b=b||{};d=b.iter||1E3;c=c[a]=c[a]||{};d=c[d]=c[d]||{firstSalt:b.salt&&b.salt.length?b.salt.slice(0):sjcl.random.randomWords(2,0)};c=b.salt===undefined?d.firstSalt:b.salt;d[c]=d[c]||sjcl.misc.pbkdf2(a,c,b.iter);return{key:d[c].slice(0),salt:c.slice(0)}};
|
40
|
+
var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
41
|
+
var b64pad="=";
|
42
|
+
|
43
|
+
function hex2b64(h) {
|
44
|
+
var i;
|
45
|
+
var c;
|
46
|
+
var ret = "";
|
47
|
+
for(i = 0; i+3 <= h.length; i+=3) {
|
48
|
+
c = parseInt(h.substring(i,i+3),16);
|
49
|
+
ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
|
50
|
+
}
|
51
|
+
if(i+1 == h.length) {
|
52
|
+
c = parseInt(h.substring(i,i+1),16);
|
53
|
+
ret += b64map.charAt(c << 2);
|
54
|
+
}
|
55
|
+
else if(i+2 == h.length) {
|
56
|
+
c = parseInt(h.substring(i,i+2),16);
|
57
|
+
ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
|
58
|
+
}
|
59
|
+
while((ret.length & 3) > 0) ret += b64pad;
|
60
|
+
return ret;
|
61
|
+
}
|
62
|
+
|
63
|
+
// convert a base64 string to hex
|
64
|
+
function b64tohex(s) {
|
65
|
+
var ret = ""
|
66
|
+
var i;
|
67
|
+
var k = 0; // b64 state, 0-3
|
68
|
+
var slop;
|
69
|
+
for(i = 0; i < s.length; ++i) {
|
70
|
+
if(s.charAt(i) == b64pad) break;
|
71
|
+
var v = b64map.indexOf(s.charAt(i));
|
72
|
+
if(v < 0) continue;
|
73
|
+
if(k == 0) {
|
74
|
+
ret += int2char(v >> 2);
|
75
|
+
slop = v & 3;
|
76
|
+
k = 1;
|
77
|
+
}
|
78
|
+
else if(k == 1) {
|
79
|
+
ret += int2char((slop << 2) | (v >> 4));
|
80
|
+
slop = v & 0xf;
|
81
|
+
k = 2;
|
82
|
+
}
|
83
|
+
else if(k == 2) {
|
84
|
+
ret += int2char(slop);
|
85
|
+
ret += int2char(v >> 2);
|
86
|
+
slop = v & 3;
|
87
|
+
k = 3;
|
88
|
+
}
|
89
|
+
else {
|
90
|
+
ret += int2char((slop << 2) | (v >> 4));
|
91
|
+
ret += int2char(v & 0xf);
|
92
|
+
k = 0;
|
93
|
+
}
|
94
|
+
}
|
95
|
+
if(k == 1)
|
96
|
+
ret += int2char(slop << 2);
|
97
|
+
return ret;
|
98
|
+
}
|
99
|
+
|
100
|
+
// convert a base64 string to a byte/number array
|
101
|
+
function b64toBA(s) {
|
102
|
+
//piggyback on b64tohex for now, optimize later
|
103
|
+
var h = b64tohex(s);
|
104
|
+
var i;
|
105
|
+
var a = new Array();
|
106
|
+
for(i = 0; 2*i < h.length; ++i) {
|
107
|
+
a[i] = parseInt(h.substring(2*i,2*i+2),16);
|
108
|
+
}
|
109
|
+
return a;
|
110
|
+
}
|
111
|
+
// Copyright (c) 2005 Tom Wu
|
112
|
+
// All Rights Reserved.
|
113
|
+
// See "LICENSE" for details.
|
114
|
+
|
115
|
+
// Basic JavaScript BN library - subset useful for RSA encryption.
|
116
|
+
|
117
|
+
// Bits per digit
|
118
|
+
var dbits;
|
119
|
+
|
120
|
+
// JavaScript engine analysis
|
121
|
+
var canary = 0xdeadbeefcafe;
|
122
|
+
var j_lm = ((canary&0xffffff)==0xefcafe);
|
123
|
+
|
124
|
+
// (public) Constructor
|
125
|
+
function BigInteger(a,b,c) {
|
126
|
+
if(a != null)
|
127
|
+
if("number" == typeof a) this.fromNumber(a,b,c);
|
128
|
+
else if(b == null && "string" != typeof a) this.fromString(a,256);
|
129
|
+
else this.fromString(a,b);
|
130
|
+
}
|
131
|
+
|
132
|
+
// return new, unset BigInteger
|
133
|
+
function nbi() { return new BigInteger(null); }
|
134
|
+
|
135
|
+
// am: Compute w_j += (x*this_i), propagate carries,
|
136
|
+
// c is initial carry, returns final carry.
|
137
|
+
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
|
138
|
+
// We need to select the fastest one that works in this environment.
|
139
|
+
|
140
|
+
// am1: use a single mult and divide to get the high bits,
|
141
|
+
// max digit bits should be 26 because
|
142
|
+
// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
|
143
|
+
function am1(i,x,w,j,c,n) {
|
144
|
+
while(--n >= 0) {
|
145
|
+
var v = x*this[i++]+w[j]+c;
|
146
|
+
c = Math.floor(v/0x4000000);
|
147
|
+
w[j++] = v&0x3ffffff;
|
148
|
+
}
|
149
|
+
return c;
|
150
|
+
}
|
151
|
+
// am2 avoids a big mult-and-extract completely.
|
152
|
+
// Max digit bits should be <= 30 because we do bitwise ops
|
153
|
+
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
|
154
|
+
function am2(i,x,w,j,c,n) {
|
155
|
+
var xl = x&0x7fff, xh = x>>15;
|
156
|
+
while(--n >= 0) {
|
157
|
+
var l = this[i]&0x7fff;
|
158
|
+
var h = this[i++]>>15;
|
159
|
+
var m = xh*l+h*xl;
|
160
|
+
l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
|
161
|
+
c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
|
162
|
+
w[j++] = l&0x3fffffff;
|
163
|
+
}
|
164
|
+
return c;
|
165
|
+
}
|
166
|
+
// Alternately, set max digit bits to 28 since some
|
167
|
+
// browsers slow down when dealing with 32-bit numbers.
|
168
|
+
function am3(i,x,w,j,c,n) {
|
169
|
+
var xl = x&0x3fff, xh = x>>14;
|
170
|
+
while(--n >= 0) {
|
171
|
+
var l = this[i]&0x3fff;
|
172
|
+
var h = this[i++]>>14;
|
173
|
+
var m = xh*l+h*xl;
|
174
|
+
l = xl*l+((m&0x3fff)<<14)+w[j]+c;
|
175
|
+
c = (l>>28)+(m>>14)+xh*h;
|
176
|
+
w[j++] = l&0xfffffff;
|
177
|
+
}
|
178
|
+
return c;
|
179
|
+
}
|
180
|
+
if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
|
181
|
+
BigInteger.prototype.am = am2;
|
182
|
+
dbits = 30;
|
183
|
+
}
|
184
|
+
else if(j_lm && (navigator.appName != "Netscape")) {
|
185
|
+
BigInteger.prototype.am = am1;
|
186
|
+
dbits = 26;
|
187
|
+
}
|
188
|
+
else { // Mozilla/Netscape seems to prefer am3
|
189
|
+
BigInteger.prototype.am = am3;
|
190
|
+
dbits = 28;
|
191
|
+
}
|
192
|
+
|
193
|
+
BigInteger.prototype.DB = dbits;
|
194
|
+
BigInteger.prototype.DM = ((1<<dbits)-1);
|
195
|
+
BigInteger.prototype.DV = (1<<dbits);
|
196
|
+
|
197
|
+
var BI_FP = 52;
|
198
|
+
BigInteger.prototype.FV = Math.pow(2,BI_FP);
|
199
|
+
BigInteger.prototype.F1 = BI_FP-dbits;
|
200
|
+
BigInteger.prototype.F2 = 2*dbits-BI_FP;
|
201
|
+
|
202
|
+
// Digit conversions
|
203
|
+
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
|
204
|
+
var BI_RC = new Array();
|
205
|
+
var rr,vv;
|
206
|
+
rr = "0".charCodeAt(0);
|
207
|
+
for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
|
208
|
+
rr = "a".charCodeAt(0);
|
209
|
+
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
|
210
|
+
rr = "A".charCodeAt(0);
|
211
|
+
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
|
212
|
+
|
213
|
+
function int2char(n) { return BI_RM.charAt(n); }
|
214
|
+
function intAt(s,i) {
|
215
|
+
var c = BI_RC[s.charCodeAt(i)];
|
216
|
+
return (c==null)?-1:c;
|
217
|
+
}
|
218
|
+
|
219
|
+
// (protected) copy this to r
|
220
|
+
function bnpCopyTo(r) {
|
221
|
+
for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
|
222
|
+
r.t = this.t;
|
223
|
+
r.s = this.s;
|
224
|
+
}
|
225
|
+
|
226
|
+
// (protected) set from integer value x, -DV <= x < DV
|
227
|
+
function bnpFromInt(x) {
|
228
|
+
this.t = 1;
|
229
|
+
this.s = (x<0)?-1:0;
|
230
|
+
if(x > 0) this[0] = x;
|
231
|
+
else if(x < -1) this[0] = x+DV;
|
232
|
+
else this.t = 0;
|
233
|
+
}
|
234
|
+
|
235
|
+
// return bigint initialized to value
|
236
|
+
function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
|
237
|
+
|
238
|
+
// (protected) set from string and radix
|
239
|
+
function bnpFromString(s,b) {
|
240
|
+
var k;
|
241
|
+
if(b == 16) k = 4;
|
242
|
+
else if(b == 8) k = 3;
|
243
|
+
else if(b == 256) k = 8; // byte array
|
244
|
+
else if(b == 2) k = 1;
|
245
|
+
else if(b == 32) k = 5;
|
246
|
+
else if(b == 4) k = 2;
|
247
|
+
else { this.fromRadix(s,b); return; }
|
248
|
+
this.t = 0;
|
249
|
+
this.s = 0;
|
250
|
+
var i = s.length, mi = false, sh = 0;
|
251
|
+
while(--i >= 0) {
|
252
|
+
var x = (k==8)?s[i]&0xff:intAt(s,i);
|
253
|
+
if(x < 0) {
|
254
|
+
if(s.charAt(i) == "-") mi = true;
|
255
|
+
continue;
|
256
|
+
}
|
257
|
+
mi = false;
|
258
|
+
if(sh == 0)
|
259
|
+
this[this.t++] = x;
|
260
|
+
else if(sh+k > this.DB) {
|
261
|
+
this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
|
262
|
+
this[this.t++] = (x>>(this.DB-sh));
|
263
|
+
}
|
264
|
+
else
|
265
|
+
this[this.t-1] |= x<<sh;
|
266
|
+
sh += k;
|
267
|
+
if(sh >= this.DB) sh -= this.DB;
|
268
|
+
}
|
269
|
+
if(k == 8 && (s[0]&0x80) != 0) {
|
270
|
+
this.s = -1;
|
271
|
+
if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
|
272
|
+
}
|
273
|
+
this.clamp();
|
274
|
+
if(mi) BigInteger.ZERO.subTo(this,this);
|
275
|
+
}
|
276
|
+
|
277
|
+
// (protected) clamp off excess high words
|
278
|
+
function bnpClamp() {
|
279
|
+
var c = this.s&this.DM;
|
280
|
+
while(this.t > 0 && this[this.t-1] == c) --this.t;
|
281
|
+
}
|
282
|
+
|
283
|
+
// (public) return string representation in given radix
|
284
|
+
function bnToString(b) {
|
285
|
+
if(this.s < 0) return "-"+this.negate().toString(b);
|
286
|
+
var k;
|
287
|
+
if(b == 16) k = 4;
|
288
|
+
else if(b == 8) k = 3;
|
289
|
+
else if(b == 2) k = 1;
|
290
|
+
else if(b == 32) k = 5;
|
291
|
+
else if(b == 4) k = 2;
|
292
|
+
else return this.toRadix(b);
|
293
|
+
var km = (1<<k)-1, d, m = false, r = "", i = this.t;
|
294
|
+
var p = this.DB-(i*this.DB)%k;
|
295
|
+
if(i-- > 0) {
|
296
|
+
if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
|
297
|
+
while(i >= 0) {
|
298
|
+
if(p < k) {
|
299
|
+
d = (this[i]&((1<<p)-1))<<(k-p);
|
300
|
+
d |= this[--i]>>(p+=this.DB-k);
|
301
|
+
}
|
302
|
+
else {
|
303
|
+
d = (this[i]>>(p-=k))&km;
|
304
|
+
if(p <= 0) { p += this.DB; --i; }
|
305
|
+
}
|
306
|
+
if(d > 0) m = true;
|
307
|
+
if(m) r += int2char(d);
|
308
|
+
}
|
309
|
+
}
|
310
|
+
return m?r:"0";
|
311
|
+
}
|
312
|
+
|
313
|
+
// (public) -this
|
314
|
+
function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
|
315
|
+
|
316
|
+
// (public) |this|
|
317
|
+
function bnAbs() { return (this.s<0)?this.negate():this; }
|
318
|
+
|
319
|
+
// (public) return + if this > a, - if this < a, 0 if equal
|
320
|
+
function bnCompareTo(a) {
|
321
|
+
var r = this.s-a.s;
|
322
|
+
if(r != 0) return r;
|
323
|
+
var i = this.t;
|
324
|
+
r = i-a.t;
|
325
|
+
if(r != 0) return r;
|
326
|
+
while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
|
327
|
+
return 0;
|
328
|
+
}
|
329
|
+
|
330
|
+
// returns bit length of the integer x
|
331
|
+
function nbits(x) {
|
332
|
+
var r = 1, t;
|
333
|
+
if((t=x>>>16) != 0) { x = t; r += 16; }
|
334
|
+
if((t=x>>8) != 0) { x = t; r += 8; }
|
335
|
+
if((t=x>>4) != 0) { x = t; r += 4; }
|
336
|
+
if((t=x>>2) != 0) { x = t; r += 2; }
|
337
|
+
if((t=x>>1) != 0) { x = t; r += 1; }
|
338
|
+
return r;
|
339
|
+
}
|
340
|
+
|
341
|
+
// (public) return the number of bits in "this"
|
342
|
+
function bnBitLength() {
|
343
|
+
if(this.t <= 0) return 0;
|
344
|
+
return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
|
345
|
+
}
|
346
|
+
|
347
|
+
// (protected) r = this << n*DB
|
348
|
+
function bnpDLShiftTo(n,r) {
|
349
|
+
var i;
|
350
|
+
for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
|
351
|
+
for(i = n-1; i >= 0; --i) r[i] = 0;
|
352
|
+
r.t = this.t+n;
|
353
|
+
r.s = this.s;
|
354
|
+
}
|
355
|
+
|
356
|
+
// (protected) r = this >> n*DB
|
357
|
+
function bnpDRShiftTo(n,r) {
|
358
|
+
for(var i = n; i < this.t; ++i) r[i-n] = this[i];
|
359
|
+
r.t = Math.max(this.t-n,0);
|
360
|
+
r.s = this.s;
|
361
|
+
}
|
362
|
+
|
363
|
+
// (protected) r = this << n
|
364
|
+
function bnpLShiftTo(n,r) {
|
365
|
+
var bs = n%this.DB;
|
366
|
+
var cbs = this.DB-bs;
|
367
|
+
var bm = (1<<cbs)-1;
|
368
|
+
var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
|
369
|
+
for(i = this.t-1; i >= 0; --i) {
|
370
|
+
r[i+ds+1] = (this[i]>>cbs)|c;
|
371
|
+
c = (this[i]&bm)<<bs;
|
372
|
+
}
|
373
|
+
for(i = ds-1; i >= 0; --i) r[i] = 0;
|
374
|
+
r[ds] = c;
|
375
|
+
r.t = this.t+ds+1;
|
376
|
+
r.s = this.s;
|
377
|
+
r.clamp();
|
378
|
+
}
|
379
|
+
|
380
|
+
// (protected) r = this >> n
|
381
|
+
function bnpRShiftTo(n,r) {
|
382
|
+
r.s = this.s;
|
383
|
+
var ds = Math.floor(n/this.DB);
|
384
|
+
if(ds >= this.t) { r.t = 0; return; }
|
385
|
+
var bs = n%this.DB;
|
386
|
+
var cbs = this.DB-bs;
|
387
|
+
var bm = (1<<bs)-1;
|
388
|
+
r[0] = this[ds]>>bs;
|
389
|
+
for(var i = ds+1; i < this.t; ++i) {
|
390
|
+
r[i-ds-1] |= (this[i]&bm)<<cbs;
|
391
|
+
r[i-ds] = this[i]>>bs;
|
392
|
+
}
|
393
|
+
if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
|
394
|
+
r.t = this.t-ds;
|
395
|
+
r.clamp();
|
396
|
+
}
|
397
|
+
|
398
|
+
// (protected) r = this - a
|
399
|
+
function bnpSubTo(a,r) {
|
400
|
+
var i = 0, c = 0, m = Math.min(a.t,this.t);
|
401
|
+
while(i < m) {
|
402
|
+
c += this[i]-a[i];
|
403
|
+
r[i++] = c&this.DM;
|
404
|
+
c >>= this.DB;
|
405
|
+
}
|
406
|
+
if(a.t < this.t) {
|
407
|
+
c -= a.s;
|
408
|
+
while(i < this.t) {
|
409
|
+
c += this[i];
|
410
|
+
r[i++] = c&this.DM;
|
411
|
+
c >>= this.DB;
|
412
|
+
}
|
413
|
+
c += this.s;
|
414
|
+
}
|
415
|
+
else {
|
416
|
+
c += this.s;
|
417
|
+
while(i < a.t) {
|
418
|
+
c -= a[i];
|
419
|
+
r[i++] = c&this.DM;
|
420
|
+
c >>= this.DB;
|
421
|
+
}
|
422
|
+
c -= a.s;
|
423
|
+
}
|
424
|
+
r.s = (c<0)?-1:0;
|
425
|
+
if(c < -1) r[i++] = this.DV+c;
|
426
|
+
else if(c > 0) r[i++] = c;
|
427
|
+
r.t = i;
|
428
|
+
r.clamp();
|
429
|
+
}
|
430
|
+
|
431
|
+
// (protected) r = this * a, r != this,a (HAC 14.12)
|
432
|
+
// "this" should be the larger one if appropriate.
|
433
|
+
function bnpMultiplyTo(a,r) {
|
434
|
+
var x = this.abs(), y = a.abs();
|
435
|
+
var i = x.t;
|
436
|
+
r.t = i+y.t;
|
437
|
+
while(--i >= 0) r[i] = 0;
|
438
|
+
for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
|
439
|
+
r.s = 0;
|
440
|
+
r.clamp();
|
441
|
+
if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
|
442
|
+
}
|
443
|
+
|
444
|
+
// (protected) r = this^2, r != this (HAC 14.16)
|
445
|
+
function bnpSquareTo(r) {
|
446
|
+
var x = this.abs();
|
447
|
+
var i = r.t = 2*x.t;
|
448
|
+
while(--i >= 0) r[i] = 0;
|
449
|
+
for(i = 0; i < x.t-1; ++i) {
|
450
|
+
var c = x.am(i,x[i],r,2*i,0,1);
|
451
|
+
if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
|
452
|
+
r[i+x.t] -= x.DV;
|
453
|
+
r[i+x.t+1] = 1;
|
454
|
+
}
|
455
|
+
}
|
456
|
+
if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
|
457
|
+
r.s = 0;
|
458
|
+
r.clamp();
|
459
|
+
}
|
460
|
+
|
461
|
+
// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
|
462
|
+
// r != q, this != m. q or r may be null.
|
463
|
+
function bnpDivRemTo(m,q,r) {
|
464
|
+
var pm = m.abs();
|
465
|
+
if(pm.t <= 0) return;
|
466
|
+
var pt = this.abs();
|
467
|
+
if(pt.t < pm.t) {
|
468
|
+
if(q != null) q.fromInt(0);
|
469
|
+
if(r != null) this.copyTo(r);
|
470
|
+
return;
|
471
|
+
}
|
472
|
+
if(r == null) r = nbi();
|
473
|
+
var y = nbi(), ts = this.s, ms = m.s;
|
474
|
+
var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
|
475
|
+
if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
|
476
|
+
else { pm.copyTo(y); pt.copyTo(r); }
|
477
|
+
var ys = y.t;
|
478
|
+
var y0 = y[ys-1];
|
479
|
+
if(y0 == 0) return;
|
480
|
+
var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
|
481
|
+
var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
|
482
|
+
var i = r.t, j = i-ys, t = (q==null)?nbi():q;
|
483
|
+
y.dlShiftTo(j,t);
|
484
|
+
if(r.compareTo(t) >= 0) {
|
485
|
+
r[r.t++] = 1;
|
486
|
+
r.subTo(t,r);
|
487
|
+
}
|
488
|
+
BigInteger.ONE.dlShiftTo(ys,t);
|
489
|
+
t.subTo(y,y); // "negative" y so we can replace sub with am later
|
490
|
+
while(y.t < ys) y[y.t++] = 0;
|
491
|
+
while(--j >= 0) {
|
492
|
+
// Estimate quotient digit
|
493
|
+
var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
|
494
|
+
if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
|
495
|
+
y.dlShiftTo(j,t);
|
496
|
+
r.subTo(t,r);
|
497
|
+
while(r[i] < --qd) r.subTo(t,r);
|
498
|
+
}
|
499
|
+
}
|
500
|
+
if(q != null) {
|
501
|
+
r.drShiftTo(ys,q);
|
502
|
+
if(ts != ms) BigInteger.ZERO.subTo(q,q);
|
503
|
+
}
|
504
|
+
r.t = ys;
|
505
|
+
r.clamp();
|
506
|
+
if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
|
507
|
+
if(ts < 0) BigInteger.ZERO.subTo(r,r);
|
508
|
+
}
|
509
|
+
|
510
|
+
// (public) this mod a
|
511
|
+
function bnMod(a) {
|
512
|
+
var r = nbi();
|
513
|
+
this.abs().divRemTo(a,null,r);
|
514
|
+
if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
|
515
|
+
return r;
|
516
|
+
}
|
517
|
+
|
518
|
+
// Modular reduction using "classic" algorithm
|
519
|
+
function Classic(m) { this.m = m; }
|
520
|
+
function cConvert(x) {
|
521
|
+
if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
|
522
|
+
else return x;
|
523
|
+
}
|
524
|
+
function cRevert(x) { return x; }
|
525
|
+
function cReduce(x) { x.divRemTo(this.m,null,x); }
|
526
|
+
function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
|
527
|
+
function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
|
528
|
+
|
529
|
+
Classic.prototype.convert = cConvert;
|
530
|
+
Classic.prototype.revert = cRevert;
|
531
|
+
Classic.prototype.reduce = cReduce;
|
532
|
+
Classic.prototype.mulTo = cMulTo;
|
533
|
+
Classic.prototype.sqrTo = cSqrTo;
|
534
|
+
|
535
|
+
// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
|
536
|
+
// justification:
|
537
|
+
// xy == 1 (mod m)
|
538
|
+
// xy = 1+km
|
539
|
+
// xy(2-xy) = (1+km)(1-km)
|
540
|
+
// x[y(2-xy)] = 1-k^2m^2
|
541
|
+
// x[y(2-xy)] == 1 (mod m^2)
|
542
|
+
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
|
543
|
+
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
|
544
|
+
// JS multiply "overflows" differently from C/C++, so care is needed here.
|
545
|
+
function bnpInvDigit() {
|
546
|
+
if(this.t < 1) return 0;
|
547
|
+
var x = this[0];
|
548
|
+
if((x&1) == 0) return 0;
|
549
|
+
var y = x&3; // y == 1/x mod 2^2
|
550
|
+
y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
|
551
|
+
y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
|
552
|
+
y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
|
553
|
+
// last step - calculate inverse mod DV directly;
|
554
|
+
// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
|
555
|
+
y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
|
556
|
+
// we really want the negative inverse, and -DV < y < DV
|
557
|
+
return (y>0)?this.DV-y:-y;
|
558
|
+
}
|
559
|
+
|
560
|
+
// Montgomery reduction
|
561
|
+
function Montgomery(m) {
|
562
|
+
this.m = m;
|
563
|
+
this.mp = m.invDigit();
|
564
|
+
this.mpl = this.mp&0x7fff;
|
565
|
+
this.mph = this.mp>>15;
|
566
|
+
this.um = (1<<(m.DB-15))-1;
|
567
|
+
this.mt2 = 2*m.t;
|
568
|
+
}
|
569
|
+
|
570
|
+
// xR mod m
|
571
|
+
function montConvert(x) {
|
572
|
+
var r = nbi();
|
573
|
+
x.abs().dlShiftTo(this.m.t,r);
|
574
|
+
r.divRemTo(this.m,null,r);
|
575
|
+
if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
|
576
|
+
return r;
|
577
|
+
}
|
578
|
+
|
579
|
+
// x/R mod m
|
580
|
+
function montRevert(x) {
|
581
|
+
var r = nbi();
|
582
|
+
x.copyTo(r);
|
583
|
+
this.reduce(r);
|
584
|
+
return r;
|
585
|
+
}
|
586
|
+
|
587
|
+
// x = x/R mod m (HAC 14.32)
|
588
|
+
function montReduce(x) {
|
589
|
+
while(x.t <= this.mt2) // pad x so am has enough room later
|
590
|
+
x[x.t++] = 0;
|
591
|
+
for(var i = 0; i < this.m.t; ++i) {
|
592
|
+
// faster way of calculating u0 = x[i]*mp mod DV
|
593
|
+
var j = x[i]&0x7fff;
|
594
|
+
var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
|
595
|
+
// use am to combine the multiply-shift-add into one call
|
596
|
+
j = i+this.m.t;
|
597
|
+
x[j] += this.m.am(0,u0,x,i,0,this.m.t);
|
598
|
+
// propagate carry
|
599
|
+
while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
|
600
|
+
}
|
601
|
+
x.clamp();
|
602
|
+
x.drShiftTo(this.m.t,x);
|
603
|
+
if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
|
604
|
+
}
|
605
|
+
|
606
|
+
// r = "x^2/R mod m"; x != r
|
607
|
+
function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
|
608
|
+
|
609
|
+
// r = "xy/R mod m"; x,y != r
|
610
|
+
function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
|
611
|
+
|
612
|
+
Montgomery.prototype.convert = montConvert;
|
613
|
+
Montgomery.prototype.revert = montRevert;
|
614
|
+
Montgomery.prototype.reduce = montReduce;
|
615
|
+
Montgomery.prototype.mulTo = montMulTo;
|
616
|
+
Montgomery.prototype.sqrTo = montSqrTo;
|
617
|
+
|
618
|
+
// (protected) true iff this is even
|
619
|
+
function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
|
620
|
+
|
621
|
+
// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
|
622
|
+
function bnpExp(e,z) {
|
623
|
+
if(e > 0xffffffff || e < 1) return BigInteger.ONE;
|
624
|
+
var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
|
625
|
+
g.copyTo(r);
|
626
|
+
while(--i >= 0) {
|
627
|
+
z.sqrTo(r,r2);
|
628
|
+
if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
|
629
|
+
else { var t = r; r = r2; r2 = t; }
|
630
|
+
}
|
631
|
+
return z.revert(r);
|
632
|
+
}
|
633
|
+
|
634
|
+
// (public) this^e % m, 0 <= e < 2^32
|
635
|
+
function bnModPowInt(e,m) {
|
636
|
+
var z;
|
637
|
+
if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
|
638
|
+
return this.exp(e,z);
|
639
|
+
}
|
640
|
+
|
641
|
+
// protected
|
642
|
+
BigInteger.prototype.copyTo = bnpCopyTo;
|
643
|
+
BigInteger.prototype.fromInt = bnpFromInt;
|
644
|
+
BigInteger.prototype.fromString = bnpFromString;
|
645
|
+
BigInteger.prototype.clamp = bnpClamp;
|
646
|
+
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
|
647
|
+
BigInteger.prototype.drShiftTo = bnpDRShiftTo;
|
648
|
+
BigInteger.prototype.lShiftTo = bnpLShiftTo;
|
649
|
+
BigInteger.prototype.rShiftTo = bnpRShiftTo;
|
650
|
+
BigInteger.prototype.subTo = bnpSubTo;
|
651
|
+
BigInteger.prototype.multiplyTo = bnpMultiplyTo;
|
652
|
+
BigInteger.prototype.squareTo = bnpSquareTo;
|
653
|
+
BigInteger.prototype.divRemTo = bnpDivRemTo;
|
654
|
+
BigInteger.prototype.invDigit = bnpInvDigit;
|
655
|
+
BigInteger.prototype.isEven = bnpIsEven;
|
656
|
+
BigInteger.prototype.exp = bnpExp;
|
657
|
+
|
658
|
+
// public
|
659
|
+
BigInteger.prototype.toString = bnToString;
|
660
|
+
BigInteger.prototype.negate = bnNegate;
|
661
|
+
BigInteger.prototype.abs = bnAbs;
|
662
|
+
BigInteger.prototype.compareTo = bnCompareTo;
|
663
|
+
BigInteger.prototype.bitLength = bnBitLength;
|
664
|
+
BigInteger.prototype.mod = bnMod;
|
665
|
+
BigInteger.prototype.modPowInt = bnModPowInt;
|
666
|
+
|
667
|
+
// "constants"
|
668
|
+
BigInteger.ZERO = nbv(0);
|
669
|
+
BigInteger.ONE = nbv(1);
|
670
|
+
// Copyright (c) 2005-2009 Tom Wu
|
671
|
+
// All Rights Reserved.
|
672
|
+
// See "LICENSE" for details.
|
673
|
+
|
674
|
+
// Extended JavaScript BN functions, required for RSA private ops.
|
675
|
+
|
676
|
+
// Version 1.1: new BigInteger("0", 10) returns "proper" zero
|
677
|
+
|
678
|
+
// (public)
|
679
|
+
function bnClone() { var r = nbi(); this.copyTo(r); return r; }
|
680
|
+
|
681
|
+
// (public) return value as integer
|
682
|
+
function bnIntValue() {
|
683
|
+
if(this.s < 0) {
|
684
|
+
if(this.t == 1) return this[0]-this.DV;
|
685
|
+
else if(this.t == 0) return -1;
|
686
|
+
}
|
687
|
+
else if(this.t == 1) return this[0];
|
688
|
+
else if(this.t == 0) return 0;
|
689
|
+
// assumes 16 < DB < 32
|
690
|
+
return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
|
691
|
+
}
|
692
|
+
|
693
|
+
// (public) return value as byte
|
694
|
+
function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
|
695
|
+
|
696
|
+
// (public) return value as short (assumes DB>=16)
|
697
|
+
function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
|
698
|
+
|
699
|
+
// (protected) return x s.t. r^x < DV
|
700
|
+
function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
|
701
|
+
|
702
|
+
// (public) 0 if this == 0, 1 if this > 0
|
703
|
+
function bnSigNum() {
|
704
|
+
if(this.s < 0) return -1;
|
705
|
+
else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
|
706
|
+
else return 1;
|
707
|
+
}
|
708
|
+
|
709
|
+
// (protected) convert to radix string
|
710
|
+
function bnpToRadix(b) {
|
711
|
+
if(b == null) b = 10;
|
712
|
+
if(this.signum() == 0 || b < 2 || b > 36) return "0";
|
713
|
+
var cs = this.chunkSize(b);
|
714
|
+
var a = Math.pow(b,cs);
|
715
|
+
var d = nbv(a), y = nbi(), z = nbi(), r = "";
|
716
|
+
this.divRemTo(d,y,z);
|
717
|
+
while(y.signum() > 0) {
|
718
|
+
r = (a+z.intValue()).toString(b).substr(1) + r;
|
719
|
+
y.divRemTo(d,y,z);
|
720
|
+
}
|
721
|
+
return z.intValue().toString(b) + r;
|
722
|
+
}
|
723
|
+
|
724
|
+
// (protected) convert from radix string
|
725
|
+
function bnpFromRadix(s,b) {
|
726
|
+
this.fromInt(0);
|
727
|
+
if(b == null) b = 10;
|
728
|
+
var cs = this.chunkSize(b);
|
729
|
+
var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
|
730
|
+
for(var i = 0; i < s.length; ++i) {
|
731
|
+
var x = intAt(s,i);
|
732
|
+
if(x < 0) {
|
733
|
+
if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
|
734
|
+
continue;
|
735
|
+
}
|
736
|
+
w = b*w+x;
|
737
|
+
if(++j >= cs) {
|
738
|
+
this.dMultiply(d);
|
739
|
+
this.dAddOffset(w,0);
|
740
|
+
j = 0;
|
741
|
+
w = 0;
|
742
|
+
}
|
743
|
+
}
|
744
|
+
if(j > 0) {
|
745
|
+
this.dMultiply(Math.pow(b,j));
|
746
|
+
this.dAddOffset(w,0);
|
747
|
+
}
|
748
|
+
if(mi) BigInteger.ZERO.subTo(this,this);
|
749
|
+
}
|
750
|
+
|
751
|
+
// (protected) alternate constructor
|
752
|
+
function bnpFromNumber(a,b,c) {
|
753
|
+
if("number" == typeof b) {
|
754
|
+
// new BigInteger(int,int,RNG)
|
755
|
+
if(a < 2) this.fromInt(1);
|
756
|
+
else {
|
757
|
+
this.fromNumber(a,c);
|
758
|
+
if(!this.testBit(a-1)) // force MSB set
|
759
|
+
this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
|
760
|
+
if(this.isEven()) this.dAddOffset(1,0); // force odd
|
761
|
+
while(!this.isProbablePrime(b)) {
|
762
|
+
this.dAddOffset(2,0);
|
763
|
+
if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
|
764
|
+
}
|
765
|
+
}
|
766
|
+
}
|
767
|
+
else {
|
768
|
+
// new BigInteger(int,RNG)
|
769
|
+
var x = new Array(), t = a&7;
|
770
|
+
x.length = (a>>3)+1;
|
771
|
+
b.nextBytes(x);
|
772
|
+
if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
|
773
|
+
this.fromString(x,256);
|
774
|
+
}
|
775
|
+
}
|
776
|
+
|
777
|
+
// (public) convert to bigendian byte array
|
778
|
+
function bnToByteArray() {
|
779
|
+
var i = this.t, r = new Array();
|
780
|
+
r[0] = this.s;
|
781
|
+
var p = this.DB-(i*this.DB)%8, d, k = 0;
|
782
|
+
if(i-- > 0) {
|
783
|
+
if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
|
784
|
+
r[k++] = d|(this.s<<(this.DB-p));
|
785
|
+
while(i >= 0) {
|
786
|
+
if(p < 8) {
|
787
|
+
d = (this[i]&((1<<p)-1))<<(8-p);
|
788
|
+
d |= this[--i]>>(p+=this.DB-8);
|
789
|
+
}
|
790
|
+
else {
|
791
|
+
d = (this[i]>>(p-=8))&0xff;
|
792
|
+
if(p <= 0) { p += this.DB; --i; }
|
793
|
+
}
|
794
|
+
if((d&0x80) != 0) d |= -256;
|
795
|
+
if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
|
796
|
+
if(k > 0 || d != this.s) r[k++] = d;
|
797
|
+
}
|
798
|
+
}
|
799
|
+
return r;
|
800
|
+
}
|
801
|
+
|
802
|
+
function bnEquals(a) { return(this.compareTo(a)==0); }
|
803
|
+
function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
|
804
|
+
function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
|
805
|
+
|
806
|
+
// (protected) r = this op a (bitwise)
|
807
|
+
function bnpBitwiseTo(a,op,r) {
|
808
|
+
var i, f, m = Math.min(a.t,this.t);
|
809
|
+
for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
|
810
|
+
if(a.t < this.t) {
|
811
|
+
f = a.s&this.DM;
|
812
|
+
for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
|
813
|
+
r.t = this.t;
|
814
|
+
}
|
815
|
+
else {
|
816
|
+
f = this.s&this.DM;
|
817
|
+
for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
|
818
|
+
r.t = a.t;
|
819
|
+
}
|
820
|
+
r.s = op(this.s,a.s);
|
821
|
+
r.clamp();
|
822
|
+
}
|
823
|
+
|
824
|
+
// (public) this & a
|
825
|
+
function op_and(x,y) { return x&y; }
|
826
|
+
function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
|
827
|
+
|
828
|
+
// (public) this | a
|
829
|
+
function op_or(x,y) { return x|y; }
|
830
|
+
function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
|
831
|
+
|
832
|
+
// (public) this ^ a
|
833
|
+
function op_xor(x,y) { return x^y; }
|
834
|
+
function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
|
835
|
+
|
836
|
+
// (public) this & ~a
|
837
|
+
function op_andnot(x,y) { return x&~y; }
|
838
|
+
function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
|
839
|
+
|
840
|
+
// (public) ~this
|
841
|
+
function bnNot() {
|
842
|
+
var r = nbi();
|
843
|
+
for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
|
844
|
+
r.t = this.t;
|
845
|
+
r.s = ~this.s;
|
846
|
+
return r;
|
847
|
+
}
|
848
|
+
|
849
|
+
// (public) this << n
|
850
|
+
function bnShiftLeft(n) {
|
851
|
+
var r = nbi();
|
852
|
+
if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
|
853
|
+
return r;
|
854
|
+
}
|
855
|
+
|
856
|
+
// (public) this >> n
|
857
|
+
function bnShiftRight(n) {
|
858
|
+
var r = nbi();
|
859
|
+
if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
|
860
|
+
return r;
|
861
|
+
}
|
862
|
+
|
863
|
+
// return index of lowest 1-bit in x, x < 2^31
|
864
|
+
function lbit(x) {
|
865
|
+
if(x == 0) return -1;
|
866
|
+
var r = 0;
|
867
|
+
if((x&0xffff) == 0) { x >>= 16; r += 16; }
|
868
|
+
if((x&0xff) == 0) { x >>= 8; r += 8; }
|
869
|
+
if((x&0xf) == 0) { x >>= 4; r += 4; }
|
870
|
+
if((x&3) == 0) { x >>= 2; r += 2; }
|
871
|
+
if((x&1) == 0) ++r;
|
872
|
+
return r;
|
873
|
+
}
|
874
|
+
|
875
|
+
// (public) returns index of lowest 1-bit (or -1 if none)
|
876
|
+
function bnGetLowestSetBit() {
|
877
|
+
for(var i = 0; i < this.t; ++i)
|
878
|
+
if(this[i] != 0) return i*this.DB+lbit(this[i]);
|
879
|
+
if(this.s < 0) return this.t*this.DB;
|
880
|
+
return -1;
|
881
|
+
}
|
882
|
+
|
883
|
+
// return number of 1 bits in x
|
884
|
+
function cbit(x) {
|
885
|
+
var r = 0;
|
886
|
+
while(x != 0) { x &= x-1; ++r; }
|
887
|
+
return r;
|
888
|
+
}
|
889
|
+
|
890
|
+
// (public) return number of set bits
|
891
|
+
function bnBitCount() {
|
892
|
+
var r = 0, x = this.s&this.DM;
|
893
|
+
for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
|
894
|
+
return r;
|
895
|
+
}
|
896
|
+
|
897
|
+
// (public) true iff nth bit is set
|
898
|
+
function bnTestBit(n) {
|
899
|
+
var j = Math.floor(n/this.DB);
|
900
|
+
if(j >= this.t) return(this.s!=0);
|
901
|
+
return((this[j]&(1<<(n%this.DB)))!=0);
|
902
|
+
}
|
903
|
+
|
904
|
+
// (protected) this op (1<<n)
|
905
|
+
function bnpChangeBit(n,op) {
|
906
|
+
var r = BigInteger.ONE.shiftLeft(n);
|
907
|
+
this.bitwiseTo(r,op,r);
|
908
|
+
return r;
|
909
|
+
}
|
910
|
+
|
911
|
+
// (public) this | (1<<n)
|
912
|
+
function bnSetBit(n) { return this.changeBit(n,op_or); }
|
913
|
+
|
914
|
+
// (public) this & ~(1<<n)
|
915
|
+
function bnClearBit(n) { return this.changeBit(n,op_andnot); }
|
916
|
+
|
917
|
+
// (public) this ^ (1<<n)
|
918
|
+
function bnFlipBit(n) { return this.changeBit(n,op_xor); }
|
919
|
+
|
920
|
+
// (protected) r = this + a
|
921
|
+
function bnpAddTo(a,r) {
|
922
|
+
var i = 0, c = 0, m = Math.min(a.t,this.t);
|
923
|
+
while(i < m) {
|
924
|
+
c += this[i]+a[i];
|
925
|
+
r[i++] = c&this.DM;
|
926
|
+
c >>= this.DB;
|
927
|
+
}
|
928
|
+
if(a.t < this.t) {
|
929
|
+
c += a.s;
|
930
|
+
while(i < this.t) {
|
931
|
+
c += this[i];
|
932
|
+
r[i++] = c&this.DM;
|
933
|
+
c >>= this.DB;
|
934
|
+
}
|
935
|
+
c += this.s;
|
936
|
+
}
|
937
|
+
else {
|
938
|
+
c += this.s;
|
939
|
+
while(i < a.t) {
|
940
|
+
c += a[i];
|
941
|
+
r[i++] = c&this.DM;
|
942
|
+
c >>= this.DB;
|
943
|
+
}
|
944
|
+
c += a.s;
|
945
|
+
}
|
946
|
+
r.s = (c<0)?-1:0;
|
947
|
+
if(c > 0) r[i++] = c;
|
948
|
+
else if(c < -1) r[i++] = this.DV+c;
|
949
|
+
r.t = i;
|
950
|
+
r.clamp();
|
951
|
+
}
|
952
|
+
|
953
|
+
// (public) this + a
|
954
|
+
function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
|
955
|
+
|
956
|
+
// (public) this - a
|
957
|
+
function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
|
958
|
+
|
959
|
+
// (public) this * a
|
960
|
+
function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
|
961
|
+
|
962
|
+
// (public) this / a
|
963
|
+
function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
|
964
|
+
|
965
|
+
// (public) this % a
|
966
|
+
function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
|
967
|
+
|
968
|
+
// (public) [this/a,this%a]
|
969
|
+
function bnDivideAndRemainder(a) {
|
970
|
+
var q = nbi(), r = nbi();
|
971
|
+
this.divRemTo(a,q,r);
|
972
|
+
return new Array(q,r);
|
973
|
+
}
|
974
|
+
|
975
|
+
// (protected) this *= n, this >= 0, 1 < n < DV
|
976
|
+
function bnpDMultiply(n) {
|
977
|
+
this[this.t] = this.am(0,n-1,this,0,0,this.t);
|
978
|
+
++this.t;
|
979
|
+
this.clamp();
|
980
|
+
}
|
981
|
+
|
982
|
+
// (protected) this += n << w words, this >= 0
|
983
|
+
function bnpDAddOffset(n,w) {
|
984
|
+
if(n == 0) return;
|
985
|
+
while(this.t <= w) this[this.t++] = 0;
|
986
|
+
this[w] += n;
|
987
|
+
while(this[w] >= this.DV) {
|
988
|
+
this[w] -= this.DV;
|
989
|
+
if(++w >= this.t) this[this.t++] = 0;
|
990
|
+
++this[w];
|
991
|
+
}
|
992
|
+
}
|
993
|
+
|
994
|
+
// A "null" reducer
|
995
|
+
function NullExp() {}
|
996
|
+
function nNop(x) { return x; }
|
997
|
+
function nMulTo(x,y,r) { x.multiplyTo(y,r); }
|
998
|
+
function nSqrTo(x,r) { x.squareTo(r); }
|
999
|
+
|
1000
|
+
NullExp.prototype.convert = nNop;
|
1001
|
+
NullExp.prototype.revert = nNop;
|
1002
|
+
NullExp.prototype.mulTo = nMulTo;
|
1003
|
+
NullExp.prototype.sqrTo = nSqrTo;
|
1004
|
+
|
1005
|
+
// (public) this^e
|
1006
|
+
function bnPow(e) { return this.exp(e,new NullExp()); }
|
1007
|
+
|
1008
|
+
// (protected) r = lower n words of "this * a", a.t <= n
|
1009
|
+
// "this" should be the larger one if appropriate.
|
1010
|
+
function bnpMultiplyLowerTo(a,n,r) {
|
1011
|
+
var i = Math.min(this.t+a.t,n);
|
1012
|
+
r.s = 0; // assumes a,this >= 0
|
1013
|
+
r.t = i;
|
1014
|
+
while(i > 0) r[--i] = 0;
|
1015
|
+
var j;
|
1016
|
+
for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
|
1017
|
+
for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
|
1018
|
+
r.clamp();
|
1019
|
+
}
|
1020
|
+
|
1021
|
+
// (protected) r = "this * a" without lower n words, n > 0
|
1022
|
+
// "this" should be the larger one if appropriate.
|
1023
|
+
function bnpMultiplyUpperTo(a,n,r) {
|
1024
|
+
--n;
|
1025
|
+
var i = r.t = this.t+a.t-n;
|
1026
|
+
r.s = 0; // assumes a,this >= 0
|
1027
|
+
while(--i >= 0) r[i] = 0;
|
1028
|
+
for(i = Math.max(n-this.t,0); i < a.t; ++i)
|
1029
|
+
r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
|
1030
|
+
r.clamp();
|
1031
|
+
r.drShiftTo(1,r);
|
1032
|
+
}
|
1033
|
+
|
1034
|
+
// Barrett modular reduction
|
1035
|
+
function Barrett(m) {
|
1036
|
+
// setup Barrett
|
1037
|
+
this.r2 = nbi();
|
1038
|
+
this.q3 = nbi();
|
1039
|
+
BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
|
1040
|
+
this.mu = this.r2.divide(m);
|
1041
|
+
this.m = m;
|
1042
|
+
}
|
1043
|
+
|
1044
|
+
function barrettConvert(x) {
|
1045
|
+
if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
|
1046
|
+
else if(x.compareTo(this.m) < 0) return x;
|
1047
|
+
else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
function barrettRevert(x) { return x; }
|
1051
|
+
|
1052
|
+
// x = x mod m (HAC 14.42)
|
1053
|
+
function barrettReduce(x) {
|
1054
|
+
x.drShiftTo(this.m.t-1,this.r2);
|
1055
|
+
if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
|
1056
|
+
this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
|
1057
|
+
this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
|
1058
|
+
while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
|
1059
|
+
x.subTo(this.r2,x);
|
1060
|
+
while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
|
1061
|
+
}
|
1062
|
+
|
1063
|
+
// r = x^2 mod m; x != r
|
1064
|
+
function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
|
1065
|
+
|
1066
|
+
// r = x*y mod m; x,y != r
|
1067
|
+
function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
|
1068
|
+
|
1069
|
+
Barrett.prototype.convert = barrettConvert;
|
1070
|
+
Barrett.prototype.revert = barrettRevert;
|
1071
|
+
Barrett.prototype.reduce = barrettReduce;
|
1072
|
+
Barrett.prototype.mulTo = barrettMulTo;
|
1073
|
+
Barrett.prototype.sqrTo = barrettSqrTo;
|
1074
|
+
|
1075
|
+
// (public) this^e % m (HAC 14.85)
|
1076
|
+
function bnModPow(e,m) {
|
1077
|
+
var i = e.bitLength(), k, r = nbv(1), z;
|
1078
|
+
if(i <= 0) return r;
|
1079
|
+
else if(i < 18) k = 1;
|
1080
|
+
else if(i < 48) k = 3;
|
1081
|
+
else if(i < 144) k = 4;
|
1082
|
+
else if(i < 768) k = 5;
|
1083
|
+
else k = 6;
|
1084
|
+
if(i < 8)
|
1085
|
+
z = new Classic(m);
|
1086
|
+
else if(m.isEven())
|
1087
|
+
z = new Barrett(m);
|
1088
|
+
else
|
1089
|
+
z = new Montgomery(m);
|
1090
|
+
|
1091
|
+
// precomputation
|
1092
|
+
var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
|
1093
|
+
g[1] = z.convert(this);
|
1094
|
+
if(k > 1) {
|
1095
|
+
var g2 = nbi();
|
1096
|
+
z.sqrTo(g[1],g2);
|
1097
|
+
while(n <= km) {
|
1098
|
+
g[n] = nbi();
|
1099
|
+
z.mulTo(g2,g[n-2],g[n]);
|
1100
|
+
n += 2;
|
1101
|
+
}
|
1102
|
+
}
|
1103
|
+
|
1104
|
+
var j = e.t-1, w, is1 = true, r2 = nbi(), t;
|
1105
|
+
i = nbits(e[j])-1;
|
1106
|
+
while(j >= 0) {
|
1107
|
+
if(i >= k1) w = (e[j]>>(i-k1))&km;
|
1108
|
+
else {
|
1109
|
+
w = (e[j]&((1<<(i+1))-1))<<(k1-i);
|
1110
|
+
if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
|
1111
|
+
}
|
1112
|
+
|
1113
|
+
n = k;
|
1114
|
+
while((w&1) == 0) { w >>= 1; --n; }
|
1115
|
+
if((i -= n) < 0) { i += this.DB; --j; }
|
1116
|
+
if(is1) { // ret == 1, don't bother squaring or multiplying it
|
1117
|
+
g[w].copyTo(r);
|
1118
|
+
is1 = false;
|
1119
|
+
}
|
1120
|
+
else {
|
1121
|
+
while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
|
1122
|
+
if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
|
1123
|
+
z.mulTo(r2,g[w],r);
|
1124
|
+
}
|
1125
|
+
|
1126
|
+
while(j >= 0 && (e[j]&(1<<i)) == 0) {
|
1127
|
+
z.sqrTo(r,r2); t = r; r = r2; r2 = t;
|
1128
|
+
if(--i < 0) { i = this.DB-1; --j; }
|
1129
|
+
}
|
1130
|
+
}
|
1131
|
+
return z.revert(r);
|
1132
|
+
}
|
1133
|
+
|
1134
|
+
// (public) gcd(this,a) (HAC 14.54)
|
1135
|
+
function bnGCD(a) {
|
1136
|
+
var x = (this.s<0)?this.negate():this.clone();
|
1137
|
+
var y = (a.s<0)?a.negate():a.clone();
|
1138
|
+
if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
|
1139
|
+
var i = x.getLowestSetBit(), g = y.getLowestSetBit();
|
1140
|
+
if(g < 0) return x;
|
1141
|
+
if(i < g) g = i;
|
1142
|
+
if(g > 0) {
|
1143
|
+
x.rShiftTo(g,x);
|
1144
|
+
y.rShiftTo(g,y);
|
1145
|
+
}
|
1146
|
+
while(x.signum() > 0) {
|
1147
|
+
if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
|
1148
|
+
if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
|
1149
|
+
if(x.compareTo(y) >= 0) {
|
1150
|
+
x.subTo(y,x);
|
1151
|
+
x.rShiftTo(1,x);
|
1152
|
+
}
|
1153
|
+
else {
|
1154
|
+
y.subTo(x,y);
|
1155
|
+
y.rShiftTo(1,y);
|
1156
|
+
}
|
1157
|
+
}
|
1158
|
+
if(g > 0) y.lShiftTo(g,y);
|
1159
|
+
return y;
|
1160
|
+
}
|
1161
|
+
|
1162
|
+
// (protected) this % n, n < 2^26
|
1163
|
+
function bnpModInt(n) {
|
1164
|
+
if(n <= 0) return 0;
|
1165
|
+
var d = this.DV%n, r = (this.s<0)?n-1:0;
|
1166
|
+
if(this.t > 0)
|
1167
|
+
if(d == 0) r = this[0]%n;
|
1168
|
+
else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
|
1169
|
+
return r;
|
1170
|
+
}
|
1171
|
+
|
1172
|
+
// (public) 1/this % m (HAC 14.61)
|
1173
|
+
function bnModInverse(m) {
|
1174
|
+
var ac = m.isEven();
|
1175
|
+
if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
|
1176
|
+
var u = m.clone(), v = this.clone();
|
1177
|
+
var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
|
1178
|
+
while(u.signum() != 0) {
|
1179
|
+
while(u.isEven()) {
|
1180
|
+
u.rShiftTo(1,u);
|
1181
|
+
if(ac) {
|
1182
|
+
if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
|
1183
|
+
a.rShiftTo(1,a);
|
1184
|
+
}
|
1185
|
+
else if(!b.isEven()) b.subTo(m,b);
|
1186
|
+
b.rShiftTo(1,b);
|
1187
|
+
}
|
1188
|
+
while(v.isEven()) {
|
1189
|
+
v.rShiftTo(1,v);
|
1190
|
+
if(ac) {
|
1191
|
+
if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
|
1192
|
+
c.rShiftTo(1,c);
|
1193
|
+
}
|
1194
|
+
else if(!d.isEven()) d.subTo(m,d);
|
1195
|
+
d.rShiftTo(1,d);
|
1196
|
+
}
|
1197
|
+
if(u.compareTo(v) >= 0) {
|
1198
|
+
u.subTo(v,u);
|
1199
|
+
if(ac) a.subTo(c,a);
|
1200
|
+
b.subTo(d,b);
|
1201
|
+
}
|
1202
|
+
else {
|
1203
|
+
v.subTo(u,v);
|
1204
|
+
if(ac) c.subTo(a,c);
|
1205
|
+
d.subTo(b,d);
|
1206
|
+
}
|
1207
|
+
}
|
1208
|
+
if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
|
1209
|
+
if(d.compareTo(m) >= 0) return d.subtract(m);
|
1210
|
+
if(d.signum() < 0) d.addTo(m,d); else return d;
|
1211
|
+
if(d.signum() < 0) return d.add(m); else return d;
|
1212
|
+
}
|
1213
|
+
|
1214
|
+
var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509];
|
1215
|
+
var lplim = (1<<26)/lowprimes[lowprimes.length-1];
|
1216
|
+
|
1217
|
+
// (public) test primality with certainty >= 1-.5^t
|
1218
|
+
function bnIsProbablePrime(t) {
|
1219
|
+
var i, x = this.abs();
|
1220
|
+
if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
|
1221
|
+
for(i = 0; i < lowprimes.length; ++i)
|
1222
|
+
if(x[0] == lowprimes[i]) return true;
|
1223
|
+
return false;
|
1224
|
+
}
|
1225
|
+
if(x.isEven()) return false;
|
1226
|
+
i = 1;
|
1227
|
+
while(i < lowprimes.length) {
|
1228
|
+
var m = lowprimes[i], j = i+1;
|
1229
|
+
while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
|
1230
|
+
m = x.modInt(m);
|
1231
|
+
while(i < j) if(m%lowprimes[i++] == 0) return false;
|
1232
|
+
}
|
1233
|
+
return x.millerRabin(t);
|
1234
|
+
}
|
1235
|
+
|
1236
|
+
// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
|
1237
|
+
function bnpMillerRabin(t) {
|
1238
|
+
var n1 = this.subtract(BigInteger.ONE);
|
1239
|
+
var k = n1.getLowestSetBit();
|
1240
|
+
if(k <= 0) return false;
|
1241
|
+
var r = n1.shiftRight(k);
|
1242
|
+
t = (t+1)>>1;
|
1243
|
+
if(t > lowprimes.length) t = lowprimes.length;
|
1244
|
+
var a = nbi();
|
1245
|
+
for(var i = 0; i < t; ++i) {
|
1246
|
+
a.fromInt(lowprimes[i]);
|
1247
|
+
var y = a.modPow(r,this);
|
1248
|
+
if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
|
1249
|
+
var j = 1;
|
1250
|
+
while(j++ < k && y.compareTo(n1) != 0) {
|
1251
|
+
y = y.modPowInt(2,this);
|
1252
|
+
if(y.compareTo(BigInteger.ONE) == 0) return false;
|
1253
|
+
}
|
1254
|
+
if(y.compareTo(n1) != 0) return false;
|
1255
|
+
}
|
1256
|
+
}
|
1257
|
+
return true;
|
1258
|
+
}
|
1259
|
+
|
1260
|
+
// protected
|
1261
|
+
BigInteger.prototype.chunkSize = bnpChunkSize;
|
1262
|
+
BigInteger.prototype.toRadix = bnpToRadix;
|
1263
|
+
BigInteger.prototype.fromRadix = bnpFromRadix;
|
1264
|
+
BigInteger.prototype.fromNumber = bnpFromNumber;
|
1265
|
+
BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
|
1266
|
+
BigInteger.prototype.changeBit = bnpChangeBit;
|
1267
|
+
BigInteger.prototype.addTo = bnpAddTo;
|
1268
|
+
BigInteger.prototype.dMultiply = bnpDMultiply;
|
1269
|
+
BigInteger.prototype.dAddOffset = bnpDAddOffset;
|
1270
|
+
BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
|
1271
|
+
BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
|
1272
|
+
BigInteger.prototype.modInt = bnpModInt;
|
1273
|
+
BigInteger.prototype.millerRabin = bnpMillerRabin;
|
1274
|
+
|
1275
|
+
// public
|
1276
|
+
BigInteger.prototype.clone = bnClone;
|
1277
|
+
BigInteger.prototype.intValue = bnIntValue;
|
1278
|
+
BigInteger.prototype.byteValue = bnByteValue;
|
1279
|
+
BigInteger.prototype.shortValue = bnShortValue;
|
1280
|
+
BigInteger.prototype.signum = bnSigNum;
|
1281
|
+
BigInteger.prototype.toByteArray = bnToByteArray;
|
1282
|
+
BigInteger.prototype.equals = bnEquals;
|
1283
|
+
BigInteger.prototype.min = bnMin;
|
1284
|
+
BigInteger.prototype.max = bnMax;
|
1285
|
+
BigInteger.prototype.and = bnAnd;
|
1286
|
+
BigInteger.prototype.or = bnOr;
|
1287
|
+
BigInteger.prototype.xor = bnXor;
|
1288
|
+
BigInteger.prototype.andNot = bnAndNot;
|
1289
|
+
BigInteger.prototype.not = bnNot;
|
1290
|
+
BigInteger.prototype.shiftLeft = bnShiftLeft;
|
1291
|
+
BigInteger.prototype.shiftRight = bnShiftRight;
|
1292
|
+
BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
|
1293
|
+
BigInteger.prototype.bitCount = bnBitCount;
|
1294
|
+
BigInteger.prototype.testBit = bnTestBit;
|
1295
|
+
BigInteger.prototype.setBit = bnSetBit;
|
1296
|
+
BigInteger.prototype.clearBit = bnClearBit;
|
1297
|
+
BigInteger.prototype.flipBit = bnFlipBit;
|
1298
|
+
BigInteger.prototype.add = bnAdd;
|
1299
|
+
BigInteger.prototype.subtract = bnSubtract;
|
1300
|
+
BigInteger.prototype.multiply = bnMultiply;
|
1301
|
+
BigInteger.prototype.divide = bnDivide;
|
1302
|
+
BigInteger.prototype.remainder = bnRemainder;
|
1303
|
+
BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
|
1304
|
+
BigInteger.prototype.modPow = bnModPow;
|
1305
|
+
BigInteger.prototype.modInverse = bnModInverse;
|
1306
|
+
BigInteger.prototype.pow = bnPow;
|
1307
|
+
BigInteger.prototype.gcd = bnGCD;
|
1308
|
+
BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
|
1309
|
+
|
1310
|
+
// BigInteger interfaces not implemented in jsbn:
|
1311
|
+
|
1312
|
+
// BigInteger(int signum, byte[] magnitude)
|
1313
|
+
// double doubleValue()
|
1314
|
+
// float floatValue()
|
1315
|
+
// int hashCode()
|
1316
|
+
// long longValue()
|
1317
|
+
// static BigInteger valueOf(long val)
|
1318
|
+
// Depends on jsbn.js and rng.js
|
1319
|
+
|
1320
|
+
// Version 1.1: support utf-8 encoding in pkcs1pad2
|
1321
|
+
|
1322
|
+
// convert a (hex) string to a bignum object
|
1323
|
+
function parseBigInt(str,r) {
|
1324
|
+
return new BigInteger(str,r);
|
1325
|
+
}
|
1326
|
+
|
1327
|
+
function linebrk(s,n) {
|
1328
|
+
var ret = "";
|
1329
|
+
var i = 0;
|
1330
|
+
while(i + n < s.length) {
|
1331
|
+
ret += s.substring(i,i+n) + "\n";
|
1332
|
+
i += n;
|
1333
|
+
}
|
1334
|
+
return ret + s.substring(i,s.length);
|
1335
|
+
}
|
1336
|
+
|
1337
|
+
function byte2Hex(b) {
|
1338
|
+
if(b < 0x10)
|
1339
|
+
return "0" + b.toString(16);
|
1340
|
+
else
|
1341
|
+
return b.toString(16);
|
1342
|
+
}
|
1343
|
+
|
1344
|
+
// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
|
1345
|
+
function pkcs1pad2(s,n) {
|
1346
|
+
if(n < s.length + 11) { // TODO: fix for utf-8
|
1347
|
+
alert("Message too long for RSA");
|
1348
|
+
return null;
|
1349
|
+
}
|
1350
|
+
var ba = new Array();
|
1351
|
+
var i = s.length - 1;
|
1352
|
+
while(i >= 0 && n > 0) {
|
1353
|
+
var c = s.charCodeAt(i--);
|
1354
|
+
if(c < 128) { // encode using utf-8
|
1355
|
+
ba[--n] = c;
|
1356
|
+
}
|
1357
|
+
else if((c > 127) && (c < 2048)) {
|
1358
|
+
ba[--n] = (c & 63) | 128;
|
1359
|
+
ba[--n] = (c >> 6) | 192;
|
1360
|
+
}
|
1361
|
+
else {
|
1362
|
+
ba[--n] = (c & 63) | 128;
|
1363
|
+
ba[--n] = ((c >> 6) & 63) | 128;
|
1364
|
+
ba[--n] = (c >> 12) | 224;
|
1365
|
+
}
|
1366
|
+
}
|
1367
|
+
ba[--n] = 0;
|
1368
|
+
var rng = new SecureRandom();
|
1369
|
+
var x = new Array();
|
1370
|
+
while(n > 2) { // random non-zero pad
|
1371
|
+
x[0] = 0;
|
1372
|
+
while(x[0] == 0) rng.nextBytes(x);
|
1373
|
+
ba[--n] = x[0];
|
1374
|
+
}
|
1375
|
+
ba[--n] = 2;
|
1376
|
+
ba[--n] = 0;
|
1377
|
+
return new BigInteger(ba);
|
1378
|
+
}
|
1379
|
+
|
1380
|
+
// "empty" RSA key constructor
|
1381
|
+
function RSAKey() {
|
1382
|
+
this.n = null;
|
1383
|
+
this.e = 0;
|
1384
|
+
this.d = null;
|
1385
|
+
this.p = null;
|
1386
|
+
this.q = null;
|
1387
|
+
this.dmp1 = null;
|
1388
|
+
this.dmq1 = null;
|
1389
|
+
this.coeff = null;
|
1390
|
+
}
|
1391
|
+
|
1392
|
+
// Set the public key fields N and e from hex strings
|
1393
|
+
function RSASetPublic(N,E) {
|
1394
|
+
if(N != null && E != null && N.length > 0 && E.length > 0) {
|
1395
|
+
this.n = parseBigInt(N,16);
|
1396
|
+
this.e = parseInt(E,16);
|
1397
|
+
}
|
1398
|
+
else
|
1399
|
+
alert("Invalid RSA public key");
|
1400
|
+
}
|
1401
|
+
|
1402
|
+
// Perform raw public operation on "x": return x^e (mod n)
|
1403
|
+
function RSADoPublic(x) {
|
1404
|
+
return x.modPowInt(this.e, this.n);
|
1405
|
+
}
|
1406
|
+
|
1407
|
+
// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
|
1408
|
+
function RSAEncrypt(text) {
|
1409
|
+
var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
|
1410
|
+
if(m == null) return null;
|
1411
|
+
var c = this.doPublic(m);
|
1412
|
+
if(c == null) return null;
|
1413
|
+
var h = c.toString(16);
|
1414
|
+
if((h.length & 1) == 0) return h; else return "0" + h;
|
1415
|
+
}
|
1416
|
+
|
1417
|
+
// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
|
1418
|
+
//function RSAEncryptB64(text) {
|
1419
|
+
// var h = this.encrypt(text);
|
1420
|
+
// if(h) return hex2b64(h); else return null;
|
1421
|
+
//}
|
1422
|
+
|
1423
|
+
// protected
|
1424
|
+
RSAKey.prototype.doPublic = RSADoPublic;
|
1425
|
+
|
1426
|
+
// public
|
1427
|
+
RSAKey.prototype.setPublic = RSASetPublic;
|
1428
|
+
RSAKey.prototype.encrypt = RSAEncrypt;
|
1429
|
+
//RSAKey.prototype.encrypt_b64 = RSAEncryptB64;
|
1430
|
+
// Depends on rsa.js and jsbn2.js
|
1431
|
+
|
1432
|
+
// Version 1.1: support utf-8 decoding in pkcs1unpad2
|
1433
|
+
|
1434
|
+
// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
|
1435
|
+
function pkcs1unpad2(d,n) {
|
1436
|
+
var b = d.toByteArray();
|
1437
|
+
var i = 0;
|
1438
|
+
while(i < b.length && b[i] == 0) ++i;
|
1439
|
+
if(b.length-i != n-1 || b[i] != 2)
|
1440
|
+
return null;
|
1441
|
+
++i;
|
1442
|
+
while(b[i] != 0)
|
1443
|
+
if(++i >= b.length) return null;
|
1444
|
+
var ret = "";
|
1445
|
+
while(++i < b.length) {
|
1446
|
+
var c = b[i] & 255;
|
1447
|
+
if(c < 128) { // utf-8 decode
|
1448
|
+
ret += String.fromCharCode(c);
|
1449
|
+
}
|
1450
|
+
else if((c > 191) && (c < 224)) {
|
1451
|
+
ret += String.fromCharCode(((c & 31) << 6) | (b[i+1] & 63));
|
1452
|
+
++i;
|
1453
|
+
}
|
1454
|
+
else {
|
1455
|
+
ret += String.fromCharCode(((c & 15) << 12) | ((b[i+1] & 63) << 6) | (b[i+2] & 63));
|
1456
|
+
i += 2;
|
1457
|
+
}
|
1458
|
+
}
|
1459
|
+
return ret;
|
1460
|
+
}
|
1461
|
+
|
1462
|
+
// Set the private key fields N, e, and d from hex strings
|
1463
|
+
function RSASetPrivate(N,E,D) {
|
1464
|
+
if(N != null && E != null && N.length > 0 && E.length > 0) {
|
1465
|
+
this.n = parseBigInt(N,16);
|
1466
|
+
this.e = parseInt(E,16);
|
1467
|
+
this.d = parseBigInt(D,16);
|
1468
|
+
}
|
1469
|
+
else
|
1470
|
+
alert("Invalid RSA private key");
|
1471
|
+
}
|
1472
|
+
|
1473
|
+
// Set the private key fields N, e, d and CRT params from hex strings
|
1474
|
+
function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) {
|
1475
|
+
if(N != null && E != null && N.length > 0 && E.length > 0) {
|
1476
|
+
this.n = parseBigInt(N,16);
|
1477
|
+
this.e = parseInt(E,16);
|
1478
|
+
this.d = parseBigInt(D,16);
|
1479
|
+
this.p = parseBigInt(P,16);
|
1480
|
+
this.q = parseBigInt(Q,16);
|
1481
|
+
this.dmp1 = parseBigInt(DP,16);
|
1482
|
+
this.dmq1 = parseBigInt(DQ,16);
|
1483
|
+
this.coeff = parseBigInt(C,16);
|
1484
|
+
}
|
1485
|
+
else
|
1486
|
+
alert("Invalid RSA private key");
|
1487
|
+
}
|
1488
|
+
|
1489
|
+
// Generate a new random private key B bits long, using public expt E
|
1490
|
+
function RSAGenerate(B,E) {
|
1491
|
+
var rng = new SecureRandom();
|
1492
|
+
var qs = B>>1;
|
1493
|
+
this.e = parseInt(E,16);
|
1494
|
+
var ee = new BigInteger(E,16);
|
1495
|
+
for(;;) {
|
1496
|
+
for(;;) {
|
1497
|
+
this.p = new BigInteger(B-qs,1,rng);
|
1498
|
+
if(this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break;
|
1499
|
+
}
|
1500
|
+
for(;;) {
|
1501
|
+
this.q = new BigInteger(qs,1,rng);
|
1502
|
+
if(this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break;
|
1503
|
+
}
|
1504
|
+
if(this.p.compareTo(this.q) <= 0) {
|
1505
|
+
var t = this.p;
|
1506
|
+
this.p = this.q;
|
1507
|
+
this.q = t;
|
1508
|
+
}
|
1509
|
+
var p1 = this.p.subtract(BigInteger.ONE);
|
1510
|
+
var q1 = this.q.subtract(BigInteger.ONE);
|
1511
|
+
var phi = p1.multiply(q1);
|
1512
|
+
if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
|
1513
|
+
this.n = this.p.multiply(this.q);
|
1514
|
+
this.d = ee.modInverse(phi);
|
1515
|
+
this.dmp1 = this.d.mod(p1);
|
1516
|
+
this.dmq1 = this.d.mod(q1);
|
1517
|
+
this.coeff = this.q.modInverse(this.p);
|
1518
|
+
break;
|
1519
|
+
}
|
1520
|
+
}
|
1521
|
+
}
|
1522
|
+
|
1523
|
+
// Perform raw private operation on "x": return x^d (mod n)
|
1524
|
+
function RSADoPrivate(x) {
|
1525
|
+
if(this.p == null || this.q == null)
|
1526
|
+
return x.modPow(this.d, this.n);
|
1527
|
+
|
1528
|
+
// TODO: re-calculate any missing CRT params
|
1529
|
+
var xp = x.mod(this.p).modPow(this.dmp1, this.p);
|
1530
|
+
var xq = x.mod(this.q).modPow(this.dmq1, this.q);
|
1531
|
+
|
1532
|
+
while(xp.compareTo(xq) < 0)
|
1533
|
+
xp = xp.add(this.p);
|
1534
|
+
return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);
|
1535
|
+
}
|
1536
|
+
|
1537
|
+
// Return the PKCS#1 RSA decryption of "ctext".
|
1538
|
+
// "ctext" is an even-length hex string and the output is a plain string.
|
1539
|
+
function RSADecrypt(ctext) {
|
1540
|
+
var c = parseBigInt(ctext, 16);
|
1541
|
+
var m = this.doPrivate(c);
|
1542
|
+
if(m == null) return null;
|
1543
|
+
return pkcs1unpad2(m, (this.n.bitLength()+7)>>3);
|
1544
|
+
}
|
1545
|
+
|
1546
|
+
// Return the PKCS#1 RSA decryption of "ctext".
|
1547
|
+
// "ctext" is a Base64-encoded string and the output is a plain string.
|
1548
|
+
//function RSAB64Decrypt(ctext) {
|
1549
|
+
// var h = b64tohex(ctext);
|
1550
|
+
// if(h) return this.decrypt(h); else return null;
|
1551
|
+
//}
|
1552
|
+
|
1553
|
+
// protected
|
1554
|
+
RSAKey.prototype.doPrivate = RSADoPrivate;
|
1555
|
+
|
1556
|
+
// public
|
1557
|
+
RSAKey.prototype.setPrivate = RSASetPrivate;
|
1558
|
+
RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
|
1559
|
+
RSAKey.prototype.generate = RSAGenerate;
|
1560
|
+
RSAKey.prototype.decrypt = RSADecrypt;
|
1561
|
+
//RSAKey.prototype.b64_decrypt = RSAB64Decrypt;
|
1562
|
+
//
|
1563
|
+
// asn1hex.js - Hexadecimal represented ASN.1 string library
|
1564
|
+
//
|
1565
|
+
//
|
1566
|
+
// version: 1.0 (2010-Jun-03)
|
1567
|
+
//
|
1568
|
+
// Copyright (c) 2010 Kenji Urushima (kenji.urushima@gmail.com)
|
1569
|
+
//
|
1570
|
+
// This software is licensed under the terms of the MIT License.
|
1571
|
+
// http://www.opensource.org/licenses/mit-license.php
|
1572
|
+
//
|
1573
|
+
// The above copyright and license notice shall be
|
1574
|
+
// included in all copies or substantial portions of the Software.
|
1575
|
+
//
|
1576
|
+
//
|
1577
|
+
// Depends on:
|
1578
|
+
//
|
1579
|
+
|
1580
|
+
// MEMO:
|
1581
|
+
// f('3082025b02...', 2) ... 82025b ... 3bytes
|
1582
|
+
// f('020100', 2) ... 01 ... 1byte
|
1583
|
+
// f('0203001...', 2) ... 03 ... 1byte
|
1584
|
+
// f('02818003...', 2) ... 8180 ... 2bytes
|
1585
|
+
// f('3080....0000', 2) ... 80 ... -1
|
1586
|
+
//
|
1587
|
+
// Requirements:
|
1588
|
+
// - ASN.1 type octet length MUST be 1.
|
1589
|
+
// (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...)
|
1590
|
+
// -
|
1591
|
+
function _asnhex_getByteLengthOfL_AtObj(s, pos) {
|
1592
|
+
if (s.substring(pos + 2, pos + 3) != '8') return 1;
|
1593
|
+
var i = parseInt(s.substring(pos + 3, pos + 4));
|
1594
|
+
if (i == 0) return -1; // length octet '80' indefinite length
|
1595
|
+
if (0 < i && i < 10) return i + 1; // including '8?' octet;
|
1596
|
+
return -2; // malformed format
|
1597
|
+
}
|
1598
|
+
|
1599
|
+
function _asnhex_getHexOfL_AtObj(s, pos) {
|
1600
|
+
var len = _asnhex_getByteLengthOfL_AtObj(s, pos);
|
1601
|
+
if (len < 1) return '';
|
1602
|
+
return s.substring(pos + 2, pos + 2 + len * 2);
|
1603
|
+
}
|
1604
|
+
|
1605
|
+
//
|
1606
|
+
// getting ASN.1 length value at the position 'idx' of
|
1607
|
+
// hexa decimal string 's'.
|
1608
|
+
//
|
1609
|
+
// f('3082025b02...', 0) ... 82025b ... ???
|
1610
|
+
// f('020100', 0) ... 01 ... 1
|
1611
|
+
// f('0203001...', 0) ... 03 ... 3
|
1612
|
+
// f('02818003...', 0) ... 8180 ... 128
|
1613
|
+
function _asnhex_getIntOfL_AtObj(s, pos) {
|
1614
|
+
var hLength = _asnhex_getHexOfL_AtObj(s, pos);
|
1615
|
+
if (hLength == '') return -1;
|
1616
|
+
var bi;
|
1617
|
+
if (parseInt(hLength.substring(0, 1)) < 8) {
|
1618
|
+
bi = parseBigInt(hLength, 16);
|
1619
|
+
} else {
|
1620
|
+
bi = parseBigInt(hLength.substring(2), 16);
|
1621
|
+
}
|
1622
|
+
return bi.intValue();
|
1623
|
+
}
|
1624
|
+
|
1625
|
+
//
|
1626
|
+
// get ASN.1 value starting string position
|
1627
|
+
// for ASN.1 object refered by index 'idx'.
|
1628
|
+
//
|
1629
|
+
function _asnhex_getStartPosOfV_AtObj(s, pos) {
|
1630
|
+
var l_len = _asnhex_getByteLengthOfL_AtObj(s, pos);
|
1631
|
+
if (l_len < 0) return l_len;
|
1632
|
+
return pos + (l_len + 1) * 2;
|
1633
|
+
}
|
1634
|
+
|
1635
|
+
function _asnhex_getHexOfV_AtObj(s, pos) {
|
1636
|
+
var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
|
1637
|
+
var len = _asnhex_getIntOfL_AtObj(s, pos);
|
1638
|
+
return s.substring(pos1, pos1 + len * 2);
|
1639
|
+
}
|
1640
|
+
|
1641
|
+
function _asnhex_getPosOfNextSibling_AtObj(s, pos) {
|
1642
|
+
var pos1 = _asnhex_getStartPosOfV_AtObj(s, pos);
|
1643
|
+
var len = _asnhex_getIntOfL_AtObj(s, pos);
|
1644
|
+
return pos1 + len * 2;
|
1645
|
+
}
|
1646
|
+
|
1647
|
+
function _asnhex_getPosArrayOfChildren_AtObj(h, pos) {
|
1648
|
+
var a = new Array();
|
1649
|
+
var p0 = _asnhex_getStartPosOfV_AtObj(h, pos);
|
1650
|
+
a.push(p0);
|
1651
|
+
|
1652
|
+
var len = _asnhex_getIntOfL_AtObj(h, pos);
|
1653
|
+
var p = p0;
|
1654
|
+
var k = 0;
|
1655
|
+
while (1) {
|
1656
|
+
var pNext = _asnhex_getPosOfNextSibling_AtObj(h, p);
|
1657
|
+
if (pNext == null || (pNext - p0 >= (len * 2))) break;
|
1658
|
+
if (k >= 200) break;
|
1659
|
+
|
1660
|
+
a.push(pNext);
|
1661
|
+
p = pNext;
|
1662
|
+
|
1663
|
+
k++;
|
1664
|
+
}
|
1665
|
+
|
1666
|
+
return a;
|
1667
|
+
}
|
1668
|
+
//
|
1669
|
+
// rsa-pem.js - adding function for reading/writing PKCS#1 PEM private key
|
1670
|
+
// to RSAKey class.
|
1671
|
+
//
|
1672
|
+
// version: 1.0 (2010-Jun-03)
|
1673
|
+
//
|
1674
|
+
// Copyright (c) 2010 Kenji Urushima (kenji.urushima@gmail.com)
|
1675
|
+
//
|
1676
|
+
// This software is licensed under the terms of the MIT License.
|
1677
|
+
// http://www.opensource.org/licenses/mit-license.php
|
1678
|
+
//
|
1679
|
+
// The above copyright and license notice shall be
|
1680
|
+
// included in all copies or substantial portions of the Software.
|
1681
|
+
//
|
1682
|
+
//
|
1683
|
+
// Depends on:
|
1684
|
+
//
|
1685
|
+
//
|
1686
|
+
//
|
1687
|
+
// _RSApem_pemToBase64(sPEM)
|
1688
|
+
//
|
1689
|
+
// removing PEM header, PEM footer and space characters including
|
1690
|
+
// new lines from PEM formatted RSA private key string.
|
1691
|
+
//
|
1692
|
+
function _rsapem_pemToBase64(sPEMPrivateKey) {
|
1693
|
+
var s = sPEMPrivateKey;
|
1694
|
+
s = s.replace("-----BEGIN RSA PRIVATE KEY-----", "");
|
1695
|
+
s = s.replace("-----END RSA PRIVATE KEY-----", "");
|
1696
|
+
s = s.replace(/[ \n]+/g, "");
|
1697
|
+
return s;
|
1698
|
+
}
|
1699
|
+
|
1700
|
+
function _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey) {
|
1701
|
+
var a = new Array();
|
1702
|
+
var v1 = _asnhex_getStartPosOfV_AtObj(hPrivateKey, 0);
|
1703
|
+
var n1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, v1);
|
1704
|
+
var e1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, n1);
|
1705
|
+
var d1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, e1);
|
1706
|
+
var p1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, d1);
|
1707
|
+
var q1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, p1);
|
1708
|
+
var dp1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, q1);
|
1709
|
+
var dq1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, dp1);
|
1710
|
+
var co1 = _asnhex_getPosOfNextSibling_AtObj(hPrivateKey, dq1);
|
1711
|
+
a.push(v1, n1, e1, d1, p1, q1, dp1, dq1, co1);
|
1712
|
+
return a;
|
1713
|
+
}
|
1714
|
+
|
1715
|
+
function _rsapem_getHexValueArrayOfChildrenFromHex(hPrivateKey) {
|
1716
|
+
var posArray = _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey);
|
1717
|
+
var v = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[0]);
|
1718
|
+
var n = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[1]);
|
1719
|
+
var e = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[2]);
|
1720
|
+
var d = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[3]);
|
1721
|
+
var p = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[4]);
|
1722
|
+
var q = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[5]);
|
1723
|
+
var dp = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[6]);
|
1724
|
+
var dq = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[7]);
|
1725
|
+
var co = _asnhex_getHexOfV_AtObj(hPrivateKey, posArray[8]);
|
1726
|
+
var a = new Array();
|
1727
|
+
a.push(v, n, e, d, p, q, dp, dq, co);
|
1728
|
+
return a;
|
1729
|
+
}
|
1730
|
+
|
1731
|
+
function _rsapem_readPrivateKeyFromPEMString(keyPEM) {
|
1732
|
+
var keyB64 = _rsapem_pemToBase64(keyPEM);
|
1733
|
+
var keyHex = b64tohex(keyB64) // depends base64.js
|
1734
|
+
var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
|
1735
|
+
this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
|
1736
|
+
}
|
1737
|
+
|
1738
|
+
RSAKey.prototype.readPrivateKeyFromPEMString = _rsapem_readPrivateKeyFromPEMString;
|
1739
|
+
//
|
1740
|
+
// rsa-sign.js - adding signing functions to RSAKey class.
|
1741
|
+
//
|
1742
|
+
//
|
1743
|
+
// version: 1.0 (2010-Jun-03)
|
1744
|
+
//
|
1745
|
+
// Copyright (c) 2010 Kenji Urushima (kenji.urushima@gmail.com)
|
1746
|
+
//
|
1747
|
+
// This software is licensed under the terms of the MIT License.
|
1748
|
+
// http://www.opensource.org/licenses/mit-license.php
|
1749
|
+
//
|
1750
|
+
// The above copyright and license notice shall be
|
1751
|
+
// included in all copies or substantial portions of the Software.
|
1752
|
+
|
1753
|
+
//
|
1754
|
+
// Depends on:
|
1755
|
+
// function sha1.hex(s) of sha1.js
|
1756
|
+
// jsbn.js
|
1757
|
+
// jsbn2.js
|
1758
|
+
// rsa.js
|
1759
|
+
// rsa2.js
|
1760
|
+
//
|
1761
|
+
|
1762
|
+
// keysize / pmstrlen
|
1763
|
+
// 512 / 128
|
1764
|
+
// 1024 / 256
|
1765
|
+
// 2048 / 512
|
1766
|
+
// 4096 / 1024
|
1767
|
+
|
1768
|
+
// As for _RSASGIN_DIHEAD values for each hash algorithm, see PKCS#1 v2.1 spec (p38).
|
1769
|
+
var _RSASIGN_DIHEAD = [];
|
1770
|
+
_RSASIGN_DIHEAD['sha1'] = "3021300906052b0e03021a05000414";
|
1771
|
+
_RSASIGN_DIHEAD['sha256'] = "3031300d060960864801650304020105000420";
|
1772
|
+
//_RSASIGN_DIHEAD['md2'] = "3020300c06082a864886f70d020205000410";
|
1773
|
+
//_RSASIGN_DIHEAD['md5'] = "3020300c06082a864886f70d020505000410";
|
1774
|
+
//_RSASIGN_DIHEAD['sha384'] = "3041300d060960864801650304020205000430";
|
1775
|
+
//_RSASIGN_DIHEAD['sha512'] = "3051300d060960864801650304020305000440";
|
1776
|
+
var _RSASIGN_HASHHEXFUNC = [];
|
1777
|
+
//_RSASIGN_HASHHEXFUNC['sha1'] = sha1.hex;
|
1778
|
+
_RSASIGN_HASHHEXFUNC['sha256'] = function(i) { return sjcl.codec.hex.fromBits(sjcl.hash.sha256.hash(i)); }
|
1779
|
+
|
1780
|
+
// ========================================================================
|
1781
|
+
// Signature Generation
|
1782
|
+
// ========================================================================
|
1783
|
+
|
1784
|
+
function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
|
1785
|
+
var pmStrLen = keySize / 4;
|
1786
|
+
var hashFunc = _RSASIGN_HASHHEXFUNC[hashAlg];
|
1787
|
+
var sHashHex = hashFunc(s);
|
1788
|
+
|
1789
|
+
var sHead = "0001";
|
1790
|
+
var sTail = "00" + _RSASIGN_DIHEAD[hashAlg] + sHashHex;
|
1791
|
+
var sMid = "";
|
1792
|
+
var fLen = pmStrLen - sHead.length - sTail.length;
|
1793
|
+
for (var i = 0; i < fLen; i += 2) {
|
1794
|
+
sMid += "ff";
|
1795
|
+
}
|
1796
|
+
var sPaddedMessageHex = sHead + sMid + sTail;
|
1797
|
+
|
1798
|
+
return sPaddedMessageHex;
|
1799
|
+
}
|
1800
|
+
|
1801
|
+
function _rsasign_signString(s, hashAlg) {
|
1802
|
+
var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), hashAlg);
|
1803
|
+
var biPaddedMessage = parseBigInt(hPM, 16);
|
1804
|
+
var biSign = this.doPrivate(biPaddedMessage);
|
1805
|
+
var hexSign = biSign.toString(16);
|
1806
|
+
return hexSign;
|
1807
|
+
}
|
1808
|
+
|
1809
|
+
function _rsasign_signStringWithSHA1(s) {
|
1810
|
+
var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), 'sha1');
|
1811
|
+
var biPaddedMessage = parseBigInt(hPM, 16);
|
1812
|
+
var biSign = this.doPrivate(biPaddedMessage);
|
1813
|
+
var hexSign = biSign.toString(16);
|
1814
|
+
return hexSign;
|
1815
|
+
}
|
1816
|
+
|
1817
|
+
function _rsasign_signStringWithSHA256(s) {
|
1818
|
+
var hPM = _rsasign_getHexPaddedDigestInfoForString(s, this.n.bitLength(), 'sha256');
|
1819
|
+
var biPaddedMessage = parseBigInt(hPM, 16);
|
1820
|
+
var biSign = this.doPrivate(biPaddedMessage);
|
1821
|
+
var hexSign = biSign.toString(16);
|
1822
|
+
return hexSign;
|
1823
|
+
}
|
1824
|
+
|
1825
|
+
// ========================================================================
|
1826
|
+
// Signature Verification
|
1827
|
+
// ========================================================================
|
1828
|
+
|
1829
|
+
function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
|
1830
|
+
var rsa = new RSAKey();
|
1831
|
+
rsa.setPublic(hN, hE);
|
1832
|
+
var biDecryptedSig = rsa.doPublic(biSig);
|
1833
|
+
return biDecryptedSig;
|
1834
|
+
}
|
1835
|
+
|
1836
|
+
function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
|
1837
|
+
var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
|
1838
|
+
var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
|
1839
|
+
return hDigestInfo;
|
1840
|
+
}
|
1841
|
+
|
1842
|
+
function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
|
1843
|
+
for (var algName in _RSASIGN_DIHEAD) {
|
1844
|
+
var head = _RSASIGN_DIHEAD[algName];
|
1845
|
+
var len = head.length;
|
1846
|
+
if (hDigestInfo.substring(0, len) == head) {
|
1847
|
+
var a = [algName, hDigestInfo.substring(len)];
|
1848
|
+
return a;
|
1849
|
+
}
|
1850
|
+
}
|
1851
|
+
return [];
|
1852
|
+
}
|
1853
|
+
|
1854
|
+
function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
|
1855
|
+
var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
|
1856
|
+
var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
|
1857
|
+
if (digestInfoAry.length == 0) return false;
|
1858
|
+
var algName = digestInfoAry[0];
|
1859
|
+
var diHashValue = digestInfoAry[1];
|
1860
|
+
var ff = _RSASIGN_HASHHEXFUNC[algName];
|
1861
|
+
var msgHashValue = ff(sMsg);
|
1862
|
+
return (diHashValue == msgHashValue);
|
1863
|
+
}
|
1864
|
+
|
1865
|
+
function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
|
1866
|
+
var biSig = parseBigInt(hSig, 16);
|
1867
|
+
var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
|
1868
|
+
this.n.toString(16),
|
1869
|
+
this.e.toString(16));
|
1870
|
+
return result;
|
1871
|
+
}
|
1872
|
+
|
1873
|
+
function _rsasign_verifyString(sMsg, hSig) {
|
1874
|
+
hSig = hSig.replace(/[ \n]+/g, "");
|
1875
|
+
var biSig = parseBigInt(hSig, 16);
|
1876
|
+
var biDecryptedSig = this.doPublic(biSig);
|
1877
|
+
var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
|
1878
|
+
var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
|
1879
|
+
|
1880
|
+
if (digestInfoAry.length == 0) return false;
|
1881
|
+
var algName = digestInfoAry[0];
|
1882
|
+
var diHashValue = digestInfoAry[1];
|
1883
|
+
var ff = _RSASIGN_HASHHEXFUNC[algName];
|
1884
|
+
var msgHashValue = ff(sMsg);
|
1885
|
+
return (diHashValue == msgHashValue);
|
1886
|
+
}
|
1887
|
+
|
1888
|
+
RSAKey.prototype.signString = _rsasign_signString;
|
1889
|
+
RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
|
1890
|
+
RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
|
1891
|
+
|
1892
|
+
RSAKey.prototype.verifyString = _rsasign_verifyString;
|
1893
|
+
RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
|
1894
|
+
|
1895
|
+
//
|
1896
|
+
// x509.js - X509 class to read subject public key from certificate.
|
1897
|
+
//
|
1898
|
+
// version: 1.0 (2010-Jun-03)
|
1899
|
+
//
|
1900
|
+
// Copyright (c) 2010 Kenji Urushima (kenji.urushima@gmail.com)
|
1901
|
+
//
|
1902
|
+
// This software is licensed under the terms of the MIT License.
|
1903
|
+
// http://www.opensource.org/licenses/mit-license.php
|
1904
|
+
//
|
1905
|
+
// The above copyright and license notice shall be
|
1906
|
+
// included in all copies or substantial portions of the Software.
|
1907
|
+
//
|
1908
|
+
|
1909
|
+
// Depends:
|
1910
|
+
// base64.js
|
1911
|
+
// rsa.js
|
1912
|
+
|
1913
|
+
function _x509_pemToBase64(sCertPEM) {
|
1914
|
+
var s = sCertPEM;
|
1915
|
+
s = s.replace("-----BEGIN CERTIFICATE-----", "");
|
1916
|
+
s = s.replace("-----END CERTIFICATE-----", "");
|
1917
|
+
s = s.replace(/[ \n]+/g, "");
|
1918
|
+
return s;
|
1919
|
+
}
|
1920
|
+
|
1921
|
+
function _x509_pemToHex(sCertPEM) {
|
1922
|
+
var b64Cert = _x509_pemToBase64(sCertPEM);
|
1923
|
+
var hCert = b64tohex(b64Cert);
|
1924
|
+
return hCert;
|
1925
|
+
}
|
1926
|
+
|
1927
|
+
function _x509_getHexTbsCertificateFromCert(hCert) {
|
1928
|
+
var pTbsCert = _asnhex_getStartPosOfV_AtObj(hCert, 0);
|
1929
|
+
return pTbsCert;
|
1930
|
+
}
|
1931
|
+
|
1932
|
+
// NOTE: privateKeyUsagePeriod field of X509v2 not supported.
|
1933
|
+
// NOTE: v1 and v3 supported
|
1934
|
+
function _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert) {
|
1935
|
+
var pTbsCert = _asnhex_getStartPosOfV_AtObj(hCert, 0);
|
1936
|
+
var a = _asnhex_getPosArrayOfChildren_AtObj(hCert, pTbsCert);
|
1937
|
+
if (a.length < 1) return -1;
|
1938
|
+
if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3
|
1939
|
+
if (a.length < 6) return -1;
|
1940
|
+
return a[6];
|
1941
|
+
} else {
|
1942
|
+
if (a.length < 5) return -1;
|
1943
|
+
return a[5];
|
1944
|
+
}
|
1945
|
+
}
|
1946
|
+
|
1947
|
+
// NOTE: Without BITSTRING encapsulation.
|
1948
|
+
function _x509_getSubjectPublicKeyPosFromCertHex(hCert) {
|
1949
|
+
var pInfo = _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert);
|
1950
|
+
if (pInfo == -1) return -1;
|
1951
|
+
var a = _asnhex_getPosArrayOfChildren_AtObj(hCert, pInfo);
|
1952
|
+
if (a.length != 2) return -1;
|
1953
|
+
var pBitString = a[1];
|
1954
|
+
if (hCert.substring(pBitString, pBitString + 2) != '03') return -1;
|
1955
|
+
var pBitStringV = _asnhex_getStartPosOfV_AtObj(hCert, pBitString);
|
1956
|
+
|
1957
|
+
if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1;
|
1958
|
+
return pBitStringV + 2;
|
1959
|
+
}
|
1960
|
+
|
1961
|
+
function _x509_getPublicKeyHexArrayFromCertHex(hCert) {
|
1962
|
+
var p = _x509_getSubjectPublicKeyPosFromCertHex(hCert);
|
1963
|
+
var a = _asnhex_getPosArrayOfChildren_AtObj(hCert, p);
|
1964
|
+
if (a.length != 2) return [];
|
1965
|
+
var hN = _asnhex_getHexOfV_AtObj(hCert, a[0]);
|
1966
|
+
var hE = _asnhex_getHexOfV_AtObj(hCert, a[1]);
|
1967
|
+
if (hN != null && hE != null) {
|
1968
|
+
return [hN, hE];
|
1969
|
+
} else {
|
1970
|
+
return [];
|
1971
|
+
}
|
1972
|
+
}
|
1973
|
+
|
1974
|
+
function _x509_getPublicKeyHexArrayFromCertPEM(sCertPEM) {
|
1975
|
+
var hCert = _x509_pemToHex(sCertPEM);
|
1976
|
+
var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
|
1977
|
+
return a;
|
1978
|
+
}
|
1979
|
+
|
1980
|
+
function _x509_readCertPEM(sCertPEM) {
|
1981
|
+
var hCert = _x509_pemToHex(sCertPEM);
|
1982
|
+
var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
|
1983
|
+
var rsa = new RSAKey();
|
1984
|
+
rsa.setPublic(a[0], a[1]);
|
1985
|
+
this.subjectPublicKeyRSA = rsa;
|
1986
|
+
this.subjectPublicKeyRSA_hN = a[0];
|
1987
|
+
this.subjectPublicKeyRSA_hE = a[1];
|
1988
|
+
}
|
1989
|
+
|
1990
|
+
function _x509_readCertPEMWithoutRSAInit(sCertPEM) {
|
1991
|
+
var hCert = _x509_pemToHex(sCertPEM);
|
1992
|
+
var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);
|
1993
|
+
this.subjectPublicKeyRSA.setPublic(a[0], a[1]);
|
1994
|
+
this.subjectPublicKeyRSA_hN = a[0];
|
1995
|
+
this.subjectPublicKeyRSA_hE = a[1];
|
1996
|
+
}
|
1997
|
+
|
1998
|
+
function X509() {
|
1999
|
+
this.subjectPublicKeyRSA = null;
|
2000
|
+
this.subjectPublicKeyRSA_hN = null;
|
2001
|
+
this.subjectPublicKeyRSA_hE = null;
|
2002
|
+
}
|
2003
|
+
|
2004
|
+
X509.prototype.readCertPEM = _x509_readCertPEM;
|
2005
|
+
X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit;
|
2006
|
+
var jwt = {};
|
2007
|
+
|
2008
|
+
var JWTInternals = (function() {
|
2009
|
+
|
2010
|
+
// convert a base64url string to hex
|
2011
|
+
var b64urlmap="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
2012
|
+
function b64urltohex(s) {
|
2013
|
+
var ret = ""
|
2014
|
+
var i;
|
2015
|
+
var k = 0; // b64 state, 0-3
|
2016
|
+
var slop;
|
2017
|
+
for(i = 0; i < s.length; ++i) {
|
2018
|
+
var v = b64urlmap.indexOf(s.charAt(i));
|
2019
|
+
if(v < 0) continue;
|
2020
|
+
if(k == 0) {
|
2021
|
+
ret += int2char(v >> 2);
|
2022
|
+
slop = v & 3;
|
2023
|
+
k = 1;
|
2024
|
+
}
|
2025
|
+
else if(k == 1) {
|
2026
|
+
ret += int2char((slop << 2) | (v >> 4));
|
2027
|
+
slop = v & 0xf;
|
2028
|
+
k = 2;
|
2029
|
+
}
|
2030
|
+
else if(k == 2) {
|
2031
|
+
ret += int2char(slop);
|
2032
|
+
ret += int2char(v >> 2);
|
2033
|
+
slop = v & 3;
|
2034
|
+
k = 3;
|
2035
|
+
}
|
2036
|
+
else {
|
2037
|
+
ret += int2char((slop << 2) | (v >> 4));
|
2038
|
+
ret += int2char(v & 0xf);
|
2039
|
+
k = 0;
|
2040
|
+
}
|
2041
|
+
}
|
2042
|
+
if(k == 1)
|
2043
|
+
ret += int2char(slop << 2);
|
2044
|
+
return ret;
|
2045
|
+
}
|
2046
|
+
|
2047
|
+
|
2048
|
+
|
2049
|
+
function base64urlencode(arg)
|
2050
|
+
{
|
2051
|
+
var s = window.btoa(arg); // Standard base64 encoder
|
2052
|
+
s = s.split('=')[0]; // Remove any trailing '='s
|
2053
|
+
s = s.replace(/\+/g, '-'); // 62nd char of encoding
|
2054
|
+
s = s.replace(/\//g, '_'); // 63rd char of encoding
|
2055
|
+
// TODO optimize this; we can do much better
|
2056
|
+
return s;
|
2057
|
+
}
|
2058
|
+
|
2059
|
+
function base64urldecode(arg)
|
2060
|
+
{
|
2061
|
+
var s = arg;
|
2062
|
+
s = s.replace(/-/g, '+'); // 62nd char of encoding
|
2063
|
+
s = s.replace(/_/g, '/'); // 63rd char of encoding
|
2064
|
+
switch (s.length % 4) // Pad with trailing '='s
|
2065
|
+
{
|
2066
|
+
case 0: break; // No pad chars in this case
|
2067
|
+
case 2: s += "=="; break; // Two pad chars
|
2068
|
+
case 3: s += "="; break; // One pad char
|
2069
|
+
default: throw new InputException("Illegal base64url string!");
|
2070
|
+
}
|
2071
|
+
return window.atob(s); // Standard base64 decoder
|
2072
|
+
}
|
2073
|
+
|
2074
|
+
function NoSuchAlgorithmException(message) {
|
2075
|
+
this.message = message;
|
2076
|
+
this.toString = function() { return "No such algorithm: "+this.message; };
|
2077
|
+
}
|
2078
|
+
function NotImplementedException(message) {
|
2079
|
+
this.message = message;
|
2080
|
+
this.toString = function() { return "Not implemented: "+this.message; };
|
2081
|
+
}
|
2082
|
+
function InputException(message) {
|
2083
|
+
this.message = message;
|
2084
|
+
this.toString = function() { return "Malformed input: "+this.message; };
|
2085
|
+
}
|
2086
|
+
|
2087
|
+
function HMACAlgorithm(hash, key)
|
2088
|
+
{
|
2089
|
+
if (hash == "sha256") {
|
2090
|
+
this.hash = sjcl.hash.sha256;
|
2091
|
+
} else {
|
2092
|
+
throw new NoSuchAlgorithmException("HMAC does not support hash " + hash);
|
2093
|
+
}
|
2094
|
+
this.key = sjcl.codec.utf8String.toBits(key);
|
2095
|
+
}
|
2096
|
+
|
2097
|
+
HMACAlgorithm.prototype =
|
2098
|
+
{
|
2099
|
+
update: function _update(data)
|
2100
|
+
{
|
2101
|
+
this.data = data;
|
2102
|
+
},
|
2103
|
+
|
2104
|
+
finalize: function _finalize()
|
2105
|
+
{
|
2106
|
+
},
|
2107
|
+
|
2108
|
+
sign: function _sign()
|
2109
|
+
{
|
2110
|
+
var hmac = new sjcl.misc.hmac(this.key, this.hash);
|
2111
|
+
var result = hmac.encrypt(this.data);
|
2112
|
+
return base64urlencode(window.atob(sjcl.codec.base64.fromBits(result)));
|
2113
|
+
},
|
2114
|
+
|
2115
|
+
verify: function _verify(sig)
|
2116
|
+
{
|
2117
|
+
var hmac = new sjcl.misc.hmac(this.key, this.hash);
|
2118
|
+
var result = hmac.encrypt(this.data);
|
2119
|
+
|
2120
|
+
return base64urlencode(window.atob(sjcl.codec.base64.fromBits(result))) == sig;
|
2121
|
+
}
|
2122
|
+
}
|
2123
|
+
|
2124
|
+
function RSASHAAlgorithm(hash, keyPEM)
|
2125
|
+
{
|
2126
|
+
if (hash == "sha1") {
|
2127
|
+
this.hash = "sha1";
|
2128
|
+
} else if (hash == "sha256") {
|
2129
|
+
this.hash = "sha256";
|
2130
|
+
} else {
|
2131
|
+
throw new NoSuchAlgorithmException("JWT algorithm: " + hash);
|
2132
|
+
}
|
2133
|
+
this.keyPEM = keyPEM;
|
2134
|
+
}
|
2135
|
+
RSASHAAlgorithm.prototype =
|
2136
|
+
{
|
2137
|
+
update: function _update(data)
|
2138
|
+
{
|
2139
|
+
this.data = data;
|
2140
|
+
},
|
2141
|
+
finalize: function _finalize()
|
2142
|
+
{
|
2143
|
+
|
2144
|
+
},
|
2145
|
+
sign: function _sign()
|
2146
|
+
{
|
2147
|
+
var rsa = new RSAKey();
|
2148
|
+
rsa.readPrivateKeyFromPEMString(this.keyPEM);
|
2149
|
+
var hSig = rsa.signString(this.data, this.hash);
|
2150
|
+
return base64urlencode(base64urldecode(hex2b64(hSig))); // TODO replace this with hex2b64urlencode!
|
2151
|
+
},
|
2152
|
+
verify: function _verify(sig)
|
2153
|
+
{
|
2154
|
+
var result = this.keyPEM.verifyString(this.data, b64urltohex(sig));
|
2155
|
+
return result;
|
2156
|
+
}
|
2157
|
+
}
|
2158
|
+
|
2159
|
+
function WebToken(objectStr, algorithm)
|
2160
|
+
{
|
2161
|
+
this.objectStr = objectStr;
|
2162
|
+
this.pkAlgorithm = algorithm;
|
2163
|
+
}
|
2164
|
+
|
2165
|
+
var WebTokenParser = {
|
2166
|
+
|
2167
|
+
parse: function _parse(input)
|
2168
|
+
{
|
2169
|
+
var parts = input.split(".");
|
2170
|
+
if (parts.length != 3) {
|
2171
|
+
throw new MalformedWebToken("Must have three parts");
|
2172
|
+
}
|
2173
|
+
var token = new WebToken();
|
2174
|
+
token.headerSegment = parts[0];
|
2175
|
+
token.payloadSegment = parts[1];
|
2176
|
+
token.cryptoSegment = parts[2];
|
2177
|
+
|
2178
|
+
token.pkAlgorithm = base64urldecode(parts[0]);
|
2179
|
+
return token;
|
2180
|
+
}
|
2181
|
+
}
|
2182
|
+
|
2183
|
+
function jsonObj(strOrObject)
|
2184
|
+
{
|
2185
|
+
if (typeof strOrObject == "string") {
|
2186
|
+
return JSON.parse(strOrObject);
|
2187
|
+
}
|
2188
|
+
return strOrObject;
|
2189
|
+
}
|
2190
|
+
|
2191
|
+
function constructAlgorithm(jwtAlgStr, key)
|
2192
|
+
{
|
2193
|
+
if ("ES256" === jwtAlgStr) {
|
2194
|
+
throw new NotImplementedException("ECDSA-SHA256 not yet implemented");
|
2195
|
+
} else if ("ES384" === jwtAlgStr) {
|
2196
|
+
throw new NotImplementedException("ECDSA-SHA384 not yet implemented");
|
2197
|
+
} else if ("ES512" === jwtAlgStr) {
|
2198
|
+
throw new NotImplementedException("ECDSA-SHA512 not yet implemented");
|
2199
|
+
} else if ("HS256" === jwtAlgStr) {
|
2200
|
+
return new HMACAlgorithm("sha256", key);
|
2201
|
+
} else if ("HS384" === jwtAlgStr) {
|
2202
|
+
throw new NotImplementedException("HMAC-SHA384 not yet implemented");
|
2203
|
+
} else if ("HS512" === jwtAlgStr) {
|
2204
|
+
throw new NotImplementedException("HMAC-SHA512 not yet implemented");
|
2205
|
+
} else if ("RS256" === jwtAlgStr) {
|
2206
|
+
return new RSASHAAlgorithm("sha256", key);
|
2207
|
+
} else if ("RS384" === jwtAlgStr) {
|
2208
|
+
throw new NotImplementedException("RSA-SHA384 not yet implemented");
|
2209
|
+
} else if ("RS512" === jwtAlgStr) {
|
2210
|
+
throw new NotImplementedException("RSA-SHA512 not yet implemented");
|
2211
|
+
} else {
|
2212
|
+
throw new NoSuchAlgorithmException("Unknown algorithm: " + jwtAlgStr);
|
2213
|
+
}
|
2214
|
+
}
|
2215
|
+
|
2216
|
+
WebToken.prototype =
|
2217
|
+
{
|
2218
|
+
serialize: function _serialize(key)
|
2219
|
+
{
|
2220
|
+
var header = jsonObj(this.pkAlgorithm);
|
2221
|
+
var jwtAlgStr = header.alg;
|
2222
|
+
var algorithm = constructAlgorithm(jwtAlgStr, key);
|
2223
|
+
var algBytes = base64urlencode(this.pkAlgorithm);
|
2224
|
+
var jsonBytes = base64urlencode(this.objectStr);
|
2225
|
+
|
2226
|
+
var stringToSign = algBytes + "." + jsonBytes;
|
2227
|
+
algorithm.update(stringToSign);
|
2228
|
+
var digestValue = algorithm.finalize();
|
2229
|
+
|
2230
|
+
var signatureValue = algorithm.sign();
|
2231
|
+
return algBytes + "." + jsonBytes + "." + signatureValue;
|
2232
|
+
},
|
2233
|
+
|
2234
|
+
verify: function _verify(key)
|
2235
|
+
{
|
2236
|
+
var header = jsonObj(this.pkAlgorithm);
|
2237
|
+
var jwtAlgStr = header.alg;
|
2238
|
+
var algorithm = constructAlgorithm(jwtAlgStr, key);
|
2239
|
+
algorithm.update(this.headerSegment + "." + this.payloadSegment);
|
2240
|
+
algorithm.finalize();
|
2241
|
+
return algorithm.verify(this.cryptoSegment);
|
2242
|
+
}
|
2243
|
+
}
|
2244
|
+
|
2245
|
+
jwt.WebToken = WebToken;
|
2246
|
+
jwt.WebTokenParser = WebTokenParser;
|
2247
|
+
jwt.base64urlencode = base64urlencode;
|
2248
|
+
jwt.base64urldecode = base64urldecode;
|
2249
|
+
})();
|