diff --git a/grunt.js b/grunt.js index dab1bcef57..a306fab645 100644 --- a/grunt.js +++ b/grunt.js @@ -36,6 +36,7 @@ module.exports = function(grunt) { "src/js/sjcl-custom/sjcl-secp256k1.js", "src/js/sjcl-custom/sjcl-ripemd160.js", "src/js/sjcl-custom/sjcl-extramath.js", + "src/js/sjcl-custom/sjcl-validecc.js", "src/js/sjcl-custom/sjcl-ecdsa-der.js" ], dest: 'build/sjcl.js' diff --git a/src/js/sjcl-custom/sjcl-validecc.js b/src/js/sjcl-custom/sjcl-validecc.js new file mode 100644 index 0000000000..99ecde393d --- /dev/null +++ b/src/js/sjcl-custom/sjcl-validecc.js @@ -0,0 +1,30 @@ +sjcl.ecc.ecdsa.secretKey.prototype = { + sign: function(hash, paranoia) { + var R = this._curve.r, + l = R.bitLength(), + k = sjcl.bn.random(R.sub(1), paranoia).add(1), + r = this._curve.G.mult(k).x.mod(R), + s = sjcl.bn.fromBits(hash).add(r.mul(this._exponent)).mul(k.inverseMod(R)).mod(R); + + return sjcl.bitArray.concat(r.toBits(l), s.toBits(l)); + } +}; + +sjcl.ecc.ecdsa.publicKey.prototype = { + verify: function(hash, rs) { + var w = sjcl.bitArray, + R = this._curve.r, + l = R.bitLength(), + r = sjcl.bn.fromBits(w.bitSlice(rs,0,l)), + s = sjcl.bn.fromBits(w.bitSlice(rs,l,2*l)), + sInv = s.modInverse(R), + hG = sjcl.bn.fromBits(hash).mul(sInv).mod(R), + hA = r.mul(sInv).mod(R), + r2 = this._curve.G.mult2(hG, hA, this._point).x; + + if (r.equals(0) || s.equals(0) || r.greaterEquals(R) || s.greaterEquals(R) || !r2.equals(r)) { + throw (new sjcl.exception.corrupt("signature didn't check out")); + } + return true; + } +};