Move custom SJCL extensions from client over to Ripple library.

This commit is contained in:
Stefan Thomas
2013-02-01 01:41:36 +01:00
parent 44a2327fbe
commit 37cc88ccf2
5 changed files with 347 additions and 1 deletions

3
src/js/README.md Normal file
View File

@@ -0,0 +1,3 @@
# Ripple JavaScript library
This library lets you connect to a ripple server via websockets.

View File

@@ -0,0 +1,61 @@
sjcl.bn.ZERO = new sjcl.bn(0);
/** [ this / that , this % that ] */
sjcl.bn.prototype.divRem = function (that) {
if (typeof(that) !== "object") { that = new this._class(that); }
var thisa = this.abs(), thata = that.abs(), quot = new this._class(0),
ci = 0;
if (!thisa.greaterEquals(thata)) {
this.initWith(0);
return this;
} else if (thisa.equals(thata)) {
this.initWith(sign);
return this;
}
for (; thisa.greaterEquals(thata); ci++) {
thata.doubleM();
}
for (; ci > 0; ci--) {
quot.doubleM();
thata.halveM();
if (thisa.greaterEquals(thata)) {
quot.addM(1);
thisa.subM(that).normalize();
}
}
return [quot, thisa];
};
/** this /= that (rounded to nearest int) */
sjcl.bn.prototype.divRound = function (that) {
var dr = this.divRem(that), quot = dr[0], rem = dr[1];
if (rem.doubleM().greaterEquals(that)) {
quot.addM(1);
}
return quot;
};
/** this /= that (rounded down) */
sjcl.bn.prototype.div = function (that) {
var dr = this.divRem(that);
return dr[0];
};
sjcl.bn.prototype.sign = function () {
return this.greaterEquals(sjcl.bn.ZERO) ? 1 : -1;
};
/** -this */
sjcl.bn.prototype.neg = function () {
return sjcl.bn.ZERO.sub(this);
};
/** |this| */
sjcl.bn.prototype.abs = function () {
if (this.sign() === -1) {
return this.neg();
} else return this;
};

View File

