red-test.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. var assert = require('assert');
  2. var BN = require('../').BN;
  3. var fixtures = require('./fixtures');
  4. describe('BN.js/Reduction context', function() {
  5. function testMethod(name, fn) {
  6. describe(name + ' method', function() {
  7. it('should support add, iadd, sub, isub operations', function() {
  8. var p = new BN(257);
  9. var m = fn(p);
  10. var a = new BN(123).toRed(m);
  11. var b = new BN(231).toRed(m);
  12. assert.equal(a.redAdd(b).fromRed().toString(10), '97');
  13. assert.equal(a.redSub(b).fromRed().toString(10), '149');
  14. assert.equal(b.redSub(a).fromRed().toString(10), '108');
  15. assert.equal(a.clone().redIAdd(b).fromRed().toString(10), '97');
  16. assert.equal(a.clone().redISub(b).fromRed().toString(10), '149');
  17. assert.equal(b.clone().redISub(a).fromRed().toString(10), '108');
  18. });
  19. it('should support pow and mul operations', function() {
  20. var p192 = new BN(
  21. 'fffffffffffffffffffffffffffffffeffffffffffffffff',
  22. 16);
  23. var m = fn(p192);
  24. var a = new BN(123);
  25. var b = new BN(231);
  26. var c = a.toRed(m).redMul(b.toRed(m)).fromRed();
  27. assert(c.cmp(a.mul(b).mod(p192)) === 0);
  28. assert.equal(a.toRed(m).redPow(new BN(3)).fromRed()
  29. .cmp(a.sqr().mul(a)), 0);
  30. assert.equal(a.toRed(m).redPow(new BN(4)).fromRed()
  31. .cmp(a.sqr().sqr()), 0);
  32. assert.equal(a.toRed(m).redPow(new BN(8)).fromRed()
  33. .cmp(a.sqr().sqr().sqr()), 0);
  34. assert.equal(a.toRed(m).redPow(new BN(9)).fromRed()
  35. .cmp(a.sqr().sqr().sqr().mul(a)), 0);
  36. assert.equal(a.toRed(m).redPow(new BN(17)).fromRed()
  37. .cmp(a.sqr().sqr().sqr().sqr().mul(a)), 0);
  38. });
  39. it('should sqrtm numbers', function() {
  40. var p = new BN(263);
  41. var m = fn(p);
  42. var q = new BN(11).toRed(m);
  43. var qr = q.redSqrt(true, p);
  44. assert.equal(qr.redSqr().cmp(q), 0);
  45. var qr = q.redSqrt(false, p);
  46. assert.equal(qr.redSqr().cmp(q), 0);
  47. var p = new BN(
  48. 'fffffffffffffffffffffffffffffffeffffffffffffffff',
  49. 16);
  50. var m = fn(p);
  51. var q = new BN(13).toRed(m);
  52. var qr = q.redSqrt(true, p);
  53. assert.equal(qr.redSqr().cmp(q), 0);
  54. var qr = q.redSqrt(false, p);
  55. assert.equal(qr.redSqr().cmp(q), 0);
  56. // Tonelli-shanks
  57. var p = new BN(13);
  58. var m = fn(p);
  59. var q = new BN(10).toRed(m);
  60. assert.equal(q.redSqrt().fromRed().toString(10), '7');
  61. });
  62. it('should invm numbers', function() {
  63. var p = new BN(257);
  64. var m = fn(p);
  65. var a = new BN(3).toRed(m);
  66. var b = a.redInvm(p);
  67. assert.equal(a.redMul(b).fromRed().toString(16), '1');
  68. });
  69. it('should imul numbers', function() {
  70. var p = new BN(
  71. 'fffffffffffffffffffffffffffffffeffffffffffffffff',
  72. 16);
  73. var m = fn(p);
  74. var a = new BN('deadbeefabbadead', 16);
  75. var b = new BN('abbadeadbeefdead', 16);
  76. var c = a.mul(b).mod(p);
  77. assert.equal(a.toRed(m).redIMul(b.toRed(m)).fromRed().toString(16),
  78. c.toString(16));
  79. });
  80. });
  81. }
  82. testMethod('Plain', BN.red);
  83. testMethod('Montgomery', BN.mont);
  84. describe('Pseudo-Mersenne Primes', function() {
  85. it('should reduce numbers mod k256', function() {
  86. var p = BN._prime('k256');
  87. assert.equal(p.ireduce(new BN(0xdead)).toString(16), 'dead');
  88. assert.equal(p.ireduce(new BN('deadbeef', 16)).toString(16), 'deadbeef');
  89. var num = new BN('fedcba9876543210fedcba9876543210dead' +
  90. 'fedcba9876543210fedcba9876543210dead',
  91. 16);
  92. var exp = num.mod(p.p).toString(16);
  93. assert.equal(p.ireduce(num).toString(16), exp);
  94. var regr = new BN('f7e46df64c1815962bf7bc9c56128798' +
  95. '3f4fcef9cb1979573163b477eab93959' +
  96. '335dfb29ef07a4d835d22aa3b6797760' +
  97. '70a8b8f59ba73d56d01a79af9',
  98. 16);
  99. var exp = regr.mod(p.p).toString(16);
  100. assert.equal(p.ireduce(regr).toString(16), exp);
  101. });
  102. it('should not fail to invm number mod k256', function() {
  103. var regr2 = new BN(
  104. '6c150c4aa9a8cf1934485d40674d4a7cd494675537bda36d49405c5d2c6f496f', 16);
  105. regr2 = regr2.toRed(BN.red('k256'));
  106. assert.equal(regr2.redInvm().redMul(regr2).fromRed().cmpn(1), 0);
  107. });
  108. it('should correctly square the number', function() {
  109. var p = BN._prime('k256').p;
  110. var red = BN.red('k256');
  111. var n = new BN('9cd8cb48c3281596139f147c1364a3ed' +
  112. 'e88d3f310fdb0eb98c924e599ca1b3c9',
  113. 16);
  114. var expected = n.sqr().mod(p);
  115. var actual = n.toRed(red).redSqr().fromRed();
  116. assert.equal(actual.toString(16), expected.toString(16));
  117. });
  118. });
  119. });