/** * Constructs a new bignum from another bignum, a number or a hex string. */ function bn(it) { this.initWith(it); } bn.prototype = { radix: 24, maxMul: 8, _class: bn, copy: function() { return new this._class(this); }, /** * Initializes this with it, either as a bn, a number, or a hex string. */ initWith: function(it) { var i=0, k, n, l; switch(typeof it) { case "object": this.limbs = it.limbs.slice(0); break; case "number": this.limbs = [it]; this.normalize(); break; case "string": it = it.replace(/^0x/, ''); this.limbs = []; // hack k = this.radix / 4; for (i=0; i < it.length; i+=k) { this.limbs.push(parseInt(it.substring(Math.max(it.length - i - k, 0), it.length - i),16)); } break; default: this.limbs = [0]; } return this; }, /** * Returns true if "this" and "that" are equal. Calls fullReduce(). * Equality test is in constant time. */ equals: function(that) { if (typeof that == "number") { that = new this._class(that); } var difference = 0, i; this.fullReduce(); that.fullReduce(); for (i = 0; i < this.limbs.length || i < that.limbs.length; i++) { difference |= this.getLimb(i) ^ that.getLimb(i); } return (difference === 0); }, /** * Get the i'th limb of this, zero if i is too large. */ getLimb: function(i) { return (i >= this.limbs.length) ? 0 : this.limbs[i]; }, /** * Constant time comparison function. * Returns 1 if this >= that, or zero otherwise. */ greaterEquals: function(that) { if (typeof that == "number") { that = new this._class(that); } var less = 0, greater = 0, i, a, b; i = Math.max(this.limbs.length, that.limbs.length) - 1; for (; i>= 0; i--) { a = this.getLimb(i); b = that.getLimb(i); greater |= (b - a) & ~less; less |= (a - b) & ~greater } return (greater | ~less) >>> 31; }, /** * Convert to a hex string. */ toString: function() { this.fullReduce(); var out="", i, s, l = this.limbs; for (i=0; i < this.limbs.length; i++) { s = l[i].toString(16); while (i < this.limbs.length - 1 && s.length < 6) { s = "0" + s; } out = s + out; } return "0x"+out; }, /** this += that. Does not normalize. */ addM: function(that) { if (typeof(that) !== "object") { that = new this._class(that); } var i; for (i=this.limbs.length; i mo) { l = limbs.pop(); ll = limbs.length; for (k=0; k= 0; i--) { out = w.concat(out, [w.partial(this.radix, this.getLimb(i))]); } return out; }; p.fromBits = function(bits) { var out = new this(), words=[], w=sjcl.bitArray, t = this.prototype, l = Math.min(w.bitLength(bits), t.exponent + 7 & -8), e = l % t.radix || t.radix; words[0] = w.extract(bits, 0, e); for (; e < l; e += t.radix) { words.unshift(w.extract(bits, e, t.radix)); } out.limbs = words; return out; }; return p; } // a small Mersenne prime p127 = pseudoMersennePrime(127, [[0,-1]]); // Bernstein's prime for Curve25519 p25519 = pseudoMersennePrime(255, [[0,-19]]); // NIST primes p192 = pseudoMersennePrime(192, [[0,-1],[64,-1]]); p224 = pseudoMersennePrime(224, [[0,1],[96,-1]]); p256 = pseudoMersennePrime(256, [[0,-1],[96,1],[192,1],[224,-1]]); p384 = pseudoMersennePrime(384, [[0,-1],[32,1],[96,-1],[128,-1]]); p521 = pseudoMersennePrime(521, [[0,-1]]); bn.random = function(modulus, paranoia) { if (typeof modulus != "object") { modulus = new bn(modulus); } var words, i, l = modulus.limbs.length, m = modulus.limbs[l-1]+1, out = new bn(); while (true) { // get a sequence whose first digits make sense do { words = sjcl.random.randomWords(l, paranoia); if (words[l-1] < 0) { words[l-1] += 0x100000000; } } while (Math.floor(words[l-1] / m) == Math.floor(0x100000000 / m)); words[l-1] %= m; // mask off all the limbs for (i=0; i