Browse Source

ADD elGamal

Jordi Coscolla 1 year ago
commit
fe7bd0124f

+ 5 - 0
README.md

@@ -0,0 +1,5 @@
1
+# Spikes
2
+
3
+Some spikes the TW team has made to explore.
4
+
5
+## El Gamal 

BIN
elgamal/.elgamal.html.swp


+ 314 - 0
elgamal/elgamal.html

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

+ 709 - 0
elgamal/milagro-js/aes.js

@@ -0,0 +1,709 @@
1
+/*
2
+    Licensed to the Apache Software Foundation (ASF) under one
3
+    or more contributor license agreements.  See the NOTICE file
4
+    distributed with this work for additional information
5
+    regarding copyright ownership.  The ASF licenses this file
6
+    to you under the Apache License, Version 2.0 (the
7
+    "License"); you may not use this file except in compliance
8
+    with the License.  You may obtain a copy of the License at
9
+
10
+    http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+    Unless required by applicable law or agreed to in writing,
13
+    software distributed under the License is distributed on an
14
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+    KIND, either express or implied.  See the License for the
16
+    specific language governing permissions and limitations
17
+    under the License.
18
+*/
19
+
20
+var AES = function() {
21
+    "use strict";
22
+
23
+    var AES = function() {
24
+        this.Nk = 0;
25
+        this.Nr = 0;
26
+        this.mode = 0;
27
+        this.fkey = [];
28
+        this.rkey = [];
29
+        this.f = [];
30
+    };
31
+
32
+    // AES constants
33
+    AES.ECB = 0;
34
+    AES.CBC = 1;
35
+    AES.CFB1 = 2;
36
+    AES.CFB2 = 3;
37
+    AES.CFB4 = 5;
38
+    AES.OFB1 = 14;
39
+    AES.OFB2 = 15;
40
+    AES.OFB4 = 17;
41
+    AES.OFB8 = 21;
42
+    AES.OFB16 = 29;
43
+    AES.CTR1 = 30;
44
+    AES.CTR2 = 31;
45
+    AES.CTR4 = 33;
46
+    AES.CTR8 = 37;
47
+    AES.CTR16 = 45;
48
+
49
+    AES.prototype = {
50
+        /* reset cipher */
51
+        reset: function(m, iv) { /* reset mode, or reset iv */
52
+            var i;
53
+
54
+            this.mode = m;
55
+
56
+            for (i = 0; i < 16; i++) {
57
+                this.f[i] = 0;
58
+            }
59
+
60
+            if (this.mode != AES.ECB && iv !== null) {
61
+                for (i = 0; i < 16; i++) {
62
+                    this.f[i] = iv[i];
63
+                }
64
+            }
65
+        },
66
+
67
+        getreg: function() {
68
+            var ir = [],
69
+                i;
70
+
71
+            for (i = 0; i < 16; i++) {
72
+                ir[i] = this.f[i];
73
+            }
74
+
75
+            return ir;
76
+        },
77
+
78
+        increment: function() {
79
+            var i;
80
+
81
+            for (i = 0; i < 16; i++) {
82
+                this.f[i]++;
83
+
84
+                if ((this.f[i] & 0xff) != 0) {
85
+                    break;
86
+                }
87
+            }
88
+        },
89
+
90
+        /* Initialise cipher */
91
+        init: function(m, nk, key, iv) { /* Key=16 bytes */
92
+            /* Key Scheduler. Create expanded encryption key */
93
+            var CipherKey = [],
94
+                b = [],
95
+                i, j, k, N, nr;
96
+
97
+            nk /= 4;
98
+
99
+            if (nk != 4 && nk != 6 && nk != 8) {
100
+                return false;
101
+            }
102
+
103
+            nr = 6 + nk;
104
+
105
+            this.Nk = nk;
106
+            this.Nr = nr;
107
+
108
+
109
+            this.reset(m, iv);
110
+            N = 4 * (nr + 1);
111
+
112
+            for (i = j = 0; i < nk; i++, j += 4) {
113
+                for (k = 0; k < 4; k++) {
114
+                    b[k] = key[j + k];
115
+                }
116
+                CipherKey[i] = AES.pack(b);
117
+            }
118
+
119
+            for (i = 0; i < nk; i++) {
120
+                this.fkey[i] = CipherKey[i];
121
+            }
122
+
123
+            for (j = nk, k = 0; j < N; j += nk, k++) {
124
+                this.fkey[j] = this.fkey[j - nk] ^ AES.SubByte(AES.ROTL24(this.fkey[j - 1])) ^ (AES.rco[k]) & 0xff;
125
+                for (i = 1; i < nk && (i + j) < N; i++) {
126
+                    this.fkey[i + j] = this.fkey[i + j - nk] ^ this.fkey[i + j - 1];
127
+                }
128
+            }
129
+
130
+            /* now for the expanded decrypt key in reverse order */
131
+
132
+            for (j = 0; j < 4; j++) {
133
+                this.rkey[j + N - 4] = this.fkey[j];
134
+            }
135
+
136
+            for (i = 4; i < N - 4; i += 4) {
137
+                k = N - 4 - i;
138
+                for (j = 0; j < 4; j++) {
139
+                    this.rkey[k + j] = AES.InvMixCol(this.fkey[i + j]);
140
+                }
141
+            }
142
+
143
+            for (j = N - 4; j < N; j++) {
144
+                this.rkey[j - N + 4] = this.fkey[j];
145
+            }
146
+        },
147
+
148
+        /* Encrypt a single block */
149
+        ecb_encrypt: function(buff) {
150
+            var b = [],
151
+                p = [],
152
+                q = [],
153
+                t, i, j, k;
154
+
155
+            for (i = j = 0; i < 4; i++, j += 4) {
156
+                for (k = 0; k < 4; k++) {
157
+                    b[k] = buff[j + k];
158
+                }
159
+                p[i] = AES.pack(b);
160
+                p[i] ^= this.fkey[i];
161
+            }
162
+
163
+            k = 4;
164
+
165
+            /* State alternates between p and q */
166
+            for (i = 1; i < this.Nr; i++) {
167
+                q[0] = this.fkey[k] ^ AES.ftable[p[0] & 0xff] ^
168
+                    AES.ROTL8(AES.ftable[(p[1] >>> 8) & 0xff]) ^
169
+                    AES.ROTL16(AES.ftable[(p[2] >>> 16) & 0xff]) ^
170
+                    AES.ROTL24(AES.ftable[(p[3] >>> 24) & 0xff]);
171
+                q[1] = this.fkey[k + 1] ^ AES.ftable[p[1] & 0xff] ^
172
+                    AES.ROTL8(AES.ftable[(p[2] >>> 8) & 0xff]) ^
173
+                    AES.ROTL16(AES.ftable[(p[3] >>> 16) & 0xff]) ^
174
+                    AES.ROTL24(AES.ftable[(p[0] >>> 24) & 0xff]);
175
+                q[2] = this.fkey[k + 2] ^ AES.ftable[p[2] & 0xff] ^
176
+                    AES.ROTL8(AES.ftable[(p[3] >>> 8) & 0xff]) ^
177
+                    AES.ROTL16(AES.ftable[(p[0] >>> 16) & 0xff]) ^
178
+                    AES.ROTL24(AES.ftable[(p[1] >>> 24) & 0xff]);
179
+                q[3] = this.fkey[k + 3] ^ AES.ftable[p[3] & 0xff] ^
180
+                    AES.ROTL8(AES.ftable[(p[0] >>> 8) & 0xff]) ^
181
+                    AES.ROTL16(AES.ftable[(p[1] >>> 16) & 0xff]) ^
182
+                    AES.ROTL24(AES.ftable[(p[2] >>> 24) & 0xff]);
183
+
184
+                k += 4;
185
+                for (j = 0; j < 4; j++) {
186
+                    t = p[j];
187
+                    p[j] = q[j];
188
+                    q[j] = t;
189
+                }
190
+            }
191
+
192
+            /* Last Round */
193
+
194
+            q[0] = this.fkey[k] ^ (AES.fbsub[p[0] & 0xff] & 0xff) ^
195
+                AES.ROTL8(AES.fbsub[(p[1] >>> 8) & 0xff] & 0xff) ^
196
+                AES.ROTL16(AES.fbsub[(p[2] >>> 16) & 0xff] & 0xff) ^
197
+                AES.ROTL24(AES.fbsub[(p[3] >>> 24) & 0xff] & 0xff);
198
+
199
+            q[1] = this.fkey[k + 1] ^ (AES.fbsub[p[1] & 0xff] & 0xff) ^
200
+                AES.ROTL8(AES.fbsub[(p[2] >>> 8) & 0xff] & 0xff) ^
201
+                AES.ROTL16(AES.fbsub[(p[3] >>> 16) & 0xff] & 0xff) ^
202
+                AES.ROTL24(AES.fbsub[(p[0] >>> 24) & 0xff] & 0xff);
203
+
204
+            q[2] = this.fkey[k + 2] ^ (AES.fbsub[p[2] & 0xff] & 0xff) ^
205
+                AES.ROTL8(AES.fbsub[(p[3] >>> 8) & 0xff] & 0xff) ^
206
+                AES.ROTL16(AES.fbsub[(p[0] >>> 16) & 0xff] & 0xff) ^
207
+                AES.ROTL24(AES.fbsub[(p[1] >>> 24) & 0xff] & 0xff);
208
+
209
+            q[3] = this.fkey[k + 3] ^ (AES.fbsub[(p[3]) & 0xff] & 0xff) ^
210
+                AES.ROTL8(AES.fbsub[(p[0] >>> 8) & 0xff] & 0xff) ^
211
+                AES.ROTL16(AES.fbsub[(p[1] >>> 16) & 0xff] & 0xff) ^
212
+                AES.ROTL24(AES.fbsub[(p[2] >>> 24) & 0xff] & 0xff);
213
+
214
+            for (i = j = 0; i < 4; i++, j += 4) {
215
+                b = AES.unpack(q[i]);
216
+                for (k = 0; k < 4; k++) {
217
+                    buff[j + k] = b[k];
218
+                }
219
+            }
220
+        },
221
+
222
+        /* Decrypt a single block */
223
+        ecb_decrypt: function(buff) {
224
+            var b = [],
225
+                p = [],
226
+                q = [],
227
+                t, i, j, k;
228
+
229
+            for (i = j = 0; i < 4; i++, j += 4) {
230
+                for (k = 0; k < 4; k++) {
231
+                    b[k] = buff[j + k];
232
+                }
233
+                p[i] = AES.pack(b);
234
+                p[i] ^= this.rkey[i];
235
+            }
236
+
237
+            k = 4;
238
+
239
+            /* State alternates between p and q */
240
+            for (i = 1; i < this.Nr; i++) {
241
+                q[0] = this.rkey[k] ^ AES.rtable[p[0] & 0xff] ^
242
+                    AES.ROTL8(AES.rtable[(p[3] >>> 8) & 0xff]) ^
243
+                    AES.ROTL16(AES.rtable[(p[2] >>> 16) & 0xff]) ^
244
+                    AES.ROTL24(AES.rtable[(p[1] >>> 24) & 0xff]);
245
+                q[1] = this.rkey[k + 1] ^ AES.rtable[p[1] & 0xff] ^
246
+                    AES.ROTL8(AES.rtable[(p[0] >>> 8) & 0xff]) ^
247
+                    AES.ROTL16(AES.rtable[(p[3] >>> 16) & 0xff]) ^
248
+                    AES.ROTL24(AES.rtable[(p[2] >>> 24) & 0xff]);
249
+                q[2] = this.rkey[k + 2] ^ AES.rtable[p[2] & 0xff] ^
250
+                    AES.ROTL8(AES.rtable[(p[1] >>> 8) & 0xff]) ^
251
+                    AES.ROTL16(AES.rtable[(p[0] >>> 16) & 0xff]) ^
252
+                    AES.ROTL24(AES.rtable[(p[3] >>> 24) & 0xff]);
253
+                q[3] = this.rkey[k + 3] ^ AES.rtable[p[3] & 0xff] ^
254
+                    AES.ROTL8(AES.rtable[(p[2] >>> 8) & 0xff]) ^
255
+                    AES.ROTL16(AES.rtable[(p[1] >>> 16) & 0xff]) ^
256
+                    AES.ROTL24(AES.rtable[(p[0] >>> 24) & 0xff]);
257
+
258
+                k += 4;
259
+
260
+                for (j = 0; j < 4; j++) {
261
+                    t = p[j];
262
+                    p[j] = q[j];
263
+                    q[j] = t;
264
+                }
265
+            }
266
+
267
+            /* Last Round */
268
+
269
+            q[0] = this.rkey[k] ^ (AES.rbsub[p[0] & 0xff] & 0xff) ^
270
+                AES.ROTL8(AES.rbsub[(p[3] >>> 8) & 0xff] & 0xff) ^
271
+                AES.ROTL16(AES.rbsub[(p[2] >>> 16) & 0xff] & 0xff) ^
272
+                AES.ROTL24(AES.rbsub[(p[1] >>> 24) & 0xff] & 0xff);
273
+            q[1] = this.rkey[k + 1] ^ (AES.rbsub[p[1] & 0xff] & 0xff) ^
274
+                AES.ROTL8(AES.rbsub[(p[0] >>> 8) & 0xff] & 0xff) ^
275
+                AES.ROTL16(AES.rbsub[(p[3] >>> 16) & 0xff] & 0xff) ^
276
+                AES.ROTL24(AES.rbsub[(p[2] >>> 24) & 0xff] & 0xff);
277
+            q[2] = this.rkey[k + 2] ^ (AES.rbsub[p[2] & 0xff] & 0xff) ^
278
+                AES.ROTL8(AES.rbsub[(p[1] >>> 8) & 0xff] & 0xff) ^
279
+                AES.ROTL16(AES.rbsub[(p[0] >>> 16) & 0xff] & 0xff) ^
280
+                AES.ROTL24(AES.rbsub[(p[3] >>> 24) & 0xff] & 0xff);
281
+            q[3] = this.rkey[k + 3] ^ (AES.rbsub[p[3] & 0xff] & 0xff) ^
282
+                AES.ROTL8(AES.rbsub[(p[2] >>> 8) & 0xff] & 0xff) ^
283
+                AES.ROTL16(AES.rbsub[(p[1] >>> 16) & 0xff] & 0xff) ^
284
+                AES.ROTL24(AES.rbsub[(p[0] >>> 24) & 0xff] & 0xff);
285
+
286
+            for (i = j = 0; i < 4; i++, j += 4) {
287
+                b = AES.unpack(q[i]);
288
+                for (k = 0; k < 4; k++) {
289
+                    buff[j + k] = b[k];
290
+                }
291
+            }
292
+
293
+        },
294
+
295
+        /* Encrypt using selected mode of operation */
296
+        encrypt: function(buff) {
297
+            var st = [],
298
+                bytes, fell_off, j;
299
+
300
+            // Supported Modes of Operation
301
+
302
+            fell_off = 0;
303
+
304
+            switch (this.mode) {
305
+                case AES.ECB:
306
+                    this.ecb_encrypt(buff);
307
+                    return 0;
308
+
309
+                case AES.CBC:
310
+                    for (j = 0; j < 16; j++) {
311
+                        buff[j] ^= this.f[j];
312
+                    }
313
+                    this.ecb_encrypt(buff);
314
+                    for (j = 0; j < 16; j++) {
315
+                        this.f[j] = buff[j];
316
+                    }
317
+                    return 0;
318
+
319
+                case AES.CFB1:
320
+                case AES.CFB2:
321
+                case AES.CFB4:
322
+                    bytes = this.mode - AES.CFB1 + 1;
323
+                    for (j = 0; j < bytes; j++) {
324
+                        fell_off = (fell_off << 8) | this.f[j];
325
+                    }
326
+                    for (j = 0; j < 16; j++) {
327
+                        st[j] = this.f[j];
328
+                    }
329
+                    for (j = bytes; j < 16; j++) {
330
+                        this.f[j - bytes] = this.f[j];
331
+                    }
332
+                    this.ecb_encrypt(st);
333
+                    for (j = 0; j < bytes; j++) {
334
+                        buff[j] ^= st[j];
335
+                        this.f[16 - bytes + j] = buff[j];
336
+                    }
337
+                    return fell_off;
338
+
339
+                case AES.OFB1:
340
+                case AES.OFB2:
341
+                case AES.OFB4:
342
+                case AES.OFB8:
343
+                case AES.OFB16:
344
+                    bytes = this.mode - AES.OFB1 + 1;
345
+                    this.ecb_encrypt(this.f);
346
+                    for (j = 0; j < bytes; j++) {
347
+                        buff[j] ^= this.f[j];
348
+                    }
349
+                    return 0;
350
+
351
+                case AES.CTR1:
352
+                case AES.CTR2:
353
+                case AES.CTR4:
354
+                case AES.CTR8:
355
+                case AES.CTR16:
356
+                    bytes = this.mode - AES.CTR1 + 1;
357
+                    for (j = 0; j < 16; j++) {
358
+                        st[j] = this.f[j];
359
+                    }
360
+                    this.ecb_encrypt(st);
361
+                    for (j = 0; j < bytes; j++) {
362
+                        buff[j] ^= st[j];
363
+                    }
364
+                    this.increment();
365
+                    return 0;
366
+
367
+                default:
368
+                    return 0;
369
+            }
370
+        },
371
+
372
+        /* Decrypt using selected mode of operation */
373
+        decrypt: function(buff) {
374
+            var st = [],
375
+                bytes,fell_off, j;
376
+
377
+            // Supported modes of operation
378
+            fell_off = 0;
379
+            switch (this.mode) {
380
+                case AES.ECB:
381
+                    this.ecb_decrypt(buff);
382
+                    return 0;
383
+
384
+                case AES.CBC:
385
+                    for (j = 0; j < 16; j++) {
386
+                        st[j] = this.f[j];
387
+                        this.f[j] = buff[j];
388
+                    }
389
+                    this.ecb_decrypt(buff);
390
+                    for (j = 0; j < 16; j++) {
391
+                        buff[j] ^= st[j];
392
+                        st[j] = 0;
393
+                    }
394
+                    return 0;
395
+
396
+                case AES.CFB1:
397
+                case AES.CFB2:
398
+                case AES.CFB4:
399
+                    bytes = this.mode - AES.CFB1 + 1;
400
+                    for (j = 0; j < bytes; j++) {
401
+                        fell_off = (fell_off << 8) | this.f[j];
402
+                    }
403
+                    for (j = 0; j < 16; j++) {
404
+                        st[j] = this.f[j];
405
+                    }
406
+                    for (j = bytes; j < 16; j++) {
407
+                        this.f[j - bytes] = this.f[j];
408
+                    }
409
+                    this.ecb_encrypt(st);
410
+                    for (j = 0; j < bytes; j++) {
411
+                        this.f[16 - bytes + j] = buff[j];
412
+                        buff[j] ^= st[j];
413
+                    }
414
+                    return fell_off;
415
+
416
+                case AES.OFB1:
417
+                case AES.OFB2:
418
+                case AES.OFB4:
419
+                case AES.OFB8:
420
+                case AES.OFB16:
421
+                    bytes = this.mode - AES.OFB1 + 1;
422
+                    this.ecb_encrypt(this.f);
423
+                    for (j = 0; j < bytes; j++) {
424
+                        buff[j] ^= this.f[j];
425
+                    }
426
+                    return 0;
427
+
428
+                case AES.CTR1:
429
+                case AES.CTR2:
430
+                case AES.CTR4:
431
+                case AES.CTR8:
432
+                case AES.CTR16:
433
+                    bytes = this.mode - AES.CTR1 + 1;
434
+                    for (j = 0; j < 16; j++) {
435
+                        st[j] = this.f[j];
436
+                    }
437
+                    this.ecb_encrypt(st);
438
+                    for (j = 0; j < bytes; j++) {
439
+                        buff[j] ^= st[j];
440
+                    }
441
+                    this.increment();
442
+                    return 0;
443
+
444
+                default:
445
+                    return 0;
446
+            }
447
+        },
448
+
449
+        /* Clean up and delete left-overs */
450
+        end: function() { // clean up
451
+            var i;
452
+
453
+            for (i = 0; i < 4 * (this.Nr + 1); i++) {
454
+                this.fkey[i] = this.rkey[i] = 0;
455
+            }
456
+
457
+            for (i = 0; i < 16; i++) {
458
+                this.f[i] = 0;
459
+            }
460
+        }
461
+    };
462
+
463
+    /* static functions */
464
+
465
+    AES.ROTL8 = function(x) {
466
+        return (((x) << 8) | ((x) >>> 24));
467
+    };
468
+
469
+    AES.ROTL16 = function(x) {
470
+        return (((x) << 16) | ((x) >>> 16));
471
+    };
472
+
473
+    AES.ROTL24 = function(x) {
474
+        return (((x) << 24) | ((x) >>> 8));
475
+    };
476
+
477
+    AES.pack = function(b) { /* pack 4 bytes into a 32-bit Word */
478
+        return (((b[3]) & 0xff) << 24) | ((b[2] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[0] & 0xff);
479
+    };
480
+
481
+    AES.unpack = function(a) { /* unpack bytes from a word */
482
+        var b = [];
483
+        b[0] = (a & 0xff);
484
+        b[1] = ((a >>> 8) & 0xff);
485
+        b[2] = ((a >>> 16) & 0xff);
486
+        b[3] = ((a >>> 24) & 0xff);
487
+        return b;
488
+    };
489
+
490
+    AES.bmul = function(x, y) { /* x.y= AntiLog(Log(x) + Log(y)) */
491
+        var ix = (x & 0xff),
492
+            iy = (y & 0xff),
493
+            lx = (AES.ltab[ix]) & 0xff,
494
+            ly = (AES.ltab[iy]) & 0xff;
495
+
496
+        if (x !== 0 && y !== 0) {
497
+            return AES.ptab[(lx + ly) % 255];
498
+        } else {
499
+            return 0;
500
+        }
501
+    };
502
+
503
+    //  if (x && y)
504
+
505
+    AES.SubByte = function(a) {
506
+        var b = AES.unpack(a);
507
+        b[0] = AES.fbsub[b[0] & 0xff];
508
+        b[1] = AES.fbsub[b[1] & 0xff];
509
+        b[2] = AES.fbsub[b[2] & 0xff];
510
+        b[3] = AES.fbsub[b[3] & 0xff];
511
+        return AES.pack(b);
512
+    };
513
+
514
+    AES.product = function(x, y) { /* dot product of two 4-byte arrays */
515
+        var xb = AES.unpack(x),
516
+            yb = AES.unpack(y);
517
+
518
+        return (AES.bmul(xb[0], yb[0]) ^ AES.bmul(xb[1], yb[1]) ^ AES.bmul(xb[2], yb[2]) ^ AES.bmul(xb[3], yb[3])) & 0xff;
519
+    };
520
+
521
+    AES.InvMixCol = function(x) { /* matrix Multiplication */
522
+        var b = [],
523
+            y, m;
524
+
525
+        m = AES.pack(AES.InCo);
526
+        b[3] = AES.product(m, x);
527
+        m = AES.ROTL24(m);
528
+        b[2] = AES.product(m, x);
529
+        m = AES.ROTL24(m);
530
+        b[1] = AES.product(m, x);
531
+        m = AES.ROTL24(m);
532
+        b[0] = AES.product(m, x);
533
+        y = AES.pack(b);
534
+
535
+        return y;
536
+    };
537
+
538
+    AES.InCo = [0xB, 0xD, 0x9, 0xE]; /* Inverse Coefficients */
539
+    AES.rco = [1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47];
540
+
541
+    AES.ptab = [
542
+        1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53,
543
+        95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170,
544
+        229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49,
545
+        83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205,
546
+        76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136,
547
+        131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154,
548
+        181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163,
549
+        254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160,
550
+        251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65,
551
+        195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117,
552
+        159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
553
+        155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84,
554
+        252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202,
555
+        69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14,
556
+        18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23,
557
+        57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1
558
+    ];
559
+    AES.ltab = [
560
+        0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3,
561
+        100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193,
562
+        125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120,
563
+        101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142,
564
+        150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56,
565
+        102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16,
566
+        126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186,
567
+        43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87,
568
+        175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232,
569
+        44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160,
570
+        127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183,
571
+        204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157,
572
+        151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209,
573
+        83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171,
574
+        68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165,
575
+        103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7
576
+    ];
577
+    AES.fbsub = [
578
+        99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
579
+        202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
580
+        183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
581
+        4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
582
+        9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
583
+        83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
584
+        208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
585
+        81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
586
+        205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
587
+        96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
588
+        224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
589
+        231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
590
+        186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
591
+        112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
592
+        225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
593
+        140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
594
+    ];
595
+    AES.rbsub = [
596
+        82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251,
597
+        124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203,
598
+        84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78,
599
+        8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37,
600
+        114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146,
601
+        108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132,
602
+        144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6,
603
+        208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107,
604
+        58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
605
+        150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110,
606
+        71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27,
607
+        252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244,
608
+        31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95,
609
+        96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239,
610
+        160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
611
+        23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125
612
+    ];
613
+    AES.ftable = [
614
+        0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0xdf2f2ff, 0xbd6b6bd6,
615
+        0xb16f6fde, 0x54c5c591, 0x50303060, 0x3010102, 0xa96767ce, 0x7d2b2b56,
616
+        0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f,
617
+        0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0xbf0f0fb,
618
+        0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
619
+        0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
620
+        0x5a36366c, 0x413f3f7e, 0x2f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551,
621
+        0x34e5e5d1, 0x8f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
622
+        0xc040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637,
623
+        0xf05050a, 0xb59a9a2f, 0x907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
624
+        0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d,
625
+        0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
626
+        0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd,
627
+        0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x0, 0x2cededc1,
628
+        0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
629
+        0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
630
+        0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a,
631
+        0x55333366, 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x6020204, 0x817f7ffe,
632
+        0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d,
633
+        0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x4f5f5f1,
634
+        0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5,
635
+        0xef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
636
+        0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755,
637
+        0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
638
+        0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
639
+        0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
640
+        0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264,
641
+        0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0xa06060c, 0x6c242448, 0xe45c5cb8,
642
+        0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531,
643
+        0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
644
+        0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac,
645
+        0x7f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
646
+        0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657,
647
+        0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
648
+        0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
649
+        0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x5030306, 0x1f6f6f7, 0x120e0e1c,
650
+        0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199,
651
+        0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
652
+        0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c,
653
+        0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
654
+        0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7,
655
+        0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
656
+        0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c
657
+    ];
658
+    AES.rtable = [
659
+        0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f,
660
+        0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5,
661
+        0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, 0x495ab1de, 0x671bba25,
662
+        0x980eea45, 0xe1c0fe5d, 0x2752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b,
663
+        0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
664
+        0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927,
665
+        0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5,
666
+        0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9,
667
+        0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72,
668
+        0x578f1fe3, 0x2aab5566, 0x728ebb2, 0x3c2b52f, 0x9a7bc586, 0xa50837d3,
669
+        0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7,
670
+        0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4,
671
+        0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040,
672
+        0x69f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d,
673
+        0xb58d5491, 0x55dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
674
+        0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879,
675
+        0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x0, 0x83868009, 0x48ed2b32,
676
+        0xac70111e, 0x4e725a6c, 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36,
677
+        0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0xfe75793,
678
+        0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
679
+        0xaba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0xb0d090e, 0xadc78bf2,
680
+        0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3,
681
+        0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b, 0xdcc623cb,
682
+        0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684,
683
+        0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
684
+        0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947,
685
+        0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, 0xc74e4987, 0xc1d138d9,
686
+        0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f,
687
+        0xe49d3a2c, 0xd927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890,
688
+        0x5ef7392e, 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
689
+        0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x97826cd, 0xf418596e,
690
+        0x1b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x8cfbc21, 0xe6e815ef,
691
+        0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431, 0x31233f2a,
692
+        0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733,
693
+        0x4a9804f1, 0xf7daec41, 0xe50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
694
+        0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546,
695
+        0x4ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92,
696
+        0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb,
697
+        0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255,
698
+        0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
699
+        0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0xc25e2bc,
700
+        0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664,
701
+        0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0
702
+    ];
703
+
704
+    return AES;
705
+};
706
+
707
+if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
708
+    module.exports.AES = AES;
709
+}