@@ -0,0 +1,207 @@
/** @fileOverview Javascript RIPEMD-160 implementation.
*
* @author Artem S Vybornov <vybornov@gmail.com>
*/
(function() {
/**
* Context for a RIPEMD-160 operation in progress.
* @constructor
* @class RIPEMD, 160 bits.
*/
sjcl.hash.ripemd160 = function (hash) {
if (hash) {
this._h = hash._h.slice(0);
this._buffer = hash._buffer.slice(0);
this._length = hash._length;
} else {
this.reset();
}
};
/**
* Hash a string or an array of words.
* @static
* @param {bitArray|String} data the data to hash.
* @return {bitArray} The hash value, an array of 5 big-endian words.
*/
sjcl.hash.ripemd160.hash = function (data) {
return (new sjcl.hash.ripemd160()).update(data).finalize();
};
sjcl.hash.ripemd160.prototype = {
/**
* Reset the hash state.
* @return this
*/
reset: function () {
this._h = _h0.slice(0);
this._buffer = [];
this._length = 0;
return this;
},
/**
* Reset the hash state.
* @param {bitArray|String} data the data to hash.
* @return this
*/
update: function (data) {
if ( typeof data === "string" )
data = sjcl.codec.utf8String.toBits(data);
var i, b = this._buffer = sjcl.bitArray.concat(this._buffer, data),
ol = this._length,
nl = this._length = ol + sjcl.bitArray.bitLength(data);
for (i = 512+ol & -512; i <= nl; i+= 512) {
var words = b.splice(0,16);
for ( var w = 0; w < 16; ++w )
words[w] = _cvt(words[w]);
_block.call( this, words );
}
return this;
},
/**
* Complete hashing and output the hash value.
* @return {bitArray} The hash value, an array of 5 big-endian words.
*/
finalize: function () {
var b = sjcl.bitArray.concat( this._buffer, [ sjcl.bitArray.partial(1,1) ] ),
l = ( this._length + 1 ) % 512,
z = ( l > 448 ? 512 : 448 ) - l % 448,
zp = z % 32;
if ( zp > 0 )
b = sjcl.bitArray.concat( b, [ sjcl.bitArray.partial(zp,0) ] )
for ( ; z >= 32; z -= 32 )
b.push(0);
b.push( _cvt( this._length | 0 ) );
b.push( _cvt( Math.floor(this._length / 0x100000000) ) );
while ( b.length ) {
var words = b.splice(0,16);
for ( var w = 0; w < 16; ++w )
words[w] = _cvt(words[w]);
_block.call( this, words );
}
var h = this._h;
this.reset();
for ( var w = 0; w < 5; ++w )
h[w] = _cvt(h[w]);
return h;
}
};
var _h0 = [ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 ];
var _k1 = [ 0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e ];
var _k2 = [ 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000 ];
for ( var i = 4; i >= 0; --i ) {
for ( var j = 1; j < 16; ++j ) {
_k1.splice(i,0,_k1[i]);
_k2.splice(i,0,_k2[i]);
}
}
var _r1 = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 ];
var _r2 = [ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 ];
var _s1 = [ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 ];
var _s2 = [ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 ];
function _f0(x,y,z) {
return x ^ y ^ z;
};
function _f1(x,y,z) {
return (x & y) | (~x & z);
};
function _f2(x,y,z) {
return (x | ~y) ^ z;
};
function _f3(x,y,z) {
return (x & z) | (y & ~z);
};
function _f4(x,y,z) {
return x ^ (y | ~z);
};
function _rol(n,l) {
return (n << l) | (n >>> (32-l));
}
function _cvt(n) {
return ( (n & 0xff << 0) << 24 )
| ( (n & 0xff << 8) << 8 )
| ( (n & 0xff << 16) >>> 8 )
| ( (n & 0xff << 24) >>> 24 );
}
function _block(X) {
var A1 = this._h[0], B1 = this._h[1], C1 = this._h[2], D1 = this._h[3], E1 = this._h[4],
A2 = this._h[0], B2 = this._h[1], C2 = this._h[2], D2 = this._h[3], E2 = this._h[4];
var j = 0, T;
for ( ; j < 16; ++j ) {
T = _rol( A1 + _f0(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1;
A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T;
T = _rol( A2 + _f4(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2;
A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; }
for ( ; j < 32; ++j ) {
T = _rol( A1 + _f1(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1;
A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T;
T = _rol( A2 + _f3(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2;
A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; }
for ( ; j < 48; ++j ) {
T = _rol( A1 + _f2(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1;
A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T;
T = _rol( A2 + _f2(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2;
A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; }
for ( ; j < 64; ++j ) {
T = _rol( A1 + _f3(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1;
A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T;
T = _rol( A2 + _f1(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2;
A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; }
for ( ; j < 80; ++j ) {
T = _rol( A1 + _f4(B1,C1,D1) + X[_r1[j]] + _k1[j], _s1[j] ) + E1;
A1 = E1; E1 = D1; D1 = _rol(C1,10); C1 = B1; B1 = T;
T = _rol( A2 + _f0(B2,C2,D2) + X[_r2[j]] + _k2[j], _s2[j] ) + E2;
A2 = E2; E2 = D2; D2 = _rol(C2,10); C2 = B2; B2 = T; }
T = this._h[1] + C1 + D2;
this._h[1] = this._h[2] + D1 + E2;
this._h[2] = this._h[3] + E1 + A2;
this._h[3] = this._h[4] + A1 + B2;
this._h[4] = this._h[0] + B1 + C2;
this._h[0] = T;
}
})();

View File

@@ -0,0 +1,72 @@
// ----- for secp256k1 ------
// Overwrite NIST-P256 with secp256k1 so we're on even footing
sjcl.ecc.curves.c256 = new sjcl.ecc.curve(
sjcl.bn.pseudoMersennePrime(256, [[0,-1],[4,-1],[6,-1],[7,-1],[8,-1],[9,-1],[32,-1]]),
"0x14551231950b75fc4402da1722fc9baee",
0,
7,
"0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"
);
// Replace point addition and doubling algorithms
// NIST-P256 is a=-3, we need algorithms for a=0
sjcl.ecc.pointJac.prototype.add = function(T) {
var S = this;
if (S.curve !== T.curve) {
throw("sjcl.ecc.add(): Points must be on the same curve to add them!");
}
if (S.isIdentity) {
return T.toJac();
} else if (T.isIdentity) {
return S;
}
var z1z1 = S.z.square();
var h = T.x.mul(z1z1).subM(S.x);
var s2 = T.y.mul(S.z).mul(z1z1);
if (h.equals(0)) {
if (S.y.equals(T.y.mul(z1z1.mul(S.z)))) {
// same point
return S.doubl();
} else {
// inverses
return new sjcl.ecc.pointJac(S.curve);
}
}
var hh = h.square();
var i = hh.copy().doubleM().doubleM();
var j = h.mul(i);
var r = s2.sub(S.y).doubleM();
var v = S.x.mul(i);
var x = r.square().subM(j).subM(v.copy().doubleM());
var y = r.mul(v.sub(x)).subM(S.y.mul(j).doubleM());
var z = S.z.add(h).square().subM(z1z1).subM(hh);
return new sjcl.ecc.pointJac(this.curve,x,y,z);
};
sjcl.ecc.pointJac.prototype.doubl = function () {
if (this.isIdentity) { return this; }
var a = this.x.square();
var b = this.y.square();
var c = b.square();
var d = this.x.add(b).square().subM(a).subM(c).doubleM();
var e = a.mul(3);
var f = e.square();
var x = f.sub(d.copy().doubleM());
var y = e.mul(d.sub(x)).subM(c.doubleM().doubleM().doubleM());
var z = this.y.mul(this.z).doubleM();
return new sjcl.ecc.pointJac(this.curve, x, y, z);
};
sjcl.ecc.point.prototype.toBytesCompressed = function () {
var header = this.y.mod(2).toString() == "0x0" ? 0x02 : 0x03;
return [header].concat(sjcl.codec.bytes.fromBits(this.x.toBits()))
};