diff --git a/core/bn.js b/core/bn.js index 3d5acc5a..52eb23e8 100644 --- a/core/bn.js +++ b/core/bn.js @@ -140,7 +140,7 @@ sjcl.bn.prototype = { l[i] = (tmp+carry)>>1; carry = (tmp&1) << r; } - if (!l[l.length-1]) { + if (!l[l.length-1] && l.length > 1) { l.pop(); } return this; @@ -386,6 +386,7 @@ sjcl.bn.prototype = { var montIn = function(c) { return montMul(c, R2); }, montMul = function(a, b) { // Standard Montgomery reduction + // Assumes a and b are already mod N var k, ab, right, abBar, mask = (1 << (s + 1)) - 1; ab = a.mul(b); @@ -419,7 +420,8 @@ sjcl.bn.prototype = { }, montOut = function(c) { return montMul(c, 1); }; - pow = montIn(pow); + // pow may be larger than N, and montIn/montMul assume their params are already mod N. + pow = montIn(pow.mod(N)); out = montIn(out); // Sliding-Window Exponentiation (HAC 14.85) diff --git a/test/bn_test.js b/test/bn_test.js index 37ec13f5..b03f8ea9 100644 --- a/test/bn_test.js +++ b/test/bn_test.js @@ -95,3 +95,21 @@ new sjcl.test.TestCase("Big Limbs Multiplication test", function (cb) { cb && cb(); }); + + +new sjcl.test.TestCase("Regression: Halving one makes zero", function (cb) { + if (!sjcl.bn) { + this.unimplemented(); + cb && cb(); + return; + } + + var actual = new sjcl.bn(1).halveM(); + this.require(actual.limbs.length === 1, "Expected: " + [0] + " Actual: " + actual.limbs); + this.require(actual.limbs[0] === 0, "Expected: " + [0] + " Actual: " + actual.limbs); + + actual = new sjcl.bn(0).halveM(); + this.require(actual.limbs.length === 1, "Expected: " + [0] + " Actual: " + actual.limbs); + this.require(actual.limbs[0] === 0, "Expected: " + [0] + " Actual: " + actual.limbs); + cb && cb(); +}); diff --git a/test/bn_vectors.js b/test/bn_vectors.js index 6d18d51e..16687dfd 100644 --- a/test/bn_vectors.js +++ b/test/bn_vectors.js @@ -78,5 +78,11 @@ sjcl.test.vector.bn_powermod = [ x: "eeaf0ab9adb3008dd6c314c9c25600057674df692c0006e0d5d8e2050b98be48e4", N: "b48130d6e07674df740e1d33b4816e0d5d8e20e2050b98be48e457674df74096ea", v: "9c3219b694befb9caac51a13eb1ac7053b02c654b6a0541cfa60c483592d478630" + }, + { + g: 2000, + x: 2, + N: 19, + v: 6 } ];