0) {
- if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
- while(i >= 0) {
- if(p < k) {
- d = (this[i]&((1<>(p+=this.DB-k);
- }
- else {
- d = (this[i]>>(p-=k))&km;
- if(p <= 0) { p += this.DB; --i; }
- }
- if(d > 0) m = true;
- if(m) r += int2char(d);
- }
- }
- return m?r:"0";
-}
-
-// (public) -this
-function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
-
-// (public) |this|
-function bnAbs() { return (this.s<0)?this.negate():this; }
-
-// (public) return + if this > a, - if this < a, 0 if equal
-function bnCompareTo(a) {
- var r = this.s-a.s;
- if(r != 0) return r;
- var i = this.t;
- r = i-a.t;
- if(r != 0) return (this.s<0)?-r:r;
- while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
- return 0;
-}
-
-// returns bit length of the integer x
-function nbits(x) {
- var r = 1, t;
- if((t=x>>>16) != 0) { x = t; r += 16; }
- if((t=x>>8) != 0) { x = t; r += 8; }
- if((t=x>>4) != 0) { x = t; r += 4; }
- if((t=x>>2) != 0) { x = t; r += 2; }
- if((t=x>>1) != 0) { x = t; r += 1; }
- return r;
-}
-
-// (public) return the number of bits in "this"
-function bnBitLength() {
- if(this.t <= 0) return 0;
- return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
-}
-
-// (protected) r = this << n*DB
-function bnpDLShiftTo(n,r) {
- var i;
- for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
- for(i = n-1; i >= 0; --i) r[i] = 0;
- r.t = this.t+n;
- r.s = this.s;
-}
-
-// (protected) r = this >> n*DB
-function bnpDRShiftTo(n,r) {
- for(var i = n; i < this.t; ++i) r[i-n] = this[i];
- r.t = Math.max(this.t-n,0);
- r.s = this.s;
-}
-
-// (protected) r = this << n
-function bnpLShiftTo(n,r) {
- var bs = n%this.DB;
- var cbs = this.DB-bs;
- var bm = (1<= 0; --i) {
- r[i+ds+1] = (this[i]>>cbs)|c;
- c = (this[i]&bm)<= 0; --i) r[i] = 0;
- r[ds] = c;
- r.t = this.t+ds+1;
- r.s = this.s;
- r.clamp();
-}
-
-// (protected) r = this >> n
-function bnpRShiftTo(n,r) {
- r.s = this.s;
- var ds = Math.floor(n/this.DB);
- if(ds >= this.t) { r.t = 0; return; }
- var bs = n%this.DB;
- var cbs = this.DB-bs;
- var bm = (1<>bs;
- for(var i = ds+1; i < this.t; ++i) {
- r[i-ds-1] |= (this[i]&bm)<>bs;
- }
- if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<>= this.DB;
- }
- if(a.t < this.t) {
- c -= a.s;
- while(i < this.t) {
- c += this[i];
- r[i++] = c&this.DM;
- c >>= this.DB;
- }
- c += this.s;
- }
- else {
- c += this.s;
- while(i < a.t) {
- c -= a[i];
- r[i++] = c&this.DM;
- c >>= this.DB;
- }
- c -= a.s;
- }
- r.s = (c<0)?-1:0;
- if(c < -1) r[i++] = this.DV+c;
- else if(c > 0) r[i++] = c;
- r.t = i;
- r.clamp();
-}
-
-// (protected) r = this * a, r != this,a (HAC 14.12)
-// "this" should be the larger one if appropriate.
-function bnpMultiplyTo(a,r) {
- var x = this.abs(), y = a.abs();
- var i = x.t;
- r.t = i+y.t;
- while(--i >= 0) r[i] = 0;
- for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
- r.s = 0;
- r.clamp();
- if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
-}
-
-// (protected) r = this^2, r != this (HAC 14.16)
-function bnpSquareTo(r) {
- var x = this.abs();
- var i = r.t = 2*x.t;
- while(--i >= 0) r[i] = 0;
- for(i = 0; i < x.t-1; ++i) {
- var c = x.am(i,x[i],r,2*i,0,1);
- if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
- r[i+x.t] -= x.DV;
- r[i+x.t+1] = 1;
- }
- }
- if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
- r.s = 0;
- r.clamp();
-}
-
-// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
-// r != q, this != m. q or r may be null.
-function bnpDivRemTo(m,q,r) {
- var pm = m.abs();
- if(pm.t <= 0) return;
- var pt = this.abs();
- if(pt.t < pm.t) {
- if(q != null) q.fromInt(0);
- if(r != null) this.copyTo(r);
- return;
- }
- if(r == null) r = nbi();
- var y = nbi(), ts = this.s, ms = m.s;
- var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
- if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
- else { pm.copyTo(y); pt.copyTo(r); }
- var ys = y.t;
- var y0 = y[ys-1];
- if(y0 == 0) return;
- var yt = y0*(1<1)?y[ys-2]>>this.F2:0);
- var d1 = this.FV/yt, d2 = (1<= 0) {
- r[r.t++] = 1;
- r.subTo(t,r);
- }
- BigInteger.ONE.dlShiftTo(ys,t);
- t.subTo(y,y); // "negative" y so we can replace sub with am later
- while(y.t < ys) y[y.t++] = 0;
- while(--j >= 0) {
- // Estimate quotient digit
- var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
- if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
- y.dlShiftTo(j,t);
- r.subTo(t,r);
- while(r[i] < --qd) r.subTo(t,r);
- }
- }
- if(q != null) {
- r.drShiftTo(ys,q);
- if(ts != ms) BigInteger.ZERO.subTo(q,q);
- }
- r.t = ys;
- r.clamp();
- if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
- if(ts < 0) BigInteger.ZERO.subTo(r,r);
-}
-
-// (public) this mod a
-function bnMod(a) {
- var r = nbi();
- this.abs().divRemTo(a,null,r);
- if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
- return r;
-}
-
-// Modular reduction using "classic" algorithm
-function Classic(m) { this.m = m; }
-function cConvert(x) {
- if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
- else return x;
-}
-function cRevert(x) { return x; }
-function cReduce(x) { x.divRemTo(this.m,null,x); }
-function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
-function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
-
-Classic.prototype.convert = cConvert;
-Classic.prototype.revert = cRevert;
-Classic.prototype.reduce = cReduce;
-Classic.prototype.mulTo = cMulTo;
-Classic.prototype.sqrTo = cSqrTo;
-
-// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
-// justification:
-// xy == 1 (mod m)
-// xy = 1+km
-// xy(2-xy) = (1+km)(1-km)
-// x[y(2-xy)] = 1-k^2m^2
-// x[y(2-xy)] == 1 (mod m^2)
-// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
-// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
-// JS multiply "overflows" differently from C/C++, so care is needed here.
-function bnpInvDigit() {
- if(this.t < 1) return 0;
- var x = this[0];
- if((x&1) == 0) return 0;
- var y = x&3; // y == 1/x mod 2^2
- y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
- y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
- y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
- // last step - calculate inverse mod DV directly;
- // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
- y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
- // we really want the negative inverse, and -DV < y < DV
- return (y>0)?this.DV-y:-y;
-}
-
-// Montgomery reduction
-function Montgomery(m) {
- this.m = m;
- this.mp = m.invDigit();
- this.mpl = this.mp&0x7fff;
- this.mph = this.mp>>15;
- this.um = (1<<(m.DB-15))-1;
- this.mt2 = 2*m.t;
-}
-
-// xR mod m
-function montConvert(x) {
- var r = nbi();
- x.abs().dlShiftTo(this.m.t,r);
- r.divRemTo(this.m,null,r);
- if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
- return r;
-}
-
-// x/R mod m
-function montRevert(x) {
- var r = nbi();
- x.copyTo(r);
- this.reduce(r);
- return r;
-}
-
-// x = x/R mod m (HAC 14.32)
-function montReduce(x) {
- while(x.t <= this.mt2) // pad x so am has enough room later
- x[x.t++] = 0;
- for(var i = 0; i < this.m.t; ++i) {
- // faster way of calculating u0 = x[i]*mp mod DV
- var j = x[i]&0x7fff;
- var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
- // use am to combine the multiply-shift-add into one call
- j = i+this.m.t;
- x[j] += this.m.am(0,u0,x,i,0,this.m.t);
- // propagate carry
- while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
- }
- x.clamp();
- x.drShiftTo(this.m.t,x);
- if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
-}
-
-// r = "x^2/R mod m"; x != r
-function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
-
-// r = "xy/R mod m"; x,y != r
-function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
-
-Montgomery.prototype.convert = montConvert;
-Montgomery.prototype.revert = montRevert;
-Montgomery.prototype.reduce = montReduce;
-Montgomery.prototype.mulTo = montMulTo;
-Montgomery.prototype.sqrTo = montSqrTo;
-
-// (protected) true iff this is even
-function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
-
-// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
-function bnpExp(e,z) {
- if(e > 0xffffffff || e < 1) return BigInteger.ONE;
- var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
- g.copyTo(r);
- while(--i >= 0) {
- z.sqrTo(r,r2);
- if((e&(1< 0) z.mulTo(r2,g,r);
- else { var t = r; r = r2; r2 = t; }
- }
- return z.revert(r);
-}
-
-// (public) this^e % m, 0 <= e < 2^32
-function bnModPowInt(e,m) {
- var z;
- if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
- return this.exp(e,z);
-}
-
-// protected
-BigInteger.prototype.copyTo = bnpCopyTo;
-BigInteger.prototype.fromInt = bnpFromInt;
-BigInteger.prototype.fromString = bnpFromString;
-BigInteger.prototype.clamp = bnpClamp;
-BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
-BigInteger.prototype.drShiftTo = bnpDRShiftTo;
-BigInteger.prototype.lShiftTo = bnpLShiftTo;
-BigInteger.prototype.rShiftTo = bnpRShiftTo;
-BigInteger.prototype.subTo = bnpSubTo;
-BigInteger.prototype.multiplyTo = bnpMultiplyTo;
-BigInteger.prototype.squareTo = bnpSquareTo;
-BigInteger.prototype.divRemTo = bnpDivRemTo;
-BigInteger.prototype.invDigit = bnpInvDigit;
-BigInteger.prototype.isEven = bnpIsEven;
-BigInteger.prototype.exp = bnpExp;
-
-// public
-BigInteger.prototype.toString = bnToString;
-BigInteger.prototype.negate = bnNegate;
-BigInteger.prototype.abs = bnAbs;
-BigInteger.prototype.compareTo = bnCompareTo;
-BigInteger.prototype.bitLength = bnBitLength;
-BigInteger.prototype.mod = bnMod;
-BigInteger.prototype.modPowInt = bnModPowInt;
-
-// "constants"
-BigInteger.ZERO = nbv(0);
-BigInteger.ONE = nbv(1);
-// Copyright (c) 2005-2009 Tom Wu
-// All Rights Reserved.
-// See "LICENSE" for details.
-
-// Extended JavaScript BN functions, required for RSA private ops.
-
-// Version 1.1: new BigInteger("0", 10) returns "proper" zero
-// Version 1.2: square() API, isProbablePrime fix
-
-// (public)
-function bnClone() { var r = nbi(); this.copyTo(r); return r; }
-
-// (public) return value as integer
-function bnIntValue() {
- if(this.s < 0) {
- if(this.t == 1) return this[0]-this.DV;
- else if(this.t == 0) return -1;
- }
- else if(this.t == 1) return this[0];
- else if(this.t == 0) return 0;
- // assumes 16 < DB < 32
- return ((this[1]&((1<<(32-this.DB))-1))<>24; }
-
-// (public) return value as short (assumes DB>=16)
-function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
-
-// (protected) return x s.t. r^x < DV
-function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
-
-// (public) 0 if this == 0, 1 if this > 0
-function bnSigNum() {
- if(this.s < 0) return -1;
- else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
- else return 1;
-}
-
-// (protected) convert to radix string
-function bnpToRadix(b) {
- if(b == null) b = 10;
- if(this.signum() == 0 || b < 2 || b > 36) return "0";
- var cs = this.chunkSize(b);
- var a = Math.pow(b,cs);
- var d = nbv(a), y = nbi(), z = nbi(), r = "";
- this.divRemTo(d,y,z);
- while(y.signum() > 0) {
- r = (a+z.intValue()).toString(b).substr(1) + r;
- y.divRemTo(d,y,z);
- }
- return z.intValue().toString(b) + r;
-}
-
-// (protected) convert from radix string
-function bnpFromRadix(s,b) {
- this.fromInt(0);
- if(b == null) b = 10;
- var cs = this.chunkSize(b);
- var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
- for(var i = 0; i < s.length; ++i) {
- var x = intAt(s,i);
- if(x < 0) {
- if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
- continue;
- }
- w = b*w+x;
- if(++j >= cs) {
- this.dMultiply(d);
- this.dAddOffset(w,0);
- j = 0;
- w = 0;
- }
- }
- if(j > 0) {
- this.dMultiply(Math.pow(b,j));
- this.dAddOffset(w,0);
- }
- if(mi) BigInteger.ZERO.subTo(this,this);
-}
-
-// (protected) alternate constructor
-function bnpFromNumber(a,b,c) {
- if("number" == typeof b) {
- // new BigInteger(int,int,RNG)
- if(a < 2) this.fromInt(1);
- else {
- this.fromNumber(a,c);
- if(!this.testBit(a-1)) // force MSB set
- this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
- if(this.isEven()) this.dAddOffset(1,0); // force odd
- while(!this.isProbablePrime(b)) {
- this.dAddOffset(2,0);
- if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
- }
- }
- }
- else {
- // new BigInteger(int,RNG)
- var x = new Array(), t = a&7;
- x.length = (a>>3)+1;
- b.nextBytes(x);
- if(t > 0) x[0] &= ((1< 0) {
- if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
- r[k++] = d|(this.s<<(this.DB-p));
- while(i >= 0) {
- if(p < 8) {
- d = (this[i]&((1<>(p+=this.DB-8);
- }
- else {
- d = (this[i]>>(p-=8))&0xff;
- if(p <= 0) { p += this.DB; --i; }
- }
- if((d&0x80) != 0) d |= -256;
- if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
- if(k > 0 || d != this.s) r[k++] = d;
- }
- }
- return r;
-}
-
-function bnEquals(a) { return(this.compareTo(a)==0); }
-function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
-function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
-
-// (protected) r = this op a (bitwise)
-function bnpBitwiseTo(a,op,r) {
- var i, f, m = Math.min(a.t,this.t);
- for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
- if(a.t < this.t) {
- f = a.s&this.DM;
- for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
- r.t = this.t;
- }
- else {
- f = this.s&this.DM;
- for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
- r.t = a.t;
- }
- r.s = op(this.s,a.s);
- r.clamp();
-}
-
-// (public) this & a
-function op_and(x,y) { return x&y; }
-function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
-
-// (public) this | a
-function op_or(x,y) { return x|y; }
-function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
-
-// (public) this ^ a
-function op_xor(x,y) { return x^y; }
-function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
-
-// (public) this & ~a
-function op_andnot(x,y) { return x&~y; }
-function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
-
-// (public) ~this
-function bnNot() {
- var r = nbi();
- for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
- r.t = this.t;
- r.s = ~this.s;
- return r;
-}
-
-// (public) this << n
-function bnShiftLeft(n) {
- var r = nbi();
- if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
- return r;
-}
-
-// (public) this >> n
-function bnShiftRight(n) {
- var r = nbi();
- if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
- return r;
-}
-
-// return index of lowest 1-bit in x, x < 2^31
-function lbit(x) {
- if(x == 0) return -1;
- var r = 0;
- if((x&0xffff) == 0) { x >>= 16; r += 16; }
- if((x&0xff) == 0) { x >>= 8; r += 8; }
- if((x&0xf) == 0) { x >>= 4; r += 4; }
- if((x&3) == 0) { x >>= 2; r += 2; }
- if((x&1) == 0) ++r;
- return r;
-}
-
-// (public) returns index of lowest 1-bit (or -1 if none)
-function bnGetLowestSetBit() {
- for(var i = 0; i < this.t; ++i)
- if(this[i] != 0) return i*this.DB+lbit(this[i]);
- if(this.s < 0) return this.t*this.DB;
- return -1;
-}
-
-// return number of 1 bits in x
-function cbit(x) {
- var r = 0;
- while(x != 0) { x &= x-1; ++r; }
- return r;
-}
-
-// (public) return number of set bits
-function bnBitCount() {
- var r = 0, x = this.s&this.DM;
- for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
- return r;
-}
-
-// (public) true iff nth bit is set
-function bnTestBit(n) {
- var j = Math.floor(n/this.DB);
- if(j >= this.t) return(this.s!=0);
- return((this[j]&(1<<(n%this.DB)))!=0);
-}
-
-// (protected) this op (1<>= this.DB;
- }
- if(a.t < this.t) {
- c += a.s;
- while(i < this.t) {
- c += this[i];
- r[i++] = c&this.DM;
- c >>= this.DB;
- }
- c += this.s;
- }
- else {
- c += this.s;
- while(i < a.t) {
- c += a[i];
- r[i++] = c&this.DM;
- c >>= this.DB;
- }
- c += a.s;
- }
- r.s = (c<0)?-1:0;
- if(c > 0) r[i++] = c;
- else if(c < -1) r[i++] = this.DV+c;
- r.t = i;
- r.clamp();
-}
-
-// (public) this + a
-function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
-
-// (public) this - a
-function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
-
-// (public) this * a
-function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
-
-// (public) this^2
-function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
-
-// (public) this / a
-function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
-
-// (public) this % a
-function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
-
-// (public) [this/a,this%a]
-function bnDivideAndRemainder(a) {
- var q = nbi(), r = nbi();
- this.divRemTo(a,q,r);
- return new Array(q,r);
-}
-
-// (protected) this *= n, this >= 0, 1 < n < DV
-function bnpDMultiply(n) {
- this[this.t] = this.am(0,n-1,this,0,0,this.t);
- ++this.t;
- this.clamp();
-}
-
-// (protected) this += n << w words, this >= 0
-function bnpDAddOffset(n,w) {
- if(n == 0) return;
- while(this.t <= w) this[this.t++] = 0;
- this[w] += n;
- while(this[w] >= this.DV) {
- this[w] -= this.DV;
- if(++w >= this.t) this[this.t++] = 0;
- ++this[w];
- }
-}
-
-// A "null" reducer
-function NullExp() {}
-function nNop(x) { return x; }
-function nMulTo(x,y,r) { x.multiplyTo(y,r); }
-function nSqrTo(x,r) { x.squareTo(r); }
-
-NullExp.prototype.convert = nNop;
-NullExp.prototype.revert = nNop;
-NullExp.prototype.mulTo = nMulTo;
-NullExp.prototype.sqrTo = nSqrTo;
-
-// (public) this^e
-function bnPow(e) { return this.exp(e,new NullExp()); }
-
-// (protected) r = lower n words of "this * a", a.t <= n
-// "this" should be the larger one if appropriate.
-function bnpMultiplyLowerTo(a,n,r) {
- var i = Math.min(this.t+a.t,n);
- r.s = 0; // assumes a,this >= 0
- r.t = i;
- while(i > 0) r[--i] = 0;
- var j;
- for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
- for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
- r.clamp();
-}
-
-// (protected) r = "this * a" without lower n words, n > 0
-// "this" should be the larger one if appropriate.
-function bnpMultiplyUpperTo(a,n,r) {
- --n;
- var i = r.t = this.t+a.t-n;
- r.s = 0; // assumes a,this >= 0
- while(--i >= 0) r[i] = 0;
- for(i = Math.max(n-this.t,0); i < a.t; ++i)
- r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
- r.clamp();
- r.drShiftTo(1,r);
-}
-
-// Barrett modular reduction
-function Barrett(m) {
- // setup Barrett
- this.r2 = nbi();
- this.q3 = nbi();
- BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
- this.mu = this.r2.divide(m);
- this.m = m;
-}
-
-function barrettConvert(x) {
- if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
- else if(x.compareTo(this.m) < 0) return x;
- else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
-}
-
-function barrettRevert(x) { return x; }
-
-// x = x mod m (HAC 14.42)
-function barrettReduce(x) {
- x.drShiftTo(this.m.t-1,this.r2);
- if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
- this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
- this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
- while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
- x.subTo(this.r2,x);
- while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
-}
-
-// r = x^2 mod m; x != r
-function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
-
-// r = x*y mod m; x,y != r
-function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
-
-Barrett.prototype.convert = barrettConvert;
-Barrett.prototype.revert = barrettRevert;
-Barrett.prototype.reduce = barrettReduce;
-Barrett.prototype.mulTo = barrettMulTo;
-Barrett.prototype.sqrTo = barrettSqrTo;
-
-// (public) this^e % m (HAC 14.85)
-function bnModPow(e,m) {
- var i = e.bitLength(), k, r = nbv(1), z;
- if(i <= 0) return r;
- else if(i < 18) k = 1;
- else if(i < 48) k = 3;
- else if(i < 144) k = 4;
- else if(i < 768) k = 5;
- else k = 6;
- if(i < 8)
- z = new Classic(m);
- else if(m.isEven())
- z = new Barrett(m);
- else
- z = new Montgomery(m);
-
- // precomputation
- var g = new Array(), n = 3, k1 = k-1, km = (1< 1) {
- var g2 = nbi();
- z.sqrTo(g[1],g2);
- while(n <= km) {
- g[n] = nbi();
- z.mulTo(g2,g[n-2],g[n]);
- n += 2;
- }
- }
-
- var j = e.t-1, w, is1 = true, r2 = nbi(), t;
- i = nbits(e[j])-1;
- while(j >= 0) {
- if(i >= k1) w = (e[j]>>(i-k1))&km;
- else {
- w = (e[j]&((1<<(i+1))-1))<<(k1-i);
- if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
- }
-
- n = k;
- while((w&1) == 0) { w >>= 1; --n; }
- if((i -= n) < 0) { i += this.DB; --j; }
- if(is1) { // ret == 1, don't bother squaring or multiplying it
- g[w].copyTo(r);
- is1 = false;
- }
- else {
- while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
- if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
- z.mulTo(r2,g[w],r);
- }
-
- while(j >= 0 && (e[j]&(1< 0) {
- x.rShiftTo(g,x);
- y.rShiftTo(g,y);
- }
- while(x.signum() > 0) {
- if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
- if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
- if(x.compareTo(y) >= 0) {
- x.subTo(y,x);
- x.rShiftTo(1,x);
- }
- else {
- y.subTo(x,y);
- y.rShiftTo(1,y);
- }
- }
- if(g > 0) y.lShiftTo(g,y);
- return y;
-}
-
-// (protected) this % n, n < 2^26
-function bnpModInt(n) {
- if(n <= 0) return 0;
- var d = this.DV%n, r = (this.s<0)?n-1:0;
- if(this.t > 0)
- if(d == 0) r = this[0]%n;
- else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
- return r;
-}
-
-// (public) 1/this % m (HAC 14.61)
-function bnModInverse(m) {
- var ac = m.isEven();
- if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
- var u = m.clone(), v = this.clone();
- var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
- while(u.signum() != 0) {
- while(u.isEven()) {
- u.rShiftTo(1,u);
- if(ac) {
- if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
- a.rShiftTo(1,a);
- }
- else if(!b.isEven()) b.subTo(m,b);
- b.rShiftTo(1,b);
- }
- while(v.isEven()) {
- v.rShiftTo(1,v);
- if(ac) {
- if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
- c.rShiftTo(1,c);
- }
- else if(!d.isEven()) d.subTo(m,d);
- d.rShiftTo(1,d);
- }
- if(u.compareTo(v) >= 0) {
- u.subTo(v,u);
- if(ac) a.subTo(c,a);
- b.subTo(d,b);
- }
- else {
- v.subTo(u,v);
- if(ac) c.subTo(a,c);
- d.subTo(b,d);
- }
- }
- if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
- if(d.compareTo(m) >= 0) return d.subtract(m);
- if(d.signum() < 0) d.addTo(m,d); else return d;
- if(d.signum() < 0) return d.add(m); else return d;
-}
-
-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,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
-var lplim = (1<<26)/lowprimes[lowprimes.length-1];
-
-// (public) test primality with certainty >= 1-.5^t
-function bnIsProbablePrime(t) {
- var i, x = this.abs();
- if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
- for(i = 0; i < lowprimes.length; ++i)
- if(x[0] == lowprimes[i]) return true;
- return false;
- }
- if(x.isEven()) return false;
- i = 1;
- while(i < lowprimes.length) {
- var m = lowprimes[i], j = i+1;
- while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
- m = x.modInt(m);
- while(i < j) if(m%lowprimes[i++] == 0) return false;
- }
- return x.millerRabin(t);
-}
-
-// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
-function bnpMillerRabin(t) {
- var n1 = this.subtract(BigInteger.ONE);
- var k = n1.getLowestSetBit();
- if(k <= 0) return false;
- var r = n1.shiftRight(k);
- t = (t+1)>>1;
- if(t > lowprimes.length) t = lowprimes.length;
- var a = nbi();
- for(var i = 0; i < t; ++i) {
- //Pick bases at random, instead of starting at 2
- a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
- var y = a.modPow(r,this);
- if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
- var j = 1;
- while(j++ < k && y.compareTo(n1) != 0) {
- y = y.modPowInt(2,this);
- if(y.compareTo(BigInteger.ONE) == 0) return false;
- }
- if(y.compareTo(n1) != 0) return false;
- }
- }
- return true;
-}
-
-// protected
-BigInteger.prototype.chunkSize = bnpChunkSize;
-BigInteger.prototype.toRadix = bnpToRadix;
-BigInteger.prototype.fromRadix = bnpFromRadix;
-BigInteger.prototype.fromNumber = bnpFromNumber;
-BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
-BigInteger.prototype.changeBit = bnpChangeBit;
-BigInteger.prototype.addTo = bnpAddTo;
-BigInteger.prototype.dMultiply = bnpDMultiply;
-BigInteger.prototype.dAddOffset = bnpDAddOffset;
-BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
-BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
-BigInteger.prototype.modInt = bnpModInt;
-BigInteger.prototype.millerRabin = bnpMillerRabin;
-
-// public
-BigInteger.prototype.clone = bnClone;
-BigInteger.prototype.intValue = bnIntValue;
-BigInteger.prototype.byteValue = bnByteValue;
-BigInteger.prototype.shortValue = bnShortValue;
-BigInteger.prototype.signum = bnSigNum;
-BigInteger.prototype.toByteArray = bnToByteArray;
-BigInteger.prototype.equals = bnEquals;
-BigInteger.prototype.min = bnMin;
-BigInteger.prototype.max = bnMax;
-BigInteger.prototype.and = bnAnd;
-BigInteger.prototype.or = bnOr;
-BigInteger.prototype.xor = bnXor;
-BigInteger.prototype.andNot = bnAndNot;
-BigInteger.prototype.not = bnNot;
-BigInteger.prototype.shiftLeft = bnShiftLeft;
-BigInteger.prototype.shiftRight = bnShiftRight;
-BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
-BigInteger.prototype.bitCount = bnBitCount;
-BigInteger.prototype.testBit = bnTestBit;
-BigInteger.prototype.setBit = bnSetBit;
-BigInteger.prototype.clearBit = bnClearBit;
-BigInteger.prototype.flipBit = bnFlipBit;
-BigInteger.prototype.add = bnAdd;
-BigInteger.prototype.subtract = bnSubtract;
-BigInteger.prototype.multiply = bnMultiply;
-BigInteger.prototype.divide = bnDivide;
-BigInteger.prototype.remainder = bnRemainder;
-BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
-BigInteger.prototype.modPow = bnModPow;
-BigInteger.prototype.modInverse = bnModInverse;
-BigInteger.prototype.pow = bnPow;
-BigInteger.prototype.gcd = bnGCD;
-BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
-
-// JSBN-specific extension
-BigInteger.prototype.square = bnSquare;
-
-// BigInteger interfaces not implemented in jsbn:
-
-// BigInteger(int signum, byte[] magnitude)
-// double doubleValue()
-// float floatValue()
-// int hashCode()
-// long longValue()
-// static BigInteger valueOf(long val)
-// prng4.js - uses Arcfour as a PRNG
-
-function Arcfour() {
- this.i = 0;
- this.j = 0;
- this.S = new Array();
-}
-
-// Initialize arcfour context from key, an array of ints, each from [0..255]
-function ARC4init(key) {
- var i, j, t;
- for(i = 0; i < 256; ++i)
- this.S[i] = i;
- j = 0;
- for(i = 0; i < 256; ++i) {
- j = (j + this.S[i] + key[i % key.length]) & 255;
- t = this.S[i];
- this.S[i] = this.S[j];
- this.S[j] = t;
- }
- this.i = 0;
- this.j = 0;
-}
-
-function ARC4next() {
- var t;
- this.i = (this.i + 1) & 255;
- this.j = (this.j + this.S[this.i]) & 255;
- t = this.S[this.i];
- this.S[this.i] = this.S[this.j];
- this.S[this.j] = t;
- return this.S[(t + this.S[this.i]) & 255];
-}
-
-Arcfour.prototype.init = ARC4init;
-Arcfour.prototype.next = ARC4next;
-
-// Plug in your RNG constructor here
-function prng_newstate() {
- return new Arcfour();
-}
-
-// Pool size must be a multiple of 4 and greater than 32.
-// An array of bytes the size of the pool will be passed to init()
-var rng_psize = 256;
-// BigInteger monkey patching
-BigInteger.valueOf = nbv;
-
-/**
- * Returns a byte array representation of the big integer.
- *
- * This returns the absolute of the contained value in big endian
- * form. A value of zero results in an empty array.
- */
-BigInteger.prototype.toByteArrayUnsigned = function () {
- var ba = this.abs().toByteArray();
- if (ba.length) {
- if (ba[0] == 0) {
- ba = ba.slice(1);
- }
- return ba.map(function (v) {
- return (v < 0) ? v + 256 : v;
- });
- } else {
- // Empty array, nothing to do
- return ba;
- }
-};
-
-/**
- * Turns a byte array into a big integer.
- *
- * This function will interpret a byte array as a big integer in big
- * endian notation and ignore leading zeros.
- */
-BigInteger.fromByteArrayUnsigned = function (ba) {
- if (!ba.length) {
- return ba.valueOf(0);
- } else if (ba[0] & 0x80) {
- // Prepend a zero so the BigInteger class doesn't mistake this
- // for a negative integer.
- return new BigInteger([0].concat(ba));
- } else {
- return new BigInteger(ba);
- }
-};
-
-/**
- * Converts big integer to signed byte representation.
- *
- * The format for this value uses a the most significant bit as a sign
- * bit. If the most significant bit is already occupied by the
- * absolute value, an extra byte is prepended and the sign bit is set
- * there.
- *
- * Examples:
- *
- * 0 => 0x00
- * 1 => 0x01
- * -1 => 0x81
- * 127 => 0x7f
- * -127 => 0xff
- * 128 => 0x0080
- * -128 => 0x8080
- * 255 => 0x00ff
- * -255 => 0x80ff
- * 16300 => 0x3fac
- * -16300 => 0xbfac
- * 62300 => 0x00f35c
- * -62300 => 0x80f35c
- */
-BigInteger.prototype.toByteArraySigned = function () {
- var val = this.abs().toByteArrayUnsigned();
- var neg = this.compareTo(BigInteger.ZERO) < 0;
-
- if (neg) {
- if (val[0] & 0x80) {
- val.unshift(0x80);
- } else {
- val[0] |= 0x80;
- }
- } else {
- if (val[0] & 0x80) {
- val.unshift(0x00);
- }
- }
-
- return val;
-};
-
-/**
- * Parse a signed big integer byte representation.
- *
- * For details on the format please see BigInteger.toByteArraySigned.
- */
-BigInteger.fromByteArraySigned = function (ba) {
- // Check for negative value
- if (ba[0] & 0x80) {
- // Remove sign bit
- ba[0] &= 0x7f;
-
- return BigInteger.fromByteArrayUnsigned(ba).negate();
- } else {
- return BigInteger.fromByteArrayUnsigned(ba);
- }
-};
-
-// Console ignore
-var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
- "dirxml", "group", "groupEnd", "time", "timeEnd", "count",
- "trace", "profile", "profileEnd"];
-
-if ("undefined" == typeof window.console) window.console = {};
-for (var i = 0; i < names.length; ++i)
- if ("undefined" == typeof window.console[names[i]])
- window.console[names[i]] = function() {};
-
-// Bitcoin utility functions
-Bitcoin.Util = {
- /**
- * Cross-browser compatibility version of Array.isArray.
- */
- isArray: Array.isArray || function(o)
- {
- return Object.prototype.toString.call(o) === '[object Array]';
- },
-
- /**
- * Create an array of a certain length filled with a specific value.
- */
- makeFilledArray: function (len, val)
- {
- var array = [];
- var i = 0;
- while (i < len) {
- array[i++] = val;
- }
- return array;
- },
-
- /**
- * Turn an integer into a "var_int".
- *
- * "var_int" is a variable length integer used by Bitcoin's binary format.
- *
- * Returns a byte array.
- */
- numToVarInt: function (i)
- {
- if (i < 0xfd) {
- // unsigned char
- return [i];
- } else if (i <= 1<<16) {
- // unsigned short (LE)
- return [0xfd, i >>> 8, i & 255];
- } else if (i <= 1<<32) {
- // unsigned int (LE)
- return [0xfe].concat(Crypto.util.wordsToBytes([i]));
- } else {
- // unsigned long long (LE)
- return [0xff].concat(Crypto.util.wordsToBytes([i >>> 32, i]));
- }
- },
-
- /**
- * Parse a Bitcoin value byte array, returning a BigInteger.
- */
- valueToBigInt: function (valueBuffer)
- {
- if (valueBuffer instanceof BigInteger) return valueBuffer;
-
- // Prepend zero byte to prevent interpretation as negative integer
- return BigInteger.fromByteArrayUnsigned(valueBuffer);
- },
-
- /**
- * Format a Bitcoin value as a string.
- *
- * Takes a BigInteger or byte-array and returns that amount of Bitcoins in a
- * nice standard formatting.
- *
- * Examples:
- * 12.3555
- * 0.1234
- * 900.99998888
- * 34.00
- */
- formatValue: function (valueBuffer) {
- var value = this.valueToBigInt(valueBuffer).toString();
- var integerPart = value.length > 8 ? value.substr(0, value.length-8) : '0';
- var decimalPart = value.length > 8 ? value.substr(value.length-8) : value;
- while (decimalPart.length < 8) decimalPart = "0"+decimalPart;
- decimalPart = decimalPart.replace(/0*$/, '');
- while (decimalPart.length < 2) decimalPart += "0";
- return integerPart+"."+decimalPart;
- },
-
- /**
- * Parse a floating point string as a Bitcoin value.
- *
- * Keep in mind that parsing user input is messy. You should always display
- * the parsed value back to the user to make sure we understood his input
- * correctly.
- */
- parseValue: function (valueString) {
- // TODO: Detect other number formats (e.g. comma as decimal separator)
- var valueComp = valueString.split('.');
- var integralPart = valueComp[0];
- var fractionalPart = valueComp[1] || "0";
- while (fractionalPart.length < 8) fractionalPart += "0";
- fractionalPart = fractionalPart.replace(/^0+/g, '');
- var value = BigInteger.valueOf(parseInt(integralPart));
- value = value.multiply(BigInteger.valueOf(100000000));
- value = value.add(BigInteger.valueOf(parseInt(fractionalPart)));
- return value;
- },
-
- /**
- * Calculate RIPEMD160(SHA256(data)).
- *
- * Takes an arbitrary byte array as inputs and returns the hash as a byte
- * array.
- */
- sha256ripe160: function (data) {
- return Crypto.RIPEMD160(Crypto.SHA256(data, {asBytes: true}), {asBytes: true});
- }
-};
-
-for (var i in Crypto.util) {
- if (Crypto.util.hasOwnProperty(i)) {
- Bitcoin.Util[i] = Crypto.util[i];
- }
-}
-// Random number generator - requires a PRNG backend, e.g. prng4.js
-
-// For best results, put code like
-//
-// in your main HTML document.
-
-var rng_state;
-var rng_pool;
-var rng_pptr;
-
-// Mix in a 32-bit integer into the pool
-function rng_seed_int(x) {
- rng_pool[rng_pptr++] ^= x & 255;
- rng_pool[rng_pptr++] ^= (x >> 8) & 255;
- rng_pool[rng_pptr++] ^= (x >> 16) & 255;
- rng_pool[rng_pptr++] ^= (x >> 24) & 255;
- if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
-}
-
-// Mix in the current time (w/milliseconds) into the pool
-function rng_seed_time() {
- rng_seed_int(new Date().getTime());
-}
-
-// Initialize the pool with junk if needed.
-if(rng_pool == null) {
- rng_pool = new Array();
- rng_pptr = 0;
- var t;
- if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
- // Extract entropy (256 bits) from NS4 RNG if available
- var z = window.crypto.random(32);
- for(t = 0; t < z.length; ++t)
- rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
- }
- while(rng_pptr < rng_psize) { // extract some randomness from Math.random()
- t = Math.floor(65536 * Math.random());
- rng_pool[rng_pptr++] = t >>> 8;
- rng_pool[rng_pptr++] = t & 255;
- }
- rng_pptr = 0;
- rng_seed_time();
- //rng_seed_int(window.screenX);
- //rng_seed_int(window.screenY);
-}
-
-function rng_get_byte() {
- if(rng_state == null) {
- rng_seed_time();
- rng_state = prng_newstate();
- rng_state.init(rng_pool);
- for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
- rng_pool[rng_pptr] = 0;
- rng_pptr = 0;
- //rng_pool = null;
- }
- // TODO: allow reseeding after first request
- return rng_state.next();
-}
-
-function rng_get_bytes(ba) {
- var i;
- for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
-}
-
-function SecureRandom() {}
-
-SecureRandom.prototype.nextBytes = rng_get_bytes;
-// Basic Javascript Elliptic Curve implementation
-// Ported loosely from BouncyCastle's Java EC code
-// Only Fp curves implemented for now
-
-// Requires jsbn.js and jsbn2.js
-
-// ----------------
-// ECFieldElementFp
-
-// constructor
-function ECFieldElementFp(q,x) {
- this.x = x;
- // TODO if(x.compareTo(q) >= 0) error
- this.q = q;
-}
-
-function feFpEquals(other) {
- if(other == this) return true;
- return (this.q.equals(other.q) && this.x.equals(other.x));
-}
-
-function feFpToBigInteger() {
- return this.x;
-}
-
-function feFpNegate() {
- return new ECFieldElementFp(this.q, this.x.negate().mod(this.q));
-}
-
-function feFpAdd(b) {
- return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q));
-}
-
-function feFpSubtract(b) {
- return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q));
-}
-
-function feFpMultiply(b) {
- return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q));
-}
-
-function feFpSquare() {
- return new ECFieldElementFp(this.q, this.x.square().mod(this.q));
-}
-
-function feFpDivide(b) {
- return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q));
-}
-
-ECFieldElementFp.prototype.equals = feFpEquals;
-ECFieldElementFp.prototype.toBigInteger = feFpToBigInteger;
-ECFieldElementFp.prototype.negate = feFpNegate;
-ECFieldElementFp.prototype.add = feFpAdd;
-ECFieldElementFp.prototype.subtract = feFpSubtract;
-ECFieldElementFp.prototype.multiply = feFpMultiply;
-ECFieldElementFp.prototype.square = feFpSquare;
-ECFieldElementFp.prototype.divide = feFpDivide;
-
-// ----------------
-// ECPointFp
-
-// constructor
-function ECPointFp(curve,x,y,z) {
- this.curve = curve;
- this.x = x;
- this.y = y;
- // Projective coordinates: either zinv == null or z * zinv == 1
- // z and zinv are just BigIntegers, not fieldElements
- if(z == null) {
- this.z = BigInteger.ONE;
- }
- else {
- this.z = z;
- }
- this.zinv = null;
- //TODO: compression flag
-}
-
-function pointFpGetX() {
- if(this.zinv == null) {
- this.zinv = this.z.modInverse(this.curve.q);
- }
- return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q));
-}
-
-function pointFpGetY() {
- if(this.zinv == null) {
- this.zinv = this.z.modInverse(this.curve.q);
- }
- return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q));
-}
-
-function pointFpEquals(other) {
- if(other == this) return true;
- if(this.isInfinity()) return other.isInfinity();
- if(other.isInfinity()) return this.isInfinity();
- var u, v;
- // u = Y2 * Z1 - Y1 * Z2
- u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q);
- if(!u.equals(BigInteger.ZERO)) return false;
- // v = X2 * Z1 - X1 * Z2
- v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q);
- return v.equals(BigInteger.ZERO);
-}
-
-function pointFpIsInfinity() {
- if((this.x == null) && (this.y == null)) return true;
- return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO);
-}
-
-function pointFpNegate() {
- return new ECPointFp(this.curve, this.x, this.y.negate(), this.z);
-}
-
-function pointFpAdd(b) {
- if(this.isInfinity()) return b;
- if(b.isInfinity()) return this;
-
- // u = Y2 * Z1 - Y1 * Z2
- var u = b.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(b.z)).mod(this.curve.q);
- // v = X2 * Z1 - X1 * Z2
- var v = b.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(b.z)).mod(this.curve.q);
-
- if(BigInteger.ZERO.equals(v)) {
- if(BigInteger.ZERO.equals(u)) {
- return this.twice(); // this == b, so double
- }
- return this.curve.getInfinity(); // this = -b, so infinity
- }
-
- var THREE = new BigInteger("3");
- var x1 = this.x.toBigInteger();
- var y1 = this.y.toBigInteger();
- var x2 = b.x.toBigInteger();
- var y2 = b.y.toBigInteger();
-
- var v2 = v.square();
- var v3 = v2.multiply(v);
- var x1v2 = x1.multiply(v2);
- var zu2 = u.square().multiply(this.z);
-
- // x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3)
- var x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).subtract(v3).multiply(v).mod(this.curve.q);
- // y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3
- var y3 = x1v2.multiply(THREE).multiply(u).subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).multiply(b.z).add(u.multiply(v3)).mod(this.curve.q);
- // z3 = v^3 * z1 * z2
- var z3 = v3.multiply(this.z).multiply(b.z).mod(this.curve.q);
-
- return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
-}
-
-function pointFpTwice() {
- if(this.isInfinity()) return this;
- if(this.y.toBigInteger().signum() == 0) return this.curve.getInfinity();
-
- // TODO: optimized handling of constants
- var THREE = new BigInteger("3");
- var x1 = this.x.toBigInteger();
- var y1 = this.y.toBigInteger();
-
- var y1z1 = y1.multiply(this.z);
- var y1sqz1 = y1z1.multiply(y1).mod(this.curve.q);
- var a = this.curve.a.toBigInteger();
-
- // w = 3 * x1^2 + a * z1^2
- var w = x1.square().multiply(THREE);
- if(!BigInteger.ZERO.equals(a)) {
- w = w.add(this.z.square().multiply(a));
- }
- w = w.mod(this.curve.q);
- // x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1)
- var x3 = w.square().subtract(x1.shiftLeft(3).multiply(y1sqz1)).shiftLeft(1).multiply(y1z1).mod(this.curve.q);
- // y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3
- var y3 = w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1)).shiftLeft(2).multiply(y1sqz1).subtract(w.square().multiply(w)).mod(this.curve.q);
- // z3 = 8 * (y1 * z1)^3
- var z3 = y1z1.square().multiply(y1z1).shiftLeft(3).mod(this.curve.q);
-
- return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
-}
-
-// Simple NAF (Non-Adjacent Form) multiplication algorithm
-// TODO: modularize the multiplication algorithm
-function pointFpMultiply(k) {
- if(this.isInfinity()) return this;
- if(k.signum() == 0) return this.curve.getInfinity();
-
- var e = k;
- var h = e.multiply(new BigInteger("3"));
-
- var neg = this.negate();
- var R = this;
-
- var i;
- for(i = h.bitLength() - 2; i > 0; --i) {
- R = R.twice();
-
- var hBit = h.testBit(i);
- var eBit = e.testBit(i);
-
- if (hBit != eBit) {
- R = R.add(hBit ? this : neg);
- }
- }
-
- return R;
-}
-
-// Compute this*j + x*k (simultaneous multiplication)
-function pointFpMultiplyTwo(j,x,k) {
- var i;
- if(j.bitLength() > k.bitLength())
- i = j.bitLength() - 1;
- else
- i = k.bitLength() - 1;
-
- var R = this.curve.getInfinity();
- var both = this.add(x);
- while(i >= 0) {
- R = R.twice();
- if(j.testBit(i)) {
- if(k.testBit(i)) {
- R = R.add(both);
- }
- else {
- R = R.add(this);
- }
- }
- else {
- if(k.testBit(i)) {
- R = R.add(x);
- }
- }
- --i;
- }
-
- return R;
-}
-
-ECPointFp.prototype.getX = pointFpGetX;
-ECPointFp.prototype.getY = pointFpGetY;
-ECPointFp.prototype.equals = pointFpEquals;
-ECPointFp.prototype.isInfinity = pointFpIsInfinity;
-ECPointFp.prototype.negate = pointFpNegate;
-ECPointFp.prototype.add = pointFpAdd;
-ECPointFp.prototype.twice = pointFpTwice;
-ECPointFp.prototype.multiply = pointFpMultiply;
-ECPointFp.prototype.multiplyTwo = pointFpMultiplyTwo;
-
-// ----------------
-// ECCurveFp
-
-// constructor
-function ECCurveFp(q,a,b) {
- this.q = q;
- this.a = this.fromBigInteger(a);
- this.b = this.fromBigInteger(b);
- this.infinity = new ECPointFp(this, null, null);
-}
-
-function curveFpGetQ() {
- return this.q;
-}
-
-function curveFpGetA() {
- return this.a;
-}
-
-function curveFpGetB() {
- return this.b;
-}
-
-function curveFpEquals(other) {
- if(other == this) return true;
- return(this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b));
-}
-
-function curveFpGetInfinity() {
- return this.infinity;
-}
-
-function curveFpFromBigInteger(x) {
- return new ECFieldElementFp(this.q, x);
-}
-
-// for now, work with hex strings because they're easier in JS
-function curveFpDecodePointHex(s) {
- switch(parseInt(s.substr(0,2), 16)) { // first byte
- case 0:
- return this.infinity;
- case 2:
- case 3:
- // point compression not supported yet
- return null;
- case 4:
- case 6:
- case 7:
- var len = (s.length - 2) / 2;
- var xHex = s.substr(2, len);
- var yHex = s.substr(len+2, len);
-
- return new ECPointFp(this,
- this.fromBigInteger(new BigInteger(xHex, 16)),
- this.fromBigInteger(new BigInteger(yHex, 16)));
-
- default: // unsupported
- return null;
- }
-}
-
-ECCurveFp.prototype.getQ = curveFpGetQ;
-ECCurveFp.prototype.getA = curveFpGetA;
-ECCurveFp.prototype.getB = curveFpGetB;
-ECCurveFp.prototype.equals = curveFpEquals;
-ECCurveFp.prototype.getInfinity = curveFpGetInfinity;
-ECCurveFp.prototype.fromBigInteger = curveFpFromBigInteger;
-ECCurveFp.prototype.decodePointHex = curveFpDecodePointHex;
-// Named EC curves
-
-// Requires ec.js, jsbn.js, and jsbn2.js
-
-// ----------------
-// X9ECParameters
-
-// constructor
-function X9ECParameters(curve,g,n,h) {
- this.curve = curve;
- this.g = g;
- this.n = n;
- this.h = h;
-}
-
-function x9getCurve() {
- return this.curve;
-}
-
-function x9getG() {
- return this.g;
-}
-
-function x9getN() {
- return this.n;
-}
-
-function x9getH() {
- return this.h;
-}
-
-X9ECParameters.prototype.getCurve = x9getCurve;
-X9ECParameters.prototype.getG = x9getG;
-X9ECParameters.prototype.getN = x9getN;
-X9ECParameters.prototype.getH = x9getH;
-
-// ----------------
-// SECNamedCurves
-
-function fromHex(s) { return new BigInteger(s, 16); }
-
-function secp128r1() {
- // p = 2^128 - 2^97 - 1
- var p = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
- var a = fromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC");
- var b = fromHex("E87579C11079F43DD824993C2CEE5ED3");
- //byte[] S = Hex.decode("000E0D4D696E6768756151750CC03A4473D03679");
- var n = fromHex("FFFFFFFE0000000075A30D1B9038A115");
- var h = BigInteger.ONE;
- var curve = new ECCurveFp(p, a, b);
- var G = curve.decodePointHex("04"
- + "161FF7528B899B2D0C28607CA52C5B86"
- + "CF5AC8395BAFEB13C02DA292DDED7A83");
- return new X9ECParameters(curve, G, n, h);
-}
-
-function secp160k1() {
- // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
- var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73");
- var a = BigInteger.ZERO;
- var b = fromHex("7");
- //byte[] S = null;
- var n = fromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3");
- var h = BigInteger.ONE;
- var curve = new ECCurveFp(p, a, b);
- var G = curve.decodePointHex("04"
- + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
- + "938CF935318FDCED6BC28286531733C3F03C4FEE");
- return new X9ECParameters(curve, G, n, h);
-}
-
-function secp160r1() {
- // p = 2^160 - 2^31 - 1
- var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF");
- var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC");
- var b = fromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45");
- //byte[] S = Hex.decode("1053CDE42C14D696E67687561517533BF3F83345");
- var n = fromHex("0100000000000000000001F4C8F927AED3CA752257");
- var h = BigInteger.ONE;
- var curve = new ECCurveFp(p, a, b);
- var G = curve.decodePointHex("04"
- + "4A96B5688EF573284664698968C38BB913CBFC82"
- + "23A628553168947D59DCC912042351377AC5FB32");
- return new X9ECParameters(curve, G, n, h);
-}
-
-function secp192k1() {
- // p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
- var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37");
- var a = BigInteger.ZERO;
- var b = fromHex("3");
- //byte[] S = null;
- var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D");
- var h = BigInteger.ONE;
- var curve = new ECCurveFp(p, a, b);
- var G = curve.decodePointHex("04"
- + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
- + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D");
- return new X9ECParameters(curve, G, n, h);
-}
-
-function secp192r1() {
- // p = 2^192 - 2^64 - 1
- var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF");
- var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC");
- var b = fromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1");
- //byte[] S = Hex.decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
- var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831");
- var h = BigInteger.ONE;
- var curve = new ECCurveFp(p, a, b);
- var G = curve.decodePointHex("04"
- + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
- + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811");
- return new X9ECParameters(curve, G, n, h);
-}
-
-function secp224r1() {
- // p = 2^224 - 2^96 + 1
- var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001");
- var a = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE");
- var b = fromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4");
- //byte[] S = Hex.decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
- var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D");
- var h = BigInteger.ONE;
- var curve = new ECCurveFp(p, a, b);
- var G = curve.decodePointHex("04"
- + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
- + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34");
- return new X9ECParameters(curve, G, n, h);
-}
-
-function secp256k1() {
- // p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
- var p = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
- var a = BigInteger.ZERO;
- var b = fromHex("7");
- //byte[] S = null;
- var n = fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
- var h = BigInteger.ONE;
- var curve = new ECCurveFp(p, a, b);
- var G = curve.decodePointHex("04"
- + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
- + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");
- return new X9ECParameters(curve, G, n, h);
-}
-
-function secp256r1() {
- // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1
- var p = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF");
- var a = fromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC");
- var b = fromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B");
- //byte[] S = Hex.decode("C49D360886E704936A6678E1139D26B7819F7E90");
- var n = fromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
- var h = BigInteger.ONE;
- var curve = new ECCurveFp(p, a, b);
- var G = curve.decodePointHex("04"
- + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
- + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5");
- return new X9ECParameters(curve, G, n, h);
-}
-
-// TODO: make this into a proper hashtable
-function getSECCurveByName(name) {
- if(name == "secp128r1") return secp128r1();
- if(name == "secp160k1") return secp160k1();
- if(name == "secp160r1") return secp160r1();
- if(name == "secp192k1") return secp192k1();
- if(name == "secp192r1") return secp192r1();
- if(name == "secp224r1") return secp224r1();
- if(name == "secp256k1") return secp256k1();
- if(name == "secp256r1") return secp256r1();
- return null;
-}
-function integerToBytes(i, len) {
- var bytes = i.toByteArrayUnsigned();
-
- if (len < bytes.length) {
- bytes = bytes.slice(bytes.length-len);
- } else while (len > bytes.length) {
- bytes.unshift(0);
- }
-
- return bytes;
-};
-
-ECFieldElementFp.prototype.getByteLength = function () {
- return Math.floor((this.toBigInteger().bitLength() + 7) / 8);
-};
-
-ECPointFp.prototype.getEncoded = function (compressed) {
- var x = this.getX().toBigInteger();
- var y = this.getY().toBigInteger();
-
- // Get value as a 32-byte Buffer
- // Fixed length based on a patch by bitaddress.org and Casascius
- var enc = integerToBytes(x, 32);
-
- if (compressed) {
- if (y.isEven()) {
- // Compressed even pubkey
- // M = 02 || X
- enc.unshift(0x02);
- } else {
- // Compressed uneven pubkey
- // M = 03 || X
- enc.unshift(0x03);
- }
- } else {
- // Uncompressed pubkey
- // M = 04 || X || Y
- enc.unshift(0x04);
- enc = enc.concat(integerToBytes(y, 32));
- }
- return enc;
-};
-
-ECPointFp.decodeFrom = function (ecparams, enc) {
- var type = enc[0];
- var dataLen = enc.length-1;
-
- // Extract x and y as byte arrays
- if (type == 4) {
- var xBa = enc.slice(1, 1 + dataLen/2),
- yBa = enc.slice(1 + dataLen/2, 1 + dataLen),
- x = BigInteger.fromByteArrayUnsigned(xBa),
- y = BigInteger.fromByteArrayUnsigned(yBa);
- }
- else {
- var xBa = enc.slice(1),
- x = BigInteger.fromByteArrayUnsigned(xBa),
- p = ecparams.getQ(),
- xCubedPlus7 = x.multiply(x).multiply(x).add(new BigInteger('7')).mod(p),
- pPlus1Over4 = p.add(new BigInteger('1'))
- .divide(new BigInteger('4')),
- y = xCubedPlus7.modPow(pPlus1Over4,p);
- if (y.mod(new BigInteger('2')).toString() != ''+(type % 2)) {
- y = p.subtract(y)
- }
- }
-
- // Return point
- return new ECPointFp(ecparams,
- ecparams.fromBigInteger(x),
- ecparams.fromBigInteger(y));
-};
-
-
-ECPointFp.prototype.add2D = function (b) {
- if(this.isInfinity()) return b;
- if(b.isInfinity()) return this;
-
- if (this.x.equals(b.x)) {
- if (this.y.equals(b.y)) {
- // this = b, i.e. this must be doubled
- return this.twice();
- }
- // this = -b, i.e. the result is the point at infinity
- return this.curve.getInfinity();
- }
-
- var x_x = b.x.subtract(this.x);
- var y_y = b.y.subtract(this.y);
- var gamma = y_y.divide(x_x);
-
- var x3 = gamma.square().subtract(this.x).subtract(b.x);
- var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
-
- return new ECPointFp(this.curve, x3, y3);
-};
-
-ECPointFp.prototype.twice2D = function () {
- if (this.isInfinity()) return this;
- if (this.y.toBigInteger().signum() == 0) {
- // if y1 == 0, then (x1, y1) == (x1, -y1)
- // and hence this = -this and thus 2(x1, y1) == infinity
- return this.curve.getInfinity();
- }
-
- var TWO = this.curve.fromBigInteger(BigInteger.valueOf(2));
- var THREE = this.curve.fromBigInteger(BigInteger.valueOf(3));
- var gamma = this.x.square().multiply(THREE).add(this.curve.a).divide(this.y.multiply(TWO));
-
- var x3 = gamma.square().subtract(this.x.multiply(TWO));
- var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
-
- return new ECPointFp(this.curve, x3, y3);
-};
-
-ECPointFp.prototype.multiply2D = function (k) {
- if(this.isInfinity()) return this;
- if(k.signum() == 0) return this.curve.getInfinity();
-
- var e = k;
- var h = e.multiply(new BigInteger("3"));
-
- var neg = this.negate();
- var R = this;
-
- var i;
- for (i = h.bitLength() - 2; i > 0; --i) {
- R = R.twice();
-
- var hBit = h.testBit(i);
- var eBit = e.testBit(i);
-
- if (hBit != eBit) {
- R = R.add2D(hBit ? this : neg);
- }
- }
-
- return R;
-};
-
-ECPointFp.prototype.isOnCurve = function () {
- var x = this.getX().toBigInteger();
- var y = this.getY().toBigInteger();
- var a = this.curve.getA().toBigInteger();
- var b = this.curve.getB().toBigInteger();
- var n = this.curve.getQ();
- var lhs = y.multiply(y).mod(n);
- var rhs = x.multiply(x).multiply(x)
- .add(a.multiply(x)).add(b).mod(n);
- return lhs.equals(rhs);
-};
-
-ECPointFp.prototype.toString = function () {
- return '('+this.getX().toBigInteger().toString()+','+
- this.getY().toBigInteger().toString()+')';
-};
-
-/**
- * Validate an elliptic curve point.
- *
- * See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive
- */
-ECPointFp.prototype.validate = function () {
- var n = this.curve.getQ();
-
- // Check Q != O
- if (this.isInfinity()) {
- throw new Error("Point is at infinity.");
- }
-
- // Check coordinate bounds
- var x = this.getX().toBigInteger();
- var y = this.getY().toBigInteger();
- if (x.compareTo(BigInteger.ONE) < 0 ||
- x.compareTo(n.subtract(BigInteger.ONE)) > 0) {
- throw new Error('x coordinate out of bounds');
- }
- if (y.compareTo(BigInteger.ONE) < 0 ||
- y.compareTo(n.subtract(BigInteger.ONE)) > 0) {
- throw new Error('y coordinate out of bounds');
- }
-
- // Check y^2 = x^3 + ax + b (mod n)
- if (!this.isOnCurve()) {
- throw new Error("Point is not on the curve.");
- }
-
- // Check nQ = 0 (Q is a scalar multiple of G)
- if (this.multiply(n).isInfinity()) {
- // TODO: This check doesn't work - fix.
- throw new Error("Point is not a scalar multiple of G.");
- }
-
- return true;
-};
-
-function dmp(v) {
- if (!(v instanceof BigInteger)) v = v.toBigInteger();
- return Crypto.util.bytesToHex(v.toByteArrayUnsigned());
-};
-
-Bitcoin.ECDSA = (function () {
- var ecparams = getSECCurveByName("secp256k1");
- var rng = new SecureRandom();
-
- var P_OVER_FOUR = null;
-
- function implShamirsTrick(P, k, Q, l)
- {
- var m = Math.max(k.bitLength(), l.bitLength());
- var Z = P.add2D(Q);
- var R = P.curve.getInfinity();
-
- for (var i = m - 1; i >= 0; --i) {
- R = R.twice2D();
-
- R.z = BigInteger.ONE;
-
- if (k.testBit(i)) {
- if (l.testBit(i)) {
- R = R.add2D(Z);
- } else {
- R = R.add2D(P);
- }
- } else {
- if (l.testBit(i)) {
- R = R.add2D(Q);
- }
- }
- }
-
- return R;
- };
-
- var ECDSA = {
- getBigRandom: function (limit) {
- return new BigInteger(limit.bitLength(), rng)
- .mod(limit.subtract(BigInteger.ONE))
- .add(BigInteger.ONE)
- ;
- },
- sign: function (hash, priv) {
- var d = priv;
- var n = ecparams.getN();
- var e = BigInteger.fromByteArrayUnsigned(hash);
-
- do {
- var k = ECDSA.getBigRandom(n);
- var G = ecparams.getG();
- var Q = G.multiply(k);
- var r = Q.getX().toBigInteger().mod(n);
- } while (r.compareTo(BigInteger.ZERO) <= 0);
-
- var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
-
- return ECDSA.serializeSig(r, s);
- },
-
- verify: function (hash, sig, pubkey) {
- var r,s;
- if (Bitcoin.Util.isArray(sig)) {
- var obj = ECDSA.parseSig(sig);
- r = obj.r;
- s = obj.s;
- } else if ("object" === typeof sig && sig.r && sig.s) {
- r = sig.r;
- s = sig.s;
- } else {
- throw "Invalid value for signature";
- }
-
- var Q;
- if (pubkey instanceof ECPointFp) {
- Q = pubkey;
- } else if (Bitcoin.Util.isArray(pubkey)) {
- Q = ECPointFp.decodeFrom(ecparams.getCurve(), pubkey);
- } else {
- throw "Invalid format for pubkey value, must be byte array or ECPointFp";
- }
- var e = BigInteger.fromByteArrayUnsigned(hash);
-
- return ECDSA.verifyRaw(e, r, s, Q);
- },
-
- verifyRaw: function (e, r, s, Q) {
- var n = ecparams.getN();
- var G = ecparams.getG();
-
- if (r.compareTo(BigInteger.ONE) < 0 ||
- r.compareTo(n) >= 0)
- return false;
-
- if (s.compareTo(BigInteger.ONE) < 0 ||
- s.compareTo(n) >= 0)
- return false;
-
- var c = s.modInverse(n);
-
- var u1 = e.multiply(c).mod(n);
- var u2 = r.multiply(c).mod(n);
-
- // TODO(!!!): For some reason Shamir's trick isn't working with
- // signed message verification!? Probably an implementation
- // error!
- //var point = implShamirsTrick(G, u1, Q, u2);
- var point = G.multiply(u1).add(Q.multiply(u2));
-
- var v = point.getX().toBigInteger().mod(n);
-
- return v.equals(r);
- },
-
- /**
- * Serialize a signature into DER format.
- *
- * Takes two BigIntegers representing r and s and returns a byte array.
- */
- serializeSig: function (r, s) {
- var rBa = r.toByteArraySigned();
- var sBa = s.toByteArraySigned();
-
- var sequence = [];
- sequence.push(0x02); // INTEGER
- sequence.push(rBa.length);
- sequence = sequence.concat(rBa);
-
- sequence.push(0x02); // INTEGER
- sequence.push(sBa.length);
- sequence = sequence.concat(sBa);
-
- sequence.unshift(sequence.length);
- sequence.unshift(0x30); // SEQUENCE
-
- return sequence;
- },
-
- /**
- * Parses a byte array containing a DER-encoded signature.
- *
- * This function will return an object of the form:
- *
- * {
- * r: BigInteger,
- * s: BigInteger
- * }
- */
- parseSig: function (sig) {
- var cursor;
- if (sig[0] != 0x30)
- throw new Error("Signature not a valid DERSequence");
-
- cursor = 2;
- if (sig[cursor] != 0x02)
- throw new Error("First element in signature must be a DERInteger");;
- var rBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]);
-
- cursor += 2+sig[cursor+1];
- if (sig[cursor] != 0x02)
- throw new Error("Second element in signature must be a DERInteger");
- var sBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]);
-
- cursor += 2+sig[cursor+1];
-
- //if (cursor != sig.length)
- // throw new Error("Extra bytes in signature");
-
- var r = BigInteger.fromByteArrayUnsigned(rBa);
- var s = BigInteger.fromByteArrayUnsigned(sBa);
-
- return {r: r, s: s};
- },
-
- parseSigCompact: function (sig) {
- if (sig.length !== 65) {
- throw "Signature has the wrong length";
- }
-
- // Signature is prefixed with a type byte storing three bits of
- // information.
- var i = sig[0] - 27;
- if (i < 0 || i > 7) {
- throw "Invalid signature type";
- }
-
- var n = ecparams.getN();
- var r = BigInteger.fromByteArrayUnsigned(sig.slice(1, 33)).mod(n);
- var s = BigInteger.fromByteArrayUnsigned(sig.slice(33, 65)).mod(n);
-
- return {r: r, s: s, i: i};
- },
-
- /**
- * Recover a public key from a signature.
- *
- * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public
- * Key Recovery Operation".
- *
- * http://www.secg.org/download/aid-780/sec1-v2.pdf
- */
- recoverPubKey: function (r, s, hash, i) {
- // The recovery parameter i has two bits.
- i = i & 3;
-
- // The less significant bit specifies whether the y coordinate
- // of the compressed point is even or not.
- var isYEven = i & 1;
-
- // The more significant bit specifies whether we should use the
- // first or second candidate key.
- var isSecondKey = i >> 1;
-
- var n = ecparams.getN();
- var G = ecparams.getG();
- var curve = ecparams.getCurve();
- var p = curve.getQ();
- var a = curve.getA().toBigInteger();
- var b = curve.getB().toBigInteger();
-
- // We precalculate (p + 1) / 4 where p is if the field order
- if (!P_OVER_FOUR) {
- P_OVER_FOUR = p.add(BigInteger.ONE).divide(BigInteger.valueOf(4));
- }
-
- // 1.1 Compute x
- var x = isSecondKey ? r.add(n) : r;
-
- // 1.3 Convert x to point
- var alpha = x.multiply(x).multiply(x).add(a.multiply(x)).add(b).mod(p);
- var beta = alpha.modPow(P_OVER_FOUR, p);
-
- var xorOdd = beta.isEven() ? (i % 2) : ((i+1) % 2);
- // If beta is even, but y isn't or vice versa, then convert it,
- // otherwise we're done and y == beta.
- var y = (beta.isEven() ? !isYEven : isYEven) ? beta : p.subtract(beta);
-
- // 1.4 Check that nR is at infinity
- var R = new ECPointFp(curve,
- curve.fromBigInteger(x),
- curve.fromBigInteger(y));
- R.validate();
-
- // 1.5 Compute e from M
- var e = BigInteger.fromByteArrayUnsigned(hash);
- var eNeg = BigInteger.ZERO.subtract(e).mod(n);
-
- // 1.6 Compute Q = r^-1 (sR - eG)
- var rInv = r.modInverse(n);
- var Q = implShamirsTrick(R, s, G, eNeg).multiply(rInv);
-
- Q.validate();
- if (!ECDSA.verifyRaw(e, r, s, Q)) {
- throw "Pubkey recovery unsuccessful";
- }
-
- var pubKey = new Bitcoin.ECKey();
- pubKey.pub = Q;
- return pubKey;
- },
-
- /**
- * Calculate pubkey extraction parameter.
- *
- * When extracting a pubkey from a signature, we have to
- * distinguish four different cases. Rather than putting this
- * burden on the verifier, Bitcoin includes a 2-bit value with the
- * signature.
- *
- * This function simply tries all four cases and returns the value
- * that resulted in a successful pubkey recovery.
- */
- calcPubkeyRecoveryParam: function (address, r, s, hash)
- {
- for (var i = 0; i < 4; i++) {
- try {
- var pubkey = Bitcoin.ECDSA.recoverPubKey(r, s, hash, i);
- if (pubkey.getBitcoinAddress().toString() == address) {
- return i;
- }
- } catch (e) {}
- }
- throw "Unable to find valid recovery factor";
- }
- };
-
- return ECDSA;
-})();
-Bitcoin.ECKey = (function () {
- var ECDSA = Bitcoin.ECDSA;
- var ecparams = getSECCurveByName("secp256k1");
- var rng = new SecureRandom();
-
- var ECKey = function (input) {
- if (!input) {
- // Generate new key
- var n = ecparams.getN();
- this.priv = ECDSA.getBigRandom(n);
- } else if (input instanceof BigInteger) {
- // Input is a private key value
- this.priv = input;
- } else if (Bitcoin.Util.isArray(input)) {
- // Prepend zero byte to prevent interpretation as negative integer
- this.priv = BigInteger.fromByteArrayUnsigned(input);
- } else if ("string" == typeof input) {
- if (input.length == 51 && input[0] == '5') {
- // Base58 encoded private key
- this.priv = BigInteger.fromByteArrayUnsigned(ECKey.decodeString(input));
- } else {
- // Prepend zero byte to prevent interpretation as negative integer
- this.priv = BigInteger.fromByteArrayUnsigned(Crypto.util.hexToBytes(input));
- }
- }
- this.compressed = !!ECKey.compressByDefault;
- };
-
- /**
- * Whether public keys should be returned compressed by default.
- */
- ECKey.compressByDefault = false;
-
- /**
- * Set whether the public key should be returned compressed or not.
- */
- ECKey.prototype.setCompressed = function (v) {
- this.compressed = !!v;
- };
-
- /**
- * Return public key in DER encoding.
- */
- ECKey.prototype.getPub = function () {
- return this.getPubPoint().getEncoded(this.compressed);
- };
-
- /**
- * Return public point as ECPoint object.
- */
- ECKey.prototype.getPubPoint = function () {
- if (!this.pub) this.pub = ecparams.getG().multiply(this.priv);
-
- return this.pub;
- };
-
- /**
- * Get the pubKeyHash for this key.
- *
- * This is calculated as RIPE160(SHA256([encoded pubkey])) and returned as
- * a byte array.
- */
- ECKey.prototype.getPubKeyHash = function () {
- if (this.pubKeyHash) return this.pubKeyHash;
-
- return this.pubKeyHash = Bitcoin.Util.sha256ripe160(this.getPub());
- };
-
- ECKey.prototype.getBitcoinAddress = function () {
- var hash = this.getPubKeyHash();
- var addr = new Bitcoin.Address(hash);
- return addr;
- };
-
- ECKey.prototype.getExportedPrivateKey = function () {
- var hash = this.priv.toByteArrayUnsigned();
- while (hash.length < 32) hash.unshift(0);
- hash.unshift(0x80);
- var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true});
- var bytes = hash.concat(checksum.slice(0,4));
- return Bitcoin.Base58.encode(bytes);
- };
-
- ECKey.prototype.setPub = function (pub) {
- this.pub = ECPointFp.decodeFrom(ecparams.getCurve(), pub);
- };
-
- ECKey.prototype.toString = function (format) {
- if (format === "base64") {
- return Crypto.util.bytesToBase64(this.priv.toByteArrayUnsigned());
- } else {
- return Crypto.util.bytesToHex(this.priv.toByteArrayUnsigned());
- }
- };
-
- ECKey.prototype.sign = function (hash) {
- return ECDSA.sign(hash, this.priv);
- };
-
- ECKey.prototype.verify = function (hash, sig) {
- return ECDSA.verify(hash, sig, this.getPub());
- };
-
- /**
- * Parse an exported private key contained in a string.
- */
- ECKey.decodeString = function (string) {
- var bytes = Bitcoin.Base58.decode(string);
-
- var hash = bytes.slice(0, 33);
-
- var checksum = Crypto.SHA256(Crypto.SHA256(hash, {asBytes: true}), {asBytes: true});
-
- if (checksum[0] != bytes[33] ||
- checksum[1] != bytes[34] ||
- checksum[2] != bytes[35] ||
- checksum[3] != bytes[36]) {
- throw "Checksum validation failed!";
- }
-
- var version = hash.shift();
-
- if (version != 0x80) {
- throw "Version "+version+" not supported!";
- }
-
- return hash;
- };
-
- return ECKey;
-})();
-
-
-module.exports.ECKey = Bitcoin.ECKey;
diff --git a/browser/browser.js b/browser/browser.js
deleted file mode 100644
index d1db04b..0000000
--- a/browser/browser.js
+++ /dev/null
@@ -1 +0,0 @@
-if ('undefined' === typeof window) window = this;
diff --git a/browser/browserify.js b/browser/browserify.js
index 21fa085..df52135 100644
--- a/browser/browserify.js
+++ b/browser/browserify.js
@@ -10,7 +10,33 @@
var fs = require('fs');
var browserify = require('browserify');
var browserPack = require('browser-pack');
+var program = require('commander');
+// concat browser vendor files
+var exec = require('child_process').exec;
+var sys = require('sys');
+var puts = function(error, stdout, stderr) {
+ if (error) console.log(error);
+ sys.puts(stdout);
+ sys.puts(stderr);
+};
+
+exec('cd browser; sh concat.sh', puts);
+
+var list = function(val) {
+ return val.split(',');
+};
+
+program
+ .version('0.0.1')
+ .option('-a, --includeall', 'Include all submodules.')
+ .option('-s, --submodules ', 'Include the listed comma-separated submodules.', list)
+ .parse(process.argv);
+
+if (!program.includeall && (!program.submodules || program.submodules.length === 0)) {
+ console.log('Must use either -s or -a option. For more info use the --help option');
+ process.exit(1);
+}
var pack = function (params) {
var preludePath = 'node_modules/soop/example/custom_prelude.js';
@@ -64,9 +90,11 @@ b.require('./util/log');
b.require('./util/util');
b.require('./util/EncodedData');
b.require('./util/VersionedData');
-b.add('./browser/bignum_config.js');
modules.forEach(function(m) {
- b.require('./' + m + '.js' ,{expose: './'+m} );
+ if (program.includeall || program.submodules.indexOf(m) > -1) {
+ console.log('Including '+m+' in the browser bundle');
+ b.require('./' + m + '.js' , {expose: './'+m} );
+ }
});
b.require('soop');
diff --git a/browser/concat.sh b/browser/concat.sh
index 21582e1..b8676e9 100755
--- a/browser/concat.sh
+++ b/browser/concat.sh
@@ -1,3 +1,7 @@
#! /bin/bash
-cat browser.js crypto.js ripemd160.js bitcoin.js navigator-adapter.js jsbn.js jsbn2.js prng4.js util.js rng.js ec.js sec.js ecdsa.js eckey.js > bitcoinjs-lib.js
+cd vendor/
+cat browser-adapter.js crypto.js ripemd160.js jsbn.js jsbn2.js prng4.js util.js rng.js ec.js sec.js ecdsa.js eckey.js > vendor-bundle.js
+mv vendor-bundle.js ../
+cd ../
+
diff --git a/browser/navigator-adapter.js b/browser/vendor/browser-adapter.js
similarity index 60%
rename from browser/navigator-adapter.js
rename to browser/vendor/browser-adapter.js
index b1eb29d..7da083e 100644
--- a/browser/navigator-adapter.js
+++ b/browser/vendor/browser-adapter.js
@@ -1,7 +1,6 @@
-
-
+if ('undefined' === typeof window) window = this;
+Bitcoin = {};
if (typeof navigator === 'undefined') {
var navigator = {};
navigator.appName = 'NodeJS';
-
}
diff --git a/browser/crypto.js b/browser/vendor/crypto.js
similarity index 100%
rename from browser/crypto.js
rename to browser/vendor/crypto.js
diff --git a/browser/ec.js b/browser/vendor/ec.js
similarity index 100%
rename from browser/ec.js
rename to browser/vendor/ec.js
diff --git a/browser/ecdsa.js b/browser/vendor/ecdsa.js
similarity index 93%
rename from browser/ecdsa.js
rename to browser/vendor/ecdsa.js
index a2497bf..57e0801 100644
--- a/browser/ecdsa.js
+++ b/browser/vendor/ecdsa.js
@@ -41,24 +41,34 @@ ECPointFp.prototype.getEncoded = function (compressed) {
return enc;
};
-ECPointFp.decodeFrom = function (curve, enc) {
+ECPointFp.decodeFrom = function (ecparams, enc) {
var type = enc[0];
var dataLen = enc.length-1;
// Extract x and y as byte arrays
- var xBa = enc.slice(1, 1 + dataLen/2);
- var yBa = enc.slice(1 + dataLen/2, 1 + dataLen);
-
- // Prepend zero byte to prevent interpretation as negative integer
- xBa.unshift(0);
- yBa.unshift(0);
-
- // Convert to BigIntegers
- var x = new BigInteger(xBa);
- var y = new BigInteger(yBa);
+ if (type === 4) {
+ var xBa = enc.slice(1, 1 + dataLen/2),
+ yBa = enc.slice(1 + dataLen/2, 1 + dataLen),
+ x = BigInteger.fromByteArrayUnsigned(xBa),
+ y = BigInteger.fromByteArrayUnsigned(yBa);
+ }
+ else {
+ var xBa = enc.slice(1),
+ x = BigInteger.fromByteArrayUnsigned(xBa),
+ p = ecparams.getQ(),
+ xCubedPlus7 = x.multiply(x).multiply(x).add(new BigInteger('7')).mod(p),
+ pPlus1Over4 = p.add(new BigInteger('1'))
+ .divide(new BigInteger('4')),
+ y = xCubedPlus7.modPow(pPlus1Over4,p);
+ if (y.mod(new BigInteger('2')).toString() != ''+(type % 2)) {
+ y = p.subtract(y)
+ }
+ }
// Return point
- return new ECPointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y));
+ return new ECPointFp(ecparams,
+ ecparams.fromBigInteger(x),
+ ecparams.fromBigInteger(y));
};
ECPointFp.prototype.add2D = function (b) {
diff --git a/browser/eckey.js b/browser/vendor/eckey.js
similarity index 100%
rename from browser/eckey.js
rename to browser/vendor/eckey.js
diff --git a/browser/jsbn.js b/browser/vendor/jsbn.js
similarity index 100%
rename from browser/jsbn.js
rename to browser/vendor/jsbn.js
diff --git a/browser/jsbn2.js b/browser/vendor/jsbn2.js
similarity index 100%
rename from browser/jsbn2.js
rename to browser/vendor/jsbn2.js
diff --git a/browser/prng4.js b/browser/vendor/prng4.js
similarity index 100%
rename from browser/prng4.js
rename to browser/vendor/prng4.js
diff --git a/browser/ripemd160.js b/browser/vendor/ripemd160.js
similarity index 93%
rename from browser/ripemd160.js
rename to browser/vendor/ripemd160.js
index a230b4b..309d39b 100644
--- a/browser/ripemd160.js
+++ b/browser/vendor/ripemd160.js
@@ -29,5 +29,17 @@ f+(((m|~n)^p)+c[2]):64>b?f+((m&p|n&~p)+c[3]):f+((m^(n|~p))+c[4]),f|=0,f=f<>>5]|=128<<24-a%32;e[(a+64>>>9<<4)+14]=(b<<8|b>>>24)&16711935|(b<<24|b>>>8)&4278255360;g.sigBytes=4*(e.length+1);this._process();g=this._hash;e=g.words;for(b=0;5>b;b++)a=e[b],e[b]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;return g},clone:function(){var e=l.clone.call(this);e._hash=this._hash.clone();return e}});j.RIPEMD160=l._createHelper(k);j.HmacRIPEMD160=l._createHmacHelper(k)})(Math);
-module.exports.RIPEMD160 = CryptoJS.RIPEMD160;
-module.exports.WordArray = CryptoJS.lib.WordArray;
+module.exports.ripemd160 = function(bytes) {
+ if (!Buffer.isBuffer(bytes)) {
+ throw new Error('arg should be a buffer');
+ }
+ var w = new CryptoJS.lib.WordArray.init(Crypto.util.bytesToWords(bytes), bytes.length);
+ var wordArray = CryptoJS.RIPEMD160(w);
+ var words = wordArray.words;
+ var answer = [];
+ for (var b = 0; b < words.length * 32; b += 8) {
+ answer.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
+ }
+ return answer;
+};
+
diff --git a/browser/rng.js b/browser/vendor/rng.js
similarity index 100%
rename from browser/rng.js
rename to browser/vendor/rng.js
diff --git a/browser/sec.js b/browser/vendor/sec.js
similarity index 100%
rename from browser/sec.js
rename to browser/vendor/sec.js
diff --git a/browser/util.js b/browser/vendor/util.js
similarity index 100%
rename from browser/util.js
rename to browser/vendor/util.js
diff --git a/examples/Address.js b/examples/Address.js
index 1cc0573..af41311 100644
--- a/examples/Address.js
+++ b/examples/Address.js
@@ -4,22 +4,16 @@
var Address = require('../Address');
-var addrStrings = [
- "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
- "1A1zP1eP5QGefi2DMPTfTL5SLmv7Dixxxx",
- "A1zP1eP5QGefi2DMPTfTL5SLmv7Dixxxx",
- "1600 Pennsylvania Ave NW",
+var addrs = [
+ '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
+ '1A1zP1eP5QGefi2DMPTfTL5SLmv7Dixxxx',
+ 'A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
+ '1600 Pennsylvania Ave NW',
].map(function(addr) {
return new Address(addr);
});
-addrStrings.forEach(function(addr) {
-
- try {
- addr.validate();
- console.log(addr.data + ": is valid");
- } catch(e) {
- console.log(addr.data + ": is not a valid address. " + e);
- }
-
+addrs.forEach(function(addr) {
+ var valid = addr.isValid();
+ console.log(addr.data + ' is ' + (valid ? '' : 'not ') + 'valid');
});
diff --git a/examples/simple.html b/examples/simple.html
new file mode 100644
index 0000000..740b3e6
--- /dev/null
+++ b/examples/simple.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
diff --git a/index.js b/index.js
deleted file mode 120000
index 955c7ec..0000000
--- a/index.js
+++ /dev/null
@@ -1 +0,0 @@
-bitcore.js
\ No newline at end of file
diff --git a/package.json b/package.json
index 4efa62a..382f3d6 100644
--- a/package.json
+++ b/package.json
@@ -36,12 +36,14 @@
"currency",
"virtual"
],
+ "main": "bitcore.js",
"repository": {
"type": "git",
"url": "https://github.com/bitpay/bitcore.git"
},
"scripts": {
- "test": "mocha test -R spec"
+ "test": "mocha test -R spec",
+ "postinstall": "node ./browser/browserify.js -a"
},
"dependencies": {
"soop": "git://github.com/bitpay/soop.git",
@@ -66,7 +68,8 @@
"browserify-buffertools": "~1.0.2",
"chai": "~1.9.0",
"brfs": "~1.0.0",
- "async": "~0.2.10"
+ "async": "~0.2.10",
+ "commander": "~2.1.0"
},
"license": "MIT"
}
diff --git a/test/index.html b/test/index.html
index a21f79e..bbd0d61 100644
--- a/test/index.html
+++ b/test/index.html
@@ -38,6 +38,8 @@
+
diff --git a/test/test.Address.js b/test/test.Address.js
index 758440e..21d1534 100644
--- a/test/test.Address.js
+++ b/test/test.Address.js
@@ -20,17 +20,31 @@ describe('Address', function() {
var a = new Address('1KfyjCgBSMsLqiCbakfSdeoBUqMqLUiu3T');
should.exist(a);
});
- it('should validate correctly', function() {
- var a = new Address('1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa');
- var m = new Address('32QBdjycLwbDTuGafUwaU5p5GxzSLPYoF6');
- var b = new Address('11111111111111111111111111122222234');
- a.validate.bind(a).should.not.throw(Error);
- m.validate.bind(m).should.not.throw(Error);
- b.validate.bind(b).should.throw(Error);
+ var data = [
+ ['1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', true],
+ ['11111111111111111111111111122222234', false], // totally invalid
+ ['32QBdjycLwbDTuGafUwaU5p5GxzSLPYoF6', true],
+ ['1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9', true],
+ ['1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i', true],
+ ['1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW600', false], // bad checksum
+ ['1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW620', false], // bad checksum
+ ['1ANNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i', false], // data changed, original checksum.
+ ['1A Na15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i', false], // invalid chars
+ ['1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62j', false], // checksums don't match.
+ ['1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62!', false], // bad char (!)
+ ['1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62iz', false], // too long Bitcoin address
+ ['1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62izz', false],// too long Bitcoin address
+ ['2cFupjhnEsSn59qHXstmK2ffpLv2', false], // valid base58 invalid data
+ ];
+ data.forEach(function(datum) {
+ var address = datum[0];
+ var result = datum[1];
+ it('should validate correctly ' + address, function() {
+ var a = new Address(address);
+ var s = a.toString();
+
+ a.isValid().should.equal(result);
+ s.should.equal(a.toString()); // check that validation doesn't change data
+ });
});
});
-
-
-
-
-
diff --git a/util/util.js b/util/util.js
index 7f3dab4..7503367 100644
--- a/util/util.js
+++ b/util/util.js
@@ -4,10 +4,10 @@ var bignum = require('bignum');
var Binary = require('binary');
var Put = require('bufferput');
var buffertools = require('buffertools');
-var bjs;
+var browser;
if (!process.versions) {
// browser version
- bjs = require('../browser/bitcoinjs-lib.js');
+ browser = require('../browser/vendor-bundle.js');
}
@@ -21,7 +21,7 @@ var ripe160 = exports.ripe160 = function (data) {
}
if (!process.versions) {
- var result = bjs.ripemd160(data);
+ var result = browser.ripemd160(data);
return new Buffer(result, 'hex');
}
return new Buffer(crypto.createHash('rmd160').update(data).digest('binary'), 'binary');