File diff suppressed because it is too large
+ 1521 - 0
elgamal/milagro-js/big.js


+ 454 - 0
elgamal/milagro-js/ctx.js

@@ -0,0 +1,454 @@
1
+/*
2
+    Licensed to the Apache Software Foundation (ASF) under one
3
+    or more contributor license agreements.  See the NOTICE file
4
+    distributed with this work for additional information
5
+    regarding copyright ownership.  The ASF licenses this file
6
+    to you under the Apache License, Version 2.0 (the
7
+    "License"); you may not use this file except in compliance
8
+    with the License.  You may obtain a copy of the License at
9
+
10
+    http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+    Unless required by applicable law or agreed to in writing,
13
+    software distributed under the License is distributed on an
14
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+    KIND, either express or implied.  See the License for the
16
+    specific language governing permissions and limitations
17
+    under the License.
18
+*/
19
+
20
+
21
+var CTX = function(input_parameter) {
22
+    "use strict";
23
+
24
+    var ctx = this,
25
+        CTXLIST,
26
+        prepareModule;
27
+
28
+    CTXLIST = {
29
+        "ED25519": {
30
+            "BITS": "256",
31
+            "FIELD": "25519",
32
+            "CURVE": "ED25519",
33
+            "@NB": 32,
34
+            "@BASE": 24,
35
+            "@NBT": 255,
36
+            "@M8": 5,
37
+            "@MT": 1,
38
+            "@CT": 1,
39
+            "@PF": 0,
40
+            "@ST": 0,
41
+            "@SX": 0
42
+        },
43
+
44
+        "C25519": {
45
+            "BITS": "256",
46
+            "FIELD": "25519",
47
+            "CURVE": "C25519",
48
+            "@NB": 32,
49
+            "@BASE": 24,
50
+            "@NBT": 255,
51
+            "@M8": 5,
52
+            "@MT": 1,
53
+            "@CT": 2,
54
+            "@PF": 0,
55
+            "@ST": 0,
56
+            "@SX": 0
57
+        },
58
+
59
+        "NIST256": {
60
+            "BITS": "256",
61
+            "FIELD": "NIST256",
62
+            "CURVE": "NIST256",
63
+            "@NB": 32,
64
+            "@BASE": 24,
65
+            "@NBT": 256,
66
+            "@M8": 7,
67
+            "@MT": 0,
68
+            "@CT": 0,
69
+            "@PF": 0,
70
+            "@ST": 0,
71
+            "@SX": 0
72
+        },
73
+
74
+        "NIST384": {
75
+            "BITS": "384",
76
+            "FIELD": "NIST384",
77
+            "CURVE": "NIST384",
78
+            "@NB": 48,
79
+            "@BASE": 23,
80
+            "@NBT": 384,
81
+            "@M8": 7,
82
+            "@MT": 0,
83
+            "@CT": 0,
84
+            "@PF": 0,
85
+            "@ST": 0,
86
+            "@SX": 0
87
+        },
88
+
89
+        "BRAINPOOL": {
90
+            "BITS": "256",
91
+            "FIELD": "BRAINPOOL",
92
+            "CURVE": "BRAINPOOL",
93
+            "@NB": 32,
94
+            "@BASE": 24,
95
+            "@NBT": 256,
96
+            "@M8": 7,
97
+            "@MT": 0,
98
+            "@CT": 0,
99
+            "@PF": 0,
100
+            "@ST": 0,
101
+            "@SX": 0
102
+        },
103
+
104
+        "ANSSI": {
105
+            "BITS": "256",
106
+            "FIELD": "ANSSI",
107
+            "CURVE": "ANSSI",
108
+            "@NB": 32,
109
+            "@BASE": 24,
110
+            "@NBT": 256,
111
+            "@M8": 7,
112
+            "@MT": 0,
113
+            "@CT": 0,
114
+            "@PF": 0,
115
+            "@ST": 0,
116
+            "@SX": 0
117
+        },
118
+
119
+        "HIFIVE": {
120
+            "BITS": "336",
121
+            "FIELD": "HIFIVE",
122
+            "CURVE": "HIFIVE",
123
+            "@NB": 42,
124
+            "@BASE": 23,
125
+            "@NBT": 336,
126
+            "@M8": 5,
127
+            "@MT": 1,
128
+            "@CT": 1,
129
+            "@PF": 0,
130
+            "@ST": 0,
131
+            "@SX": 0
132
+        },
133
+
134
+        "GOLDILOCKS": {
135
+            "BITS": "448",
136
+            "FIELD": "GOLDILOCKS",
137
+            "CURVE": "GOLDILOCKS",
138
+            "@NB": 56,
139
+            "@BASE": 23,
140
+            "@NBT": 448,
141
+            "@M8": 7,
142
+            "@MT": 2,
143
+            "@CT": 1,
144
+            "@PF": 0,
145
+            "@ST": 0,
146
+            "@SX": 0
147
+        },
148
+
149
+        "C41417": {
150
+            "BITS": "416",
151
+            "FIELD": "C41417",
152
+            "CURVE": "C41417",
153
+            "@NB": 52,
154
+            "@BASE": 22,
155
+            "@NBT": 414,
156
+            "@M8": 7,
157
+            "@MT": 1,
158
+            "@CT": 1,
159
+            "@PF": 0,
160
+            "@ST": 0,
161
+            "@SX": 0
162
+        },
163
+
164
+        "NIST521": {
165
+            "BITS": "528",
166
+            "FIELD": "NIST521",
167
+            "CURVE": "NIST521",
168
+            "@NB": 66,
169
+            "@BASE": 23,
170
+            "@NBT": 521,
171
+            "@M8": 7,
172
+            "@MT": 1,
173
+            "@CT": 0,
174
+            "@PF": 0,
175
+            "@ST": 0,
176
+            "@SX": 0
177
+        },
178
+
179
+        "NUMS256W": {
180
+            "BITS": "256",
181
+            "FIELD": "256PM",
182
+            "CURVE": "NUMS256W",
183
+            "@NB": 32,
184
+            "@BASE": 24,
185
+            "@NBT": 256,
186
+            "@M8": 3,
187
+            "@MT": 1,
188
+            "@CT": 0,
189
+            "@PF": 0,
190
+            "@ST": 0,
191
+            "@SX": 0
192
+        },
193
+
194
+        "NUMS256E": {
195
+            "BITS": "256",
196
+            "FIELD": "256PM",
197
+            "CURVE": "NUMS256E",
198
+            "@NB": 32,
199
+            "@BASE": 24,
200
+            "@NBT": 256,
201
+            "@M8": 3,
202
+            "@MT": 1,
203
+            "@CT": 1,
204
+            "@PF": 0,
205
+            "@ST": 0,
206
+            "@SX": 0
207
+        },
208
+
209
+        "NUMS384W": {
210
+            "BITS": "384",
211
+            "FIELD": "384PM",
212
+            "CURVE": "NUMS384W",
213
+            "@NB": 48,
214
+            "@BASE": 23,
215
+            "@NBT": 384,
216
+            "@M8": 3,
217
+            "@MT": 1,
218
+            "@CT": 0,
219
+            "@PF": 0,
220
+            "@ST": 0,
221
+            "@SX": 0
222
+        },
223
+
224
+        "NUMS384E": {
225
+            "BITS": "384",
226
+            "FIELD": "384PM",
227
+            "CURVE": "NUMS384E",
228
+            "@NB": 48,
229
+            "@BASE": 23,
230
+            "@NBT": 384,
231
+            "@M8": 3,
232
+            "@MT": 1,
233
+            "@CT": 1,
234
+            "@PF": 0,
235
+            "@ST": 0,
236
+            "@SX": 0
237
+        },
238
+
239
+        "NUMS512W": {
240
+            "BITS": "512",
241
+            "FIELD": "512PM",
242
+            "CURVE": "NUMS512W",
243
+            "@NB": 64,
244
+            "@BASE": 23,
245
+            "@NBT": 512,
246
+            "@M8": 7,
247
+            "@MT": 1,
248
+            "@CT": 0,
249
+            "@PF": 0,
250
+            "@ST": 0,
251
+            "@SX": 0
252
+        },
253
+
254
+        "NUMS512E": {
255
+            "BITS": "512",
256
+            "FIELD": "512PM",
257
+            "CURVE": "NUMS512E",
258
+            "@NB": 64,
259
+            "@BASE": 23,
260
+            "@NBT": 512,
261
+            "@M8": 7,
262
+            "@MT": 1,
263
+            "@CT": 1,
264
+            "@PF": 0,
265
+            "@ST": 0,
266
+            "@SX": 0
267
+        },
268
+
269
+        "FP256BN": {
270
+            "BITS": "256",
271
+            "FIELD": "FP256BN",
272
+            "CURVE": "FP256BN",
273
+            "@NB": 32,
274
+            "@BASE": 24,
275
+            "@NBT": 256,
276
+            "@M8": 3,
277
+            "@MT": 0,
278
+            "@CT": 0,
279
+            "@PF": 1,
280
+            "@ST": 1,
281
+            "@SX": 1
282
+        },
283
+
284
+        "FP512BN": {
285
+            "BITS": "512",
286
+            "FIELD": "FP512BN",
287
+            "CURVE": "FP512BN",
288
+            "@NB": 64,
289
+            "@BASE": 23,
290
+            "@NBT": 512,
291
+            "@M8": 3,
292
+            "@MT": 0,
293
+            "@CT": 0,
294
+            "@PF": 1,
295
+            "@ST": 1,
296
+            "@SX": 0
297
+        },
298
+
299
+        "BN254": {
300
+            "BITS": "256",
301
+            "FIELD": "BN254",
302
+            "CURVE": "BN254",
303
+            "@NB": 32,
304
+            "@BASE": 24,
305
+            "@NBT": 254,
306
+            "@M8": 3,
307
+            "@MT": 0,
308
+            "@CT": 0,
309
+            "@PF": 1,
310
+            "@ST": 0,
311
+            "@SX": 1
312
+        },
313
+
314
+        "BN254CX": {
315
+            "BITS": "256",
316
+            "FIELD": "BN254CX",
317
+            "CURVE": "BN254CX",
318
+            "@NB": 32,
319
+            "@BASE": 24,
320
+            "@NBT": 254,
321
+            "@M8": 3,
322
+            "@MT": 0,
323
+            "@CT": 0,
324
+            "@PF": 1,
325
+            "@ST": 0,
326
+            "@SX": 1
327
+        },
328
+
329
+        "BLS383": {
330
+            "BITS": "384",
331
+            "FIELD": "BLS383",
332
+            "CURVE": "BLS383",
333
+            "@NB": 48,
334
+            "@BASE": 23,
335
+            "@NBT": 383,
336
+            "@M8": 3,
337
+            "@MT": 0,
338
+            "@CT": 0,
339
+            "@PF": 2,
340
+            "@ST": 0,
341
+            "@SX": 0
342
+        },
343
+
344
+        "BLS461": {
345
+            "BITS": "464",
346
+            "FIELD": "BLS461",
347
+            "CURVE": "BLS461",
348
+            "@NB": 58,
349
+            "@BASE": 23,
350
+            "@NBT": 461,
351
+            "@M8": 3,
352
+            "@MT": 0,
353
+            "@CT": 0,
354
+            "@PF": 2,
355
+            "@ST": 1,
356
+            "@SX": 1
357
+        },
358
+
359
+        "RSA2048": {
360
+            "BITS": "1024",
361
+            "TFF": "2048",
362
+            "@NB": 128,
363
+            "@BASE": 22,
364
+            "@ML": 2,
365
+        },
366
+
367
+        "RSA3072": {
368
+            "BITS": "384",
369
+            "TFF": "3072",
370
+            "@NB": 48,
371
+            "@BASE": 23,
372
+            "@ML": 8,
373
+        },
374
+
375
+        "RSA4096": {
376
+            "BITS": "512",
377
+            "TFF": "4096",
378
+            "@NB": 64,
379
+            "@BASE": 23,
380
+            "@ML": 8,
381
+        },
382
+    };
383
+
384
+    prepareModule = function (moduleName, fileName, propertyName) {
385
+        if (!propertyName) {
386
+            propertyName = moduleName;
387
+        }
388
+
389
+        if (typeof require !== "undefined") {
390
+            if (!fileName) {
391
+                fileName = moduleName.toLowerCase();
392
+            }
393
+
394
+            ctx[propertyName] = require("./" + fileName)[moduleName](ctx);
395
+        } else {
396
+            ctx[propertyName] = window[moduleName](ctx);
397
+        }
398
+    };
399
+
400
+    prepareModule("AES");
401
+    prepareModule("GCM");
402
+    prepareModule("UInt64");
403
+    prepareModule("HASH256");
404
+    prepareModule("HASH384");
405
+    prepareModule("HASH512");
406
+    prepareModule("SHA3");
407
+    prepareModule("RAND");
408
+    prepareModule("NewHope");
409
+    prepareModule("NHS");
410
+
411
+    if (typeof input_parameter === "undefined") {
412
+        return;
413
+    }
414
+
415
+    ctx.config = CTXLIST[input_parameter];
416
+
417
+    prepareModule("BIG");
418
+    prepareModule("DBIG", "big");
419
+
420
+    // Set RSA parameters
421
+    if (typeof ctx.config["TFF"] !== "undefined") {
422
+        prepareModule("FF");
423
+        prepareModule("RSA");
424
+        prepareModule("rsa_public_key", "rsa");
425
+        prepareModule("rsa_private_key", "rsa");
426
+        return;
427
+    }
428
+
429
+    // Set Elliptic Curve parameters
430
+    if (typeof ctx.config["CURVE"] !== "undefined") {
431
+        prepareModule("ROM_CURVE_" + ctx.config["CURVE"], "rom_curve", "ROM_CURVE");
432
+        prepareModule("ROM_FIELD_" + ctx.config["FIELD"], "rom_field", "ROM_FIELD");
433
+
434
+        prepareModule("FP");
435
+        prepareModule("ECP");
436
+        prepareModule("ECDH");
437
+
438
+        if (ctx.config["@PF"] != 0) {
439
+            prepareModule("FP2");
440
+            prepareModule("FP4");
441
+            prepareModule("FP12");
442
+            prepareModule("ECP2");
443
+            prepareModule("PAIR");
444
+            prepareModule("MPIN");
445
+        }
446
+
447
+        return;
448
+    }
449
+
450
+};
451
+
452
+if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
453
+    module.exports = CTX;
454
+}

+ 807 - 0
elgamal/milagro-js/ecdh.js

@@ -0,0 +1,807 @@
1
+/*
2
+    Licensed to the Apache Software Foundation (ASF) under one
3
+    or more contributor license agreements.  See the NOTICE file
4
+    distributed with this work for additional information
5
+    regarding copyright ownership.  The ASF licenses this file
6
+    to you under the Apache License, Version 2.0 (the
7
+    "License"); you may not use this file except in compliance
8
+    with the License.  You may obtain a copy of the License at
9
+
10
+    http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+    Unless required by applicable law or agreed to in writing,
13
+    software distributed under the License is distributed on an
14
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+    KIND, either express or implied.  See the License for the
16
+    specific language governing permissions and limitations
17
+    under the License.
18
+*/
19
+
20
+var ECDH = function(ctx) {
21
+    "use strict";
22
+
23
+    var ECDH = {
24
+
25
+        INVALID_PUBLIC_KEY: -2,
26
+        ERROR: -3,
27
+        INVALID: -4,
28
+        EFS: ctx.BIG.MODBYTES,
29
+        EGS: ctx.BIG.MODBYTES,
30
+        EAS: 16,
31
+        EBS: 16,
32
+        SHA256: 32,
33
+        SHA384: 48,
34
+        SHA512: 64,
35
+
36
+        HASH_TYPE: 64,
37
+
38
+        /* Convert Integer to n-byte array */
39
+        inttobytes: function(n, len) {
40
+            var b = [],
41
+                i;
42
+
43
+            for (i = 0; i < len; i++) {
44
+                b[i] = 0;
45
+            }
46
+
47
+            i = len;
48
+            while (n > 0 && i > 0) {
49
+                i--;
50
+                b[i] = (n & 0xff);
51
+                n = Math.floor(n / 256);
52
+            }
53
+
54
+            return b;
55
+        },
56
+
57
+        bytestostring: function(b) {
58
+            var s = "",
59
+                len = b.length,
60
+                ch, i;
61
+
62
+            for (i = 0; i < len; i++) {
63
+                ch = b[i];
64
+                s += ((ch >>> 4) & 15).toString(16);
65
+                s += (ch & 15).toString(16);
66
+
67
+            }
68
+
69
+            return s;
70
+        },
71
+
72
+        stringtobytes: function(s) {
73
+            var b = [],
74
+                i;
75
+
76
+            for (i = 0; i < s.length; i++) {
77
+                b.push(s.charCodeAt(i));
78
+            }
79
+
80
+            return b;
81
+        },
82
+
83
+        hashit: function(sha, A, n, B, pad) {
84
+            var R = [],
85
+                H, W, i, len;
86
+
87
+            if (sha == this.SHA256) {
88
+                H = new ctx.HASH256();
89
+                H.process_array(A);
90
+
91
+                if (n > 0) {
92
+                    H.process_num(n);
93
+                }
94
+
95
+                if (B != null) {
96
+                    H.process_array(B);
97
+                }
98
+
99
+                R = H.hash();
100
+            } else if (sha == this.SHA384) {
101
+                H = new ctx.HASH384();
102
+                H.process_array(A);
103
+
104
+                if (n > 0) {
105
+                    H.process_num(n);
106
+                }
107
+
108
+                if (B != null) {
109
+                    H.process_array(B);
110
+                }
111
+
112
+                R = H.hash();
113
+            } else if (sha == this.SHA512) {
114
+                H = new ctx.HASH512();
115
+                H.process_array(A);
116
+
117
+                if (n > 0) {
118
+                    H.process_num(n);
119
+                }
120
+
121
+                if (B != null) {
122
+                    H.process_array(B);
123
+                }
124
+
125
+                R = H.hash();
126
+            }
127
+
128
+            if (R.length == 0) {
129
+                return null;
130
+            }
131
+
132
+            if (pad == 0) {
133
+                return R;
134
+            }
135
+
136
+            W = [];
137
+
138
+            len = ctx.BIG.MODBYTES;
139
+
140
+            if (sha >= len) {
141
+                for (i = 0; i < len; i++) {
142
+                    W[i] = R[i];
143
+                }
144
+            } else {
145
+                for (i = 0; i < sha; i++) {
146
+                    W[i + len - sha] = R[i];
147
+                }
148
+
149
+                for (i = 0; i < len - sha; i++) {
150
+                    W[i] = 0;
151
+                }
152
+            }
153
+
154
+            return W;
155
+        },
156
+
157
+        KDF1: function(sha, Z, olen) {
158
+            /* NOTE: the parameter olen is the length of the output K in bytes */
159
+            var hlen = sha,
160
+                K = [],
161
+                B = [],
162
+                k = 0,
163
+                counter, cthreshold, i;
164
+
165
+            for (i = 0; i < K.length; i++) {
166
+                K[i] = 0; // redundant?
167
+            }
168
+
169
+            cthreshold = Math.floor(olen / hlen);
170
+            if (olen % hlen !== 0) {
171
+                cthreshold++;
172
+            }
173
+
174
+            for (counter = 0; counter < cthreshold; counter++) {
175
+                B = this.hashit(sha, Z, counter, null, 0);
176
+
177
+                if (k + hlen > olen) {
178
+                    for (i = 0; i < olen % hlen; i++) {
179
+                        K[k++] = B[i];
180
+                    }
181
+                } else {
182
+                    for (i = 0; i < hlen; i++) {
183
+                        K[k++] = B[i];
184
+                    }
185
+                }
186
+            }
187
+
188
+            return K;
189
+        },
190
+
191
+        KDF2: function(sha, Z, P, olen) {
192
+            /* NOTE: the parameter olen is the length of the output k in bytes */
193
+            var hlen = sha,
194
+                K = [],
195
+                B = [],
196
+                k = 0,
197
+                counter, cthreshold, i;
198
+
199
+            for (i = 0; i < K.length; i++) {
200
+                K[i] = 0; // redundant?
201
+            }
202
+
203
+            cthreshold = Math.floor(olen / hlen);
204
+            if (olen % hlen !== 0) {
205
+                cthreshold++;
206
+            }
207
+
208
+            for (counter = 1; counter <= cthreshold; counter++) {
209
+                B = this.hashit(sha, Z, counter, P, 0);
210
+
211
+                if (k + hlen > olen) {
212
+                    for (i = 0; i < olen % hlen; i++) {
213
+                        K[k++] = B[i];
214
+                    }
215
+                } else {
216
+                    for (i = 0; i < hlen; i++) {
217
+                        K[k++] = B[i];
218
+                    }
219
+                }
220
+            }
221
+
222
+            return K;
223
+        },
224
+
225
+        /* Password based Key Derivation Function */
226
+        /* Input password p, salt s, and repeat count */
227
+        /* Output key of length olen */
228
+
229
+        PBKDF2: function(sha, Pass, Salt, rep, olen) {
230
+            var F = new Array(sha),
231
+                U = [],
232
+                S = [],
233
+                K = [],
234
+                opt = 0,
235
+                i, j, k, d, N, key;
236
+
237
+            d = Math.floor(olen / sha);
238
+
239
+            if (olen % sha !== 0) {
240
+                d++;
241
+            }
242
+
243
+            opt = 0;
244
+
245
+            for (i = 1; i <= d; i++) {
246
+                for (j = 0; j < Salt.length; j++) {
247
+                    S[j] = Salt[j];
248
+                }
249
+
250
+                N = this.inttobytes(i, 4);
251
+
252
+                for (j = 0; j < 4; j++) {
253
+                    S[Salt.length + j] = N[j];
254
+                }
255
+
256
+                this.HMAC(sha, S, Pass, F);
257
+
258
+                for (j = 0; j < sha; j++) {
259
+                    U[j] = F[j];
260
+                }
261
+
262
+                for (j = 2; j <= rep; j++) {
263
+                    this.HMAC(sha, U, Pass, U);
264
+                    for (k = 0; k < sha; k++) {
265
+                        F[k] ^= U[k];
266
+                    }
267
+                }
268
+
269
+                for (j = 0; j < sha; j++) {
270
+                    K[opt++] = F[j];
271
+                }
272
+            }
273
+
274
+            key = [];
275
+            for (i = 0; i < olen; i++) {
276
+                key[i] = K[i];
277
+            }
278
+
279
+            return key;
280
+        },
281
+
282
+        HMAC: function(sha, M, K, tag) {
283
+            /* Input is from an octet m        *
284
+             * olen is requested output length in bytes. k is the key  *
285
+             * The output is the calculated tag */
286
+            var olen = tag.length,
287
+                B = [],
288
+                b = 64,
289
+                K0, i;
290
+
291
+            if (sha > 32) {
292
+                b = 128;
293
+            }
294
+
295
+            K0 = new Array(b);
296
+
297
+            //b=K0.length;
298
+            if (olen < 4) {
299
+                return 0;
300
+            }
301
+
302
+            for (i = 0; i < b; i++) {
303
+                K0[i] = 0;
304
+            }
305
+
306
+            if (K.length > b) {
307
+                B = this.hashit(sha, K, 0, null, 0);
308
+                for (i = 0; i < sha; i++) {
309
+                    K0[i] = B[i];
310
+                }
311
+            } else {
312
+                for (i = 0; i < K.length; i++) {
313
+                    K0[i] = K[i];
314
+                }
315
+            }
316
+
317
+            for (i = 0; i < b; i++) {
318
+                K0[i] ^= 0x36;
319
+            }
320
+
321
+            B = this.hashit(sha, K0, 0, M, 0);
322
+
323
+            for (i = 0; i < b; i++) {
324
+                K0[i] ^= 0x6a;
325
+            }
326
+
327
+            B = this.hashit(sha, K0, 0, B, olen);
328
+
329
+            for (i = 0; i < olen; i++) {
330
+                tag[i] = B[i];
331
+            }
332
+
333
+            return 1;
334
+        },
335
+
336
+        /* ctx.AES encryption/decryption */
337
+
338
+        AES_CBC_IV0_ENCRYPT: function(K, M) { /* ctx.AES CBC encryption, with Null IV and key K */
339
+            /* Input is from an octet string M, output is to an octet string C */
340
+            /* Input is padded as necessary to make up a full final block */
341
+            var a = new ctx.AES(),
342
+                buff = [],
343
+                C = [],
344
+                fin, padlen, i, j, ipt, opt;
345
+            /*var clen=16+(Math.floor(M.length/16))*16;*/
346
+
347
+            a.init(ctx.AES.CBC, K.length, K, null);
348
+
349
+            ipt = opt = 0;
350
+            fin = false;
351
+
352
+            for (;;) {
353
+                for (i = 0; i < 16; i++) {
354
+                    if (ipt < M.length) {
355
+                        buff[i] = M[ipt++];
356
+                    } else {
357
+                        fin = true;
358
+                        break;
359
+                    }
360
+                }
361
+
362
+                if (fin) {
363
+                    break;
364
+                }
365
+
366
+                a.encrypt(buff);
367
+
368
+                for (i = 0; i < 16; i++) {
369
+                    C[opt++] = buff[i];
370
+                }
371
+            }
372
+
373
+            /* last block, filled up to i-th index */
374
+
375
+            padlen = 16 - i;
376
+            for (j = i; j < 16; j++) {
377
+                buff[j] = padlen;
378
+            }
379
+            a.encrypt(buff);
380
+            for (i = 0; i < 16; i++) {
381
+                C[opt++] = buff[i];
382
+            }
383
+            a.end();
384
+
385
+            return C;
386
+        },
387
+
388
+        AES_CBC_IV0_DECRYPT: function(K, C) { /* padding is removed */
389
+            var a = new ctx.AES(),
390
+                buff = [],
391
+                MM = [],
392
+                ipt = 0,
393
+                opt = 0,
394
+                M, ch, fin, bad, padlen, i;
395
+
396
+            a.init(ctx.AES.CBC, K.length, K, null);
397
+
398
+            if (C.length === 0) {
399
+                return [];
400
+            }
401
+            ch = C[ipt++];
402
+
403
+            fin = false;
404
+
405
+            for (;;) {
406
+                for (i = 0; i < 16; i++) {
407
+                    buff[i] = ch;
408
+                    if (ipt >= C.length) {
409
+                        fin = true;
410
+                        break;
411
+                    } else {
412
+                        ch = C[ipt++];
413
+                    }
414
+                }
415
+                a.decrypt(buff);
416
+                if (fin) {
417
+                    break;
418
+                }
419
+
420
+                for (i = 0; i < 16; i++) {
421
+                    MM[opt++] = buff[i];
422
+                }
423
+            }
424
+
425
+            a.end();
426
+            bad = false;
427
+            padlen = buff[15];
428
+
429
+            if (i != 15 || padlen < 1 || padlen > 16) {
430
+                bad = true;
431
+            }
432
+
433
+            if (padlen >= 2 && padlen <= 16) {
434
+                for (i = 16 - padlen; i < 16; i++) {
435
+                    if (buff[i] != padlen) {
436
+                        bad = true;
437
+                    }
438
+                }
439
+            }
440
+
441
+            if (!bad) {
442
+                for (i = 0; i < 16 - padlen; i++) {
443
+                    MM[opt++] = buff[i];
444
+                }
445
+            }
446
+
447
+            M = [];
448
+            if (bad) {
449
+                return M;
450
+            }
451
+
452
+            for (i = 0; i < opt; i++) {
453
+                M[i] = MM[i];
454
+            }
455
+
456
+            return M;
457
+        },
458
+
459
+        KEY_PAIR_GENERATE: function(RNG, S, W) {
460
+            var res = 0,
461
+                r, gx, gy, s,
462
+                G, WP;
463
+            //      var T=[];
464
+            G = new ctx.ECP(0);
465
+
466
+            gx = new ctx.BIG(0);
467
+            gx.rcopy(ctx.ROM_CURVE.CURVE_Gx);
468
+
469
+            if (ctx.ECP.CURVETYPE != ctx.ECP.MONTGOMERY) {
470
+                gy = new ctx.BIG(0);
471
+                gy.rcopy(ctx.ROM_CURVE.CURVE_Gy);
472
+                G.setxy(gx, gy);
473
+            } else {
474
+                G.setx(gx);
475
+            }
476
+
477
+            r = new ctx.BIG(0);
478
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
479
+
480
+            if (RNG === null) {
481
+                s = ctx.BIG.fromBytes(S);
482
+                s.mod(r);
483
+            } else {
484
+                s = ctx.BIG.randomnum(r, RNG);
485
+                // s.toBytes(T);
486
+                // for (var i=0;i<this.EGS;i++) S[i]=T[i];
487
+            }
488
+
489
+            //if (ROM.AES_S>0)
490
+            //{
491
+            //  s.mod2m(2*ROM.AES_S);
492
+            //}
493
+
494
+            s.toBytes(S);
495
+
496
+            WP = G.mul(s);
497
+            WP.toBytes(W);
498
+
499
+            return res;
500
+        },
501
+
502
+        PUBLIC_KEY_VALIDATE: function(W) {
503
+            var WP = ctx.ECP.fromBytes(W),
504
+                res = 0,
505
+                r, q, nb, k;
506
+
507
+            r = new ctx.BIG(0);
508
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
509
+
510
+            if (WP.is_infinity()) {
511
+                res = this.INVALID_PUBLIC_KEY;
512
+            }
513
+
514
+            if (res === 0) {
515
+                q = new ctx.BIG(0);
516
+                q.rcopy(ctx.ROM_FIELD.Modulus);
517
+                nb = q.nbits();
518
+                k = new ctx.BIG(1);
519
+                k.shl(Math.floor((nb + 4) / 2));
520
+                k.add(q);
521
+                k.div(r);
522
+
523
+                while (k.parity() == 0) {
524
+                    k.shr(1);
525
+                    WP.dbl();
526
+                }
527
+
528
+                if (!k.isunity()) {
529
+                    WP = WP.mul(k);
530
+                }
531
+
532
+                if (WP.is_infinity()) {
533
+                    res = this.INVALID_PUBLIC_KEY;
534
+                }
535
+            }
536
+
537
+            return res;
538
+        },
539
+
540
+        ECPSVDP_DH: function(S, WD, Z) {
541
+            var T = [],
542
+                res = 0,
543
+                r, s, i,
544
+                W;
545
+
546
+            s = ctx.BIG.fromBytes(S);
547
+
548
+            W = ctx.ECP.fromBytes(WD);
549
+            if (W.is_infinity()) {
550
+                res = this.ERROR;
551
+            }
552
+
553
+            if (res === 0) {
554
+                r = new ctx.BIG(0);
555
+                r.rcopy(ctx.ROM_CURVE.CURVE_Order);
556
+                s.mod(r);
557
+                W = W.mul(s);
558
+
559
+                if (W.is_infinity()) {
560
+                    res = this.ERROR;
561
+                } else {
562
+                    W.getX().toBytes(T);
563
+                    for (i = 0; i < this.EFS; i++) {
564
+                        Z[i] = T[i];
565
+                    }
566
+                }
567
+            }
568
+
569
+            return res;
570
+        },
571
+
572
+        ECPSP_DSA: function(sha, RNG, S, F, C, D) {
573
+            var T = [],
574
+                i, gx, gy, r, s, f, c, d, u, vx, w,
575
+                G, V, B;
576
+
577
+            B = this.hashit(sha, F, 0, null, ctx.BIG.MODBYTES);
578
+
579
+            gx = new ctx.BIG(0);
580
+            gx.rcopy(ctx.ROM_CURVE.CURVE_Gx);
581
+            gy = new ctx.BIG(0);
582
+            gy.rcopy(ctx.ROM_CURVE.CURVE_Gy);
583
+
584
+            G = new ctx.ECP(0);
585
+            G.setxy(gx, gy);
586
+            r = new ctx.BIG(0);
587
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
588
+
589
+            s = ctx.BIG.fromBytes(S);
590
+            f = ctx.BIG.fromBytes(B);
591
+
592
+            c = new ctx.BIG(0);
593
+            d = new ctx.BIG(0);
594
+            V = new ctx.ECP();
595
+
596
+            do {
597
+                u = ctx.BIG.randomnum(r, RNG);
598
+                w = ctx.BIG.randomnum(r, RNG);
599
+                //if (ROM.AES_S>0)
600
+                //{
601
+                //  u.mod2m(2*ROM.AES_S);
602
+                //}
603
+                V.copy(G);
604
+                V = V.mul(u);
605
+                vx = V.getX();
606
+                c.copy(vx);
607
+                c.mod(r);
608
+                if (c.iszilch()) {
609
+                    continue;
610
+                }
611
+                u = ctx.BIG.modmul(u, w, r);
612
+                u.invmodp(r);
613
+                d = ctx.BIG.modmul(s, c, r);
614
+                d.add(f);
615
+                d = ctx.BIG.modmul(d, w, r);
616
+                d = ctx.BIG.modmul(u, d, r);
617
+            } while (d.iszilch());
618
+
619
+            c.toBytes(T);
620
+            for (i = 0; i < this.EFS; i++) {
621
+                C[i] = T[i];
622
+            }
623
+            d.toBytes(T);
624
+            for (i = 0; i < this.EFS; i++) {
625
+                D[i] = T[i];
626
+            }
627
+
628
+            return 0;
629
+        },
630
+
631
+        ECPVP_DSA: function(sha, W, F, C, D) {
632
+            var B = [],
633
+                res = 0,
634
+                r, gx, gy, f, c, d, h2,
635
+                G, WP, P;
636
+
637
+            B = this.hashit(sha, F, 0, null, ctx.BIG.MODBYTES);
638
+
639
+            gx = new ctx.BIG(0);
640
+            gx.rcopy(ctx.ROM_CURVE.CURVE_Gx);
641
+            gy = new ctx.BIG(0);
642
+            gy.rcopy(ctx.ROM_CURVE.CURVE_Gy);
643
+
644
+            G = new ctx.ECP(0);
645
+            G.setxy(gx, gy);
646
+            r = new ctx.BIG(0);
647
+            r.rcopy(ctx.ROM_CURVE.CURVE_Order);
648
+
649
+            c = ctx.BIG.fromBytes(C);
650
+            d = ctx.BIG.fromBytes(D);
651
+            f = ctx.BIG.fromBytes(B);
652
+
653
+            if (c.iszilch() || ctx.BIG.comp(c, r) >= 0 || d.iszilch() || ctx.BIG.comp(d, r) >= 0) {
654
+                res = this.INVALID;
655
+            }
656
+
657
+            if (res === 0) {
658
+                d.invmodp(r);
659
+                f = ctx.BIG.modmul(f, d, r);
660
+                h2 = ctx.BIG.modmul(c, d, r);
661
+
662
+                WP = ctx.ECP.fromBytes(W);
663
+                if (WP.is_infinity()) {
664
+                    res = this.ERROR;
665
+                } else {
666
+                    P = new ctx.ECP();
667
+                    P.copy(WP);
668
+                    P = P.mul2(h2, G, f);
669
+
670
+                    if (P.is_infinity()) {
671
+                        res = this.INVALID;
672
+                    } else {
673
+                        d = P.getX();
674
+                        d.mod(r);
675
+                        if (ctx.BIG.comp(d, c) !== 0) {
676
+                            res = this.INVALID;
677
+                        }
678
+                    }
679
+                }
680
+            }
681
+
682
+            return res;
683
+        },
684
+
685
+        ECIES_ENCRYPT: function(sha, P1, P2, RNG, W, M, V, T) {
686
+            var Z = [],
687
+                VZ = [],
688
+                K1 = [],
689
+                K2 = [],
690
+                U = [],
691
+                C = [],
692
+                K, L2, AC, i;
693
+
694
+            if (this.KEY_PAIR_GENERATE(RNG, U, V) !== 0) {
695
+                return C;
696
+            }
697
+
698
+            if (this.ECPSVDP_DH(U, W, Z) !== 0) {
699
+                return C;
700
+            }
701
+
702
+            for (i = 0; i < 2 * this.EFS + 1; i++) {
703
+                VZ[i] = V[i];
704
+            }
705
+
706
+            for (i = 0; i < this.EFS; i++) {
707
+                VZ[2 * this.EFS + 1 + i] = Z[i];
708
+            }
709
+
710
+            K = this.KDF2(sha, VZ, P1, this.EFS);
711
+
712
+            for (i = 0; i < this.EAS; i++) {
713
+                K1[i] = K[i];
714
+                K2[i] = K[this.EAS + i];
715
+            }
716
+
717
+            C = this.AES_CBC_IV0_ENCRYPT(K1, M);
718
+
719
+            L2 = this.inttobytes(P2.length, 8);
720
+
721
+            AC = [];
722
+            for (i = 0; i < C.length; i++) {
723
+                AC[i] = C[i];
724
+            }
725
+            for (i = 0; i < P2.length; i++) {
726
+                AC[C.length + i] = P2[i];
727
+            }
728
+            for (i = 0; i < 8; i++) {
729
+                AC[C.length + P2.length + i] = L2[i];
730
+            }
731
+
732
+            this.HMAC(sha, AC, K2, T);
733
+
734
+            return C;
735
+        },
736
+
737
+        ECIES_DECRYPT: function(sha, P1, P2, V, C, T, U) {
738
+            var Z = [],
739
+                VZ = [],
740
+                K1 = [],
741
+                K2 = [],
742
+                TAG = new Array(T.length),
743
+                M = [],
744
+                K, L2, AC, same, i;
745
+
746
+            if (this.ECPSVDP_DH(U, V, Z) !== 0) {
747
+                return M;
748
+            }
749
+
750
+            for (i = 0; i < 2 * this.EFS + 1; i++) {
751
+                VZ[i] = V[i];
752
+            }
753
+
754
+            for (i = 0; i < this.EFS; i++) {
755
+                VZ[2 * this.EFS + 1 + i] = Z[i];
756
+            }
757
+
758
+            K = this.KDF2(sha, VZ, P1, this.EFS);
759
+
760
+            for (i = 0; i < this.EAS; i++) {
761
+                K1[i] = K[i];
762
+                K2[i] = K[this.EAS + i];
763
+            }
764
+
765
+            M = this.AES_CBC_IV0_DECRYPT(K1, C);
766
+
767
+            if (M.length === 0) {
768
+                return M;
769
+            }
770
+
771
+            L2 = this.inttobytes(P2.length, 8);
772
+
773
+            AC = [];
774
+
775
+            for (i = 0; i < C.length; i++) {
776
+                AC[i] = C[i];
777
+            }
778
+            for (i = 0; i < P2.length; i++) {
779
+                AC[C.length + i] = P2[i];
780
+            }
781
+            for (i = 0; i < 8; i++) {
782
+                AC[C.length + P2.length + i] = L2[i];
783
+            }
784
+
785
+            this.HMAC(sha, AC, K2, TAG);
786
+
787
+            same = true;
788
+            for (i = 0; i < T.length; i++) {
789
+                if (T[i] != TAG[i]) {
790
+                    same = false;
791
+                }
792
+            }
793
+
794
+            if (!same) {
795
+                return [];
796
+            }
797
+
798
+            return M;
799
+        }
800
+    };
801
+
802
+    return ECDH;
803
+};
804
+
805
+if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
806
+    module.exports.ECDH = ECDH;
807
+}

File diff suppressed because it is too large
+ 1325 - 0
elgamal/milagro-js/ecp.js


+ 823 - 0
elgamal/milagro-js/ecp2.js

@@ -0,0 +1,823 @@
1
+/*
2
+    Licensed to the Apache Software Foundation (ASF) under one
3
+    or more contributor license agreements.  See the NOTICE file
4
+    distributed with this work for additional information
5
+    regarding copyright ownership.  The ASF licenses this file
6
+    to you under the Apache License, Version 2.0 (the
7
+    "License"); you may not use this file except in compliance
8
+    with the License.  You may obtain a copy of the License at
9
+
10
+    http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+    Unless required by applicable law or agreed to in writing,
13
+    software distributed under the License is distributed on an
14
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+    KIND, either express or implied.  See the License for the
16
+    specific language governing permissions and limitations
17
+    under the License.
18
+*/
19
+
20
+/* AMCL Weierstrass elliptic curve functions over ctx.FP2 */
21
+
22
+var ECP2 = function(ctx) {
23
+    "use strict";
24
+
25
+    /* Constructor, set this=O */
26
+    var ECP2 = function() {
27
+        this.x = new ctx.FP2(0);
28
+        this.y = new ctx.FP2(1);
29
+        this.z = new ctx.FP2(0);
30
+        this.INF = true;
31
+    };
32
+
33
+    ECP2.prototype = {
34
+        /* Test this=O? */
35
+        is_infinity: function() {
36
+            if (this.INF) {
37
+                return true;
38
+            }
39
+
40
+            this.x.reduce();
41
+            this.y.reduce();
42
+            this.z.reduce();
43
+            this.INF = (this.x.iszilch() && this.z.iszilch());
44
+
45
+            return this.INF;
46
+        },
47
+
48
+        /* copy this=P */
49
+        copy: function(P) {
50
+            this.x.copy(P.x);
51
+            this.y.copy(P.y);
52
+            this.z.copy(P.z);
53
+            this.INF = P.INF;
54
+        },
55
+
56
+        /* set this=O */
57
+        inf: function() {
58
+            this.INF = true;
59
+            this.x.zero();
60
+            this.y.one();
61
+            this.z.zero();
62
+        },
63
+
64
+        /* conditional move of Q to P dependant on d */
65
+        cmove: function(Q, d) {
66
+            var bd;
67
+
68
+            this.x.cmove(Q.x, d);
69
+            this.y.cmove(Q.y, d);
70
+            this.z.cmove(Q.z, d);
71
+
72
+            bd = (d !== 0) ? true : false;
73
+            this.INF ^= (this.INF ^ Q.INF) & bd;
74
+        },
75
+
76
+        /* Constant time select from pre-computed table */
77
+        select: function(W, b) {
78
+            var MP = new ECP2(),
79
+                m = b >> 31,
80
+                babs = (b ^ m) - m;
81
+
82
+            babs = (babs - 1) / 2;
83
+
84
+            this.cmove(W[0], ECP2.teq(babs, 0)); // conditional move
85
+            this.cmove(W[1], ECP2.teq(babs, 1));
86
+            this.cmove(W[2], ECP2.teq(babs, 2));
87
+            this.cmove(W[3], ECP2.teq(babs, 3));
88
+            this.cmove(W[4], ECP2.teq(babs, 4));
89
+            this.cmove(W[5], ECP2.teq(babs, 5));
90
+            this.cmove(W[6], ECP2.teq(babs, 6));
91
+            this.cmove(W[7], ECP2.teq(babs, 7));
92
+
93
+            MP.copy(this);
94
+            MP.neg();
95
+            this.cmove(MP, (m & 1));
96
+        },
97
+
98
+        /* Test P == Q */
99
+        equals: function(Q) {
100
+            var a, b;
101
+
102
+            if (this.is_infinity() && Q.is_infinity()) {
103
+                return true;
104
+            }
105
+
106
+            if (this.is_infinity() || Q.is_infinity()) {
107
+                return false;
108
+            }
109
+
110
+            a = new ctx.FP2(0);
111
+            a.copy(this.x);
112
+            b = new ctx.FP2(0);
113
+            b.copy(Q.x);
114
+
115
+            a.copy(this.x);
116
+            a.mul(Q.z);
117
+            a.reduce();
118
+            b.copy(Q.x);
119
+            b.mul(this.z);
120
+            b.reduce();
121
+            if (!a.equals(b)) {
122
+                return false;
123
+            }
124
+
125
+            a.copy(this.y);
126
+            a.mul(Q.z);
127
+            a.reduce();
128
+            b.copy(Q.y);
129
+            b.mul(this.z);
130
+            b.reduce();
131
+            if (!a.equals(b)) {
132
+                return false;
133
+            }
134
+
135
+            return true;
136
+        },
137
+
138
+        /* set this=-this */
139
+        neg: function() {
140
+            //      if (this.is_infinity()) return;
141
+            this.y.norm();
142
+            this.y.neg();
143
+            this.y.norm();
144
+            return;
145
+        },
146
+
147
+        /* convert this to affine, from (x,y,z) to (x,y) */
148
+        affine: function() {
149
+            var one;
150
+
151
+            if (this.is_infinity()) {
152
+                return;
153
+            }
154
+
155
+            one = new ctx.FP2(1);
156
+
157
+            if (this.z.equals(one)) {
158
+                this.x.reduce();
159
+                this.y.reduce();
160
+                return;
161
+            }
162
+
163
+            this.z.inverse();
164
+
165
+            this.x.mul(this.z);
166
+            this.x.reduce();
167
+            this.y.mul(this.z);
168
+            this.y.reduce();
169
+            this.z.copy(one);
170
+        },
171
+
172
+        /* extract affine x as ctx.FP2 */
173
+        getX: function() {
174
+            this.affine();
175
+            return this.x;
176
+        },
177
+
178
+        /* extract affine y as ctx.FP2 */
179
+        getY: function() {
180
+            this.affine();
181
+            return this.y;
182
+        },
183
+
184
+        /* extract projective x */
185
+        getx: function() {
186
+            return this.x;
187
+        },
188
+
189
+        /* extract projective y */
190
+        gety: function() {
191
+            return this.y;
192
+        },
193
+
194
+        /* extract projective z */
195
+        getz: function() {
196
+            return this.z;
197
+        },
198
+
199
+        /* convert this to byte array */
200
+        toBytes: function(b) {
201
+            var t = [],
202
+                i;
203
+
204
+            this.affine();
205
+            this.x.getA().toBytes(t);
206
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
207
+                b[i] = t[i];
208
+            }
209
+            this.x.getB().toBytes(t);
210
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
211
+                b[i + ctx.BIG.MODBYTES] = t[i];
212
+            }
213
+
214
+            this.y.getA().toBytes(t);
215
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
216
+                b[i + 2 * ctx.BIG.MODBYTES] = t[i];
217
+            }
218
+            this.y.getB().toBytes(t);
219
+            for (i = 0; i < ctx.BIG.MODBYTES; i++) {
220
+                b[i + 3 * ctx.BIG.MODBYTES] = t[i];
221
+            }
222
+        },
223
+
224
+        /* convert this to hex string */
225
+        toString: function() {
226
+            if (this.is_infinity()) {
227
+                return "infinity";
228
+            }
229
+            this.affine();
230
+            return "(" + this.x.toString() + "," + this.y.toString() + ")";
231
+        },
232
+
233
+        /* set this=(x,y) */
234
+        setxy: function(ix, iy) {
235
+            var rhs, y2;
236
+
237
+            this.x.copy(ix);
238
+            this.y.copy(iy);
239
+            this.z.one();
240
+
241
+            rhs = ECP2.RHS(this.x);
242
+
243
+            y2 = new ctx.FP2(this.y); //y2.copy(this.y);
244
+            y2.sqr();
245
+
246
+            if (y2.equals(rhs)) {
247
+                this.INF = false;
248
+            } else {
249
+                this.inf();
250
+            }
251
+        },
252
+
253
+        /* set this=(x,.) */
254
+        setx: function(ix) {
255
+            var rhs;
256
+
257
+            this.x.copy(ix);
258
+            this.z.one();
259
+
260
+            rhs = ECP2.RHS(this.x);
261
+
262
+            if (rhs.sqrt()) {
263
+                this.y.copy(rhs);
264
+                this.INF = false;
265
+            } else {
266
+                this.inf();
267
+            }
268
+        },
269
+
270
+        /* set this*=q, where q is Modulus, using Frobenius */
271
+        frob: function(X) {
272
+            var X2;
273
+
274
+            if (this.INF) {
275
+                return;
276
+            }
277
+
278
+            X2 = new ctx.FP2(X); //X2.copy(X);
279
+            X2.sqr();
280
+            this.x.conj();
281
+            this.y.conj();
282
+            this.z.conj();
283
+            this.z.reduce();
284
+            this.x.mul(X2);
285
+            this.y.mul(X2);
286
+            this.y.mul(X);
287
+        },
288
+
289
+        /* this+=this */
290
+        dbl: function() {
291
+            var iy, t0, t1, t2, x3, y3;
292
+
293
+            if (this.INF) {
294
+                return -1;
295
+            }
296
+
297
+            iy = new ctx.FP2(0);
298
+            iy.copy(this.y); //FP2 iy=new FP2(y);
299
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
300
+                iy.mul_ip();
301
+                iy.norm();
302
+            }
303
+
304
+            t0 = new ctx.FP2(0);
305
+            t0.copy(this.y); //FP2 t0=new FP2(y);                  //***** Change
306
+            t0.sqr();
307
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
308
+                t0.mul_ip();
309
+            }
310
+            t1 = new ctx.FP2(0);
311
+            t1.copy(iy); //FP2 t1=new FP2(iy);
312
+            t1.mul(this.z);
313
+            t2 = new ctx.FP2(0);
314
+            t2.copy(this.z); //FP2 t2=new FP2(z);
315
+            t2.sqr();
316
+
317
+            this.z.copy(t0);
318
+            this.z.add(t0);
319
+            this.z.norm();
320
+            this.z.add(this.z);
321
+            this.z.add(this.z);
322
+            this.z.norm();
323
+
324
+            t2.imul(3 * ctx.ROM_CURVE.CURVE_B_I);
325
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.M_TYPE) {
326
+                t2.mul_ip();
327
+                t2.norm();
328
+            }
329
+
330
+            x3 = new ctx.FP2(0);
331
+            x3.copy(t2); //FP2 x3=new FP2(t2);
332
+            x3.mul(this.z);
333
+
334
+            y3 = new ctx.FP2(0);
335
+            y3.copy(t0); //FP2 y3=new FP2(t0);
336
+
337
+            y3.add(t2);
338
+            y3.norm();
339
+            this.z.mul(t1);
340
+            t1.copy(t2);
341
+            t1.add(t2);
342
+            t2.add(t1);
343
+            t2.norm();
344
+            t0.sub(t2);
345
+            t0.norm(); //y^2-9bz^2
346
+            y3.mul(t0);
347
+            y3.add(x3); //(y^2+3z*2)(y^2-9z^2)+3b.z^2.8y^2
348
+            t1.copy(this.x);
349
+            t1.mul(iy); //
350
+            this.x.copy(t0);
351
+            this.x.norm();
352
+            this.x.mul(t1);
353
+            this.x.add(this.x); //(y^2-9bz^2)xy2
354
+
355
+            this.x.norm();
356
+            this.y.copy(y3);
357
+            this.y.norm();
358
+
359
+            return 1;
360
+        },
361
+
362
+        /* this+=Q - return 0 for add, 1 for double, -1 for O */
363
+        /* this+=Q */
364
+        add: function(Q) {
365
+            var b, t0, t1, t2, t3, t4, x3, y3, z3;
366
+
367
+            if (this.INF) {
368
+                this.copy(Q);
369
+                return -1;
370
+            }
371
+
372
+            if (Q.INF) {
373
+                return -1;
374
+            }
375
+
376
+            b = 3 * ctx.ROM_CURVE.CURVE_B_I;
377
+            t0 = new ctx.FP2(0);
378
+            t0.copy(this.x); //FP2 t0=new FP2(x);
379
+            t0.mul(Q.x); // x.Q.x
380
+            t1 = new ctx.FP2(0);
381
+            t1.copy(this.y); //FP2 t1=new FP2(y);
382
+            t1.mul(Q.y); // y.Q.y
383
+
384
+            t2 = new ctx.FP2(0);
385
+            t2.copy(this.z); //FP2 t2=new FP2(z);
386
+            t2.mul(Q.z);
387
+            t3 = new ctx.FP2(0);
388
+            t3.copy(this.x); //FP2 t3=new FP2(x);
389
+            t3.add(this.y);
390
+            t3.norm(); //t3=X1+Y1
391
+            t4 = new ctx.FP2(0);
392
+            t4.copy(Q.x); //FP2 t4=new FP2(Q.x);
393
+            t4.add(Q.y);
394
+            t4.norm(); //t4=X2+Y2
395
+            t3.mul(t4); //t3=(X1+Y1)(X2+Y2)
396
+            t4.copy(t0);
397
+            t4.add(t1); //t4=X1.X2+Y1.Y2
398
+
399
+            t3.sub(t4);
400
+            t3.norm();
401
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
402
+                t3.mul_ip();
403
+                t3.norm(); //t3=(X1+Y1)(X2+Y2)-(X1.X2+Y1.Y2) = X1.Y2+X2.Y1
404
+            }
405
+
406
+            t4.copy(this.y);
407
+            t4.add(this.z);
408
+            t4.norm(); //t4=Y1+Z1
409
+            x3 = new ctx.FP2(0);
410
+            x3.copy(Q.y); //FP2 x3=new FP2(Q.y);
411
+            x3.add(Q.z);
412
+            x3.norm(); //x3=Y2+Z2
413
+
414
+            t4.mul(x3); //t4=(Y1+Z1)(Y2+Z2)
415
+            x3.copy(t1); //
416
+            x3.add(t2); //X3=Y1.Y2+Z1.Z2
417
+
418
+            t4.sub(x3);
419
+            t4.norm();
420
+            if (ctx.ECP.SEXTIC_TWIST == ctx.ECP.D_TYPE) {
421
+                t4.mul_ip();
422
+                t4.norm(); //t4=(Y1+Z1)(Y2+Z2) - (Y1.Y2+Z1.Z2) = Y1.Z2+Y2.Z1
423
+            }
424
+
425
+            x3.copy(this.x);
426
+            x3.add(this.z);
427
+            x3.norm(); // x3=X1+Z1
428
+            y3 = new ctx.FP2(0);
429
+            y3.copy(Q.x); //FP2 y3=new FP2(Q.x);
430
+            y3.add(Q.z);
431
+            y3.norm(); // y3=X2+Z2
432
+            x3.mul(y3); // x3=(X1+Z1)(X2+Z2)
433
+            y3.copy(t0);
434
+            y3.add(t2); // y3=X1.X2+Z1+Z2
435
+            y3.rsub(x3);
436
+            y3.norm(); // y3=(X1+Z1)(X2+Z2) - (X1.X2+Z1.Z2) = X1.Z2+X2.Z1
437
+