You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
3.2 KiB

  1. const F1Field = require("ffjavascript").F1Field;
  2. const Scalar = require("ffjavascript").Scalar;
  3. const utils = require("ffjavascript").utils;
  4. exports.addPoint = addPoint;
  5. exports.mulPointEscalar = mulPointEscalar;
  6. exports.inCurve = inCurve;
  7. exports.inSubgroup = inSubgroup;
  8. exports.packPoint = packPoint;
  9. exports.unpackPoint = unpackPoint;
  10. exports.p = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
  11. const F = new F1Field(exports.p);
  12. exports.F = F;
  13. exports.Generator = [
  14. F.e("995203441582195749578291179787384436505546430278305826713579947235728471134"),
  15. F.e("5472060717959818805561601436314318772137091100104008585924551046643952123905")
  16. ];
  17. exports.Base8 = [
  18. F.e("5299619240641551281634865583518297030282874472190772894086521144482721001553"),
  19. F.e("16950150798460657717958625567821834550301663161624707787222815936182638968203")
  20. ];
  21. exports.order = Scalar.fromString("21888242871839275222246405745257275088614511777268538073601725287587578984328");
  22. exports.subOrder = Scalar.shiftRight(exports.order, 3);
  23. exports.A = F.e("168700");
  24. exports.D = F.e("168696");
  25. function addPoint(a,b) {
  26. const res = [];
  27. /* does the equivalent of:
  28. res[0] = bigInt((a[0]*b[1] + b[0]*a[1]) * bigInt(bigInt("1") + d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q);
  29. res[1] = bigInt((a[1]*b[1] - cta*a[0]*b[0]) * bigInt(bigInt("1") - d*a[0]*b[0]*a[1]*b[1]).inverse(q)).affine(q);
  30. */
  31. const beta = F.mul(a[0],b[1]);
  32. const gamma = F.mul(a[1],b[0]);
  33. const delta = F.mul(
  34. F.sub(a[1], F.mul(exports.A, a[0])),
  35. F.add(b[0], b[1])
  36. );
  37. const tau = F.mul(beta, gamma);
  38. const dtau = F.mul(exports.D, tau);
  39. res[0] = F.div(
  40. F.add(beta, gamma),
  41. F.add(F.one, dtau)
  42. );
  43. res[1] = F.div(
  44. F.add(delta, F.sub(F.mul(exports.A,beta), gamma)),
  45. F.sub(F.one, dtau)
  46. );
  47. return res;
  48. }
  49. function mulPointEscalar(base, e) {
  50. let res = [F.e("0"),F.e("1")];
  51. let rem = e;
  52. let exp = base;
  53. while (! Scalar.isZero(rem)) {
  54. if (Scalar.isOdd(rem)) {
  55. res = addPoint(res, exp);
  56. }
  57. exp = addPoint(exp, exp);
  58. rem = Scalar.shiftRight(rem, 1);
  59. }
  60. return res;
  61. }
  62. function inSubgroup(P) {
  63. if (!inCurve(P)) return false;
  64. const res= mulPointEscalar(P, exports.subOrder);
  65. return (F.isZero(res[0]) && F.eq(res[1], F.one));
  66. }
  67. function inCurve(P) {
  68. const x2 = F.square(P[0]);
  69. const y2 = F.square(P[1]);
  70. if (!F.eq(
  71. F.add(F.mul(exports.A, x2), y2),
  72. F.add(F.one, F.mul(F.mul(x2, y2), exports.D)))) return false;
  73. return true;
  74. }
  75. function packPoint(P) {
  76. const buff = utils.leInt2Buff(P[1], 32);
  77. if (F.lt(P[0], F.zero)) {
  78. buff[31] = buff[31] | 0x80;
  79. }
  80. return buff;
  81. }
  82. function unpackPoint(_buff) {
  83. const buff = Buffer.from(_buff);
  84. let sign = false;
  85. const P = new Array(2);
  86. if (buff[31] & 0x80) {
  87. sign = true;
  88. buff[31] = buff[31] & 0x7F;
  89. }
  90. P[1] = utils.leBuff2int(buff);
  91. if (Scalar.gt(P[1], exports.p)) return null;
  92. const y2 = F.square(P[1]);
  93. let x = F.sqrt(F.div(
  94. F.sub(F.one, y2),
  95. F.sub(exports.A, F.mul(exports.D, y2))));
  96. if (x == null) return null;
  97. if (sign) x = F.neg(x);
  98. P[0] = x;
  99. return P;
  100. }