Spikes during the decode project

elgamal.html 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. <html>
  2. <head>
  3. <script src="milagro-js/rand.js"></script>
  4. <script src="milagro-js/rom_curve.js"></script>
  5. <script src="milagro-js/rom_field.js"></script>
  6. <script src="milagro-js/uint64.js"></script>
  7. <script src="milagro-js/aes.js"></script>
  8. <script src="milagro-js/big.js"></script>
  9. <script src="milagro-js/gcm.js"></script>
  10. <script src="milagro-js/hash256.js"></script>
  11. <script src="milagro-js/hash384.js"></script>
  12. <script src="milagro-js/hash512.js"></script>
  13. <script src="milagro-js/sha3.js"></script>
  14. <script src="milagro-js/newhope.js"></script>
  15. <script src="milagro-js/nhs.js"></script>
  16. <script src="milagro-js/fp.js"></script>
  17. <script src="milagro-js/fp2.js"></script>
  18. <script src="milagro-js/fp4.js"></script>
  19. <script src="milagro-js/fp12.js"></script>
  20. <script src="milagro-js/ff.js"></script>
  21. <script src="milagro-js/rsa.js"></script>
  22. <script src="milagro-js/ecp.js"></script>
  23. <script src="milagro-js/ecp2.js"></script>
  24. <script src="milagro-js/ecdh.js"></script>
  25. <script src="milagro-js/pair.js"></script>
  26. <script src="milagro-js/mpin.js"></script>
  27. <script src="milagro-js/ctx.js"></script>
  28. <script>
  29. var ctx = new CTX("NIST256");
  30. const verbose = false;
  31. /*
  32. A lot of methods on milagro library mutates the value, to mitigate
  33. the risk of modifying a value without knowing, we can clone the point
  34. each time we call a function
  35. */
  36. function cloneECP(p) {
  37. const clonedP = new ctx.ECP(0);
  38. clonedP.copy(p)
  39. return clonedP;
  40. }
  41. /**
  42. Generates the well-known and public point G
  43. This code is copied from:
  44. https://github.com/milagro-crypto/milagro-crypto-js/blob/develop/src/ecdh.js line 459
  45. */
  46. function getG() {
  47. const G = new ctx.ECP(0); // ECP means: Elliptic curve point...
  48. const gx = new ctx.BIG(0); // x part of the point
  49. const gy = new ctx.BIG(0); // y part of the point
  50. gx.rcopy(ctx.ROM_CURVE.CURVE_Gx);
  51. gy.rcopy(ctx.ROM_CURVE.CURVE_Gy);
  52. G.setxy(gx, gy)
  53. return G;
  54. }
  55. /**
  56. Generates a well known point H... What I do is just sum G again...
  57. but I don't know if that makes the thing less secure :?
  58. */
  59. function getH() {
  60. const G = getG();
  61. const scalar = new ctx.BIG(1); // NExt point?
  62. return G.mul(scalar);
  63. }
  64. function generateH_m(message) {
  65. const H = getH();
  66. return H.mul(message)
  67. }
  68. /**
  69. Generates a key x and a public key of x (pk_x)
  70. 1. Decide the key value
  71. 2. mod this value to the "order" of the curve (suppose the mod p of the curve :?)
  72. 3. multiply G to the key => pk_x
  73. */
  74. function keygen(key) {
  75. key = key || 42;
  76. const r = new ctx.BIG(0);
  77. r.rcopy(ctx.ROM_CURVE.CURVE_Order); // I think R is like the mod p
  78. const G = getG();
  79. const x = new ctx.BIG(key); // Meaning of life...
  80. x.mod(r)
  81. verbose && console.log("x: ", x.toString());
  82. const pk_x = G.mul(x)
  83. verbose && console.log("pk_x: ", pk_x.toString());
  84. return {x: x, pk_x: pk_x};
  85. }
  86. /*
  87. 1. decide a random k
  88. 2. mul(G, k) => s
  89. 3. mul(pk_x, k) + mul(H, m) => p
  90. */
  91. function E(vote_option, random_num_k, pk_x) {
  92. pk_x = cloneECP(pk_x);
  93. const G = getG();
  94. const H = getH();
  95. random_num_k = new ctx.BIG(random_num_k);
  96. vote_option = new ctx.BIG(vote_option);
  97. const s = G.mul(random_num_k);
  98. const pk_x_k = pk_x.mul(random_num_k);
  99. const h_m = generateH_m(vote_option);
  100. verbose && console.log("s: ", s.toString());
  101. verbose && console.log("pk_x_k: ", pk_x_k.toString());
  102. console.log("h_m:", h_m.toString());
  103. pk_x_k.add(h_m);
  104. verbose && console.log("p:", pk_x_k.toString());
  105. return {
  106. s: s,
  107. p: pk_x_k,
  108. }
  109. }
  110. /*
  111. 1. s = mul(s, x)
  112. 3. h_m = p - inverse(s)
  113. */
  114. function D(x, s, p) {
  115. s = cloneECP(s);
  116. p = cloneECP(p);
  117. const G = getG();
  118. const s_x = s.mul(x);
  119. s_x.neg();
  120. p.add(s_x);
  121. console.log("decrypted h_m: ", p.toString());
  122. return p;
  123. }
  124. /**
  125. s = s0 + s1
  126. p = p0 + p1
  127. */
  128. function SUM(s0, p0, s1, p1) {
  129. const G = getG();
  130. s0 = cloneECP(s0);
  131. s1 = cloneECP(s1);
  132. p0 = cloneECP(p0);
  133. p1 = cloneECP(p1);
  134. s0.add(s1);
  135. p0.add(p1);
  136. verbose && console.log("p: ", p0.toString());
  137. verbose && console.log("s: ", s0.toString());
  138. return {
  139. s: s0,
  140. p: p0,
  141. }
  142. }
  143. /*
  144. Debugging function to see all the steps and put some console logs
  145. where we suspect somoething is going wrong
  146. */
  147. function testScenario() {
  148. const {x, pk_x} = keygen();
  149. const E1 = E(1, 60, pk_x);
  150. D(x, E1.s, E1.p);
  151. console.log("!!!!! HUMMAN ASSERT!!!! result === h_m");
  152. console.log("STARTING TO SUM");
  153. console.log("Starting E1");
  154. const E_1 = E(1, 30, pk_x);
  155. console.log("Starting E2");
  156. const E_2 = E(2, 90, pk_x);
  157. console.log("Starting E_SUM");
  158. const E_SUM = SUM(E_1.s, E_1.p, E_2.s, E_2.p);
  159. console.log("Decrypt E_SUM")
  160. D(x, E_SUM.s, E_SUM.p);
  161. E(3, 9, pk_x);
  162. }
  163. /*************************************************
  164. * The code below is only for the page to interact
  165. * so you see the intermidiate results
  166. *************************************************/
  167. const GLOBAL = {
  168. E: [],
  169. };
  170. function show_genkey() {
  171. const key = parseInt(window.prompt("Introduce some number - will be the key","42"));
  172. const {x, pk_x} = keygen(key);
  173. document.querySelector("#scenario-x").innerHTML = x.toString();
  174. document.querySelector("#scenario-pk_x").innerHTML = pk_x.toString();
  175. GLOBAL.x = x;
  176. GLOBAL.pk_x = pk_x;
  177. }
  178. function show_h_m() {
  179. const message = parseInt(window.prompt("Introduce a number you want H ^ m", "1"));
  180. const h_m = generateH_m(new ctx.BIG(message));
  181. document.querySelector("#scenario-m").innerHTML = message.toString();
  182. document.querySelector("#scenario-h_m").innerHTML = h_m.toString();
  183. }
  184. function show_encrypt(div_m, div_p, div_s, index) {
  185. div_m = document.querySelector('#' + div_m);
  186. div_p = document.querySelector('#' + div_p);
  187. div_s = document.querySelector('#' + div_s);
  188. const message = parseInt(window.prompt("Introduce a number you to encrypt", "1"));
  189. const k = parseInt(window.prompt("Introduce a number random", "99"));
  190. const m = new ctx.BIG(message);
  191. div_m.innerHTML = m.toString();
  192. const {s, p} = E(m, k, GLOBAL.pk_x);
  193. div_p.innerHTML = p.toString();
  194. div_s.innerHTML = s.toString();
  195. GLOBAL.E[index] = {s, p}
  196. }
  197. function show_decrypt(div_h_m, index) {
  198. const {s, p} = GLOBAL.E[index];
  199. const h_m = D(GLOBAL.x, s, p);
  200. document.querySelector('#' + div_h_m).innerHTML = h_m.toString();
  201. }
  202. function show_sum(div_p, div_s) {
  203. div_p = document.querySelector('#' + div_p);
  204. div_s = document.querySelector('#' + div_s);
  205. E1 = GLOBAL.E[0];
  206. E2 = GLOBAL.E[1];
  207. const {p, s} = SUM(E1.s, E1.p, E2.s, E2.p);
  208. div_p.innerHTML = p.toString();
  209. div_s.innerHTML = s.toString();
  210. GLOBAL.E[2] = {s, p}
  211. }
  212. </script>
  213. </head>
  214. <body>
  215. <h1> ElGamal </h1>
  216. <h3> Key generation </h3>
  217. <p>x: <span id="scenario-x"/> </p>
  218. <p>public key x: <span id="scenario-pk_x"/> </p>
  219. <a href="javascript:show_genkey()"> Generate Key </a>
  220. <h3> Encryption 1</h3>
  221. <p>m: <span id="scenario-m0"/> </p>
  222. <p>p: <span id="scenario-p0"/> </p>
  223. <p>s: <span id="scenario-s0"/> </p>
  224. <a href="javascript:show_encrypt('scenario-m0', 'scenario-p0', 'scenario-s0', 0)"> Encrypt 1</a>
  225. <h3> Encryption 2 </h3>
  226. <p>m: <span id="scenario-m1"/> </p>
  227. <p>p: <span id="scenario-p1"/> </p>
  228. <p>s: <span id="scenario-s1"/> </p>
  229. <a href="javascript:show_encrypt('scenario-m1', 'scenario-p1', 'scenario-s1', 1)"> Encrypt 1</a>
  230. <h3> Decrypt 1 </h3>
  231. <p>H ^ m: <span id="scenario-d-h_m-0" /></p>
  232. <a href="javascript:show_decrypt('scenario-d-h_m-0', 0)"> Decrypt 1</a>
  233. <h3> Decrypt 2 </h3>
  234. <p>H ^ m: <span id="scenario-d-h_m-1" /></p>
  235. <a href="javascript:show_decrypt('scenario-d-h_m-1', 1)"> Decrypt 1</a>
  236. <h3>Sum </h3>
  237. <p>p: <span id="scenario-sum-p"/> </p>
  238. <p>s: <span id="scenario-sum-s"/> </p>
  239. <a href="javascript:show_sum('scenario-sum-p', 'scenario-sum-s')"> Sum E1 and E2 </a>
  240. <h3>Decrypt Sum </h3>
  241. <p>h_m: <span id="scenario-sum-h_m"/> </p>
  242. <a href="javascript:show_decrypt('scenario-sum-h_m', 2)"> Decrypt Sum</a>
  243. <h3> H ^ m </h3>
  244. <p>m: <span id="scenario-m"/> </p>
  245. <p>H ^ m: <span id="scenario-h_m"/> </p>
  246. <a href="javascript:show_h_m()"> Generate H ^ m</a>
  247. </body>
  248. </html>