Created
November 17, 2015 09:21
-
-
Save rumkin/7d95a84c33ed0bc3a783 to your computer and use it in GitHub Desktop.
VanillaJS Curve25519 implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Snarfed from http://savannah.gnu.org/task/?6432 | |
// Ostensibly Copyright (c) 2007 Michele Bini, GPL | |
var c255lbase32chars = "abcdefghijklmnopqrstuvwxyz234567"; | |
var c255lbase32values = {"a":0, "b":1, "c":2, "d":3, "e":4, "f":5, "g":6, "h":7, "i":8, "j":9, "k":10, "l":11, "m":12, "n":13, "o":14, "p":15, "q":16, "r":17, "s":18, "t":19, "u":20, "v":21, "w":22, "x":23, "y":24, "z":25, "2":26, "3":27, "4":28, "5":29, "6":30, "7":31 }; | |
function c255lbase32encode(n, x) { | |
var c; | |
var r = ""; | |
for (c = 0; c < 255; c+=5) { | |
r = c255lbase32chars.substr(c255lgetbit(n, c) + c255lgetbit(n, c+1)*2 + c255lgetbit(n, c+2)*4 + c255lgetbit(n, c+3)*8 + c255lgetbit(n, c+4)*16, 1) + r; | |
} | |
return r; | |
} | |
function c255lbase32decode(n, x) { | |
var c = 0; | |
var r = c255lzero(); | |
var l = n.length; | |
for (c = 0; (l > 0) && (c < 255); c+=5) { | |
l--; | |
var v = c255lbase32values[n.substr(l, 1)]; | |
if (v%2 == 1) { c255lsetbit(r, c); }; v = v >> 1; | |
if (v%2 == 1) { c255lsetbit(r, c+1, v%2); }; v = v >> 1; | |
if (v%2 == 1) { c255lsetbit(r, c+2, v%2); }; v = v >> 1; | |
if (v%2 == 1) { c255lsetbit(r, c+3, v%2); }; v = v >> 1; | |
if (v%2 == 1) { c255lsetbit(r, c+4, v); }; | |
} | |
return r; | |
} | |
var c255lhexchars = "0123456789abcdef"; | |
var c255lhexvalues = {"0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9, "a":10, "b":11, "c":12, "d":13, "e":14, "f":15 }; | |
function c255lhexencode(n, x) { | |
var c; | |
var r = ""; | |
for (c = 0; c < 255; c+=4) { | |
r = c255lhexchars.substr(c255lgetbit(n, c) + c255lgetbit(n, c+1)*2 + c255lgetbit(n, c+2)*4 + c255lgetbit(n, c+3)*8, 1) + r; | |
} | |
return r; | |
} | |
function c255lhexdecode(n, x) { | |
var c = 0; | |
var r = c255lzero(); | |
var l = n.length; | |
for (c = 0; (l > 0) && (c < 255); c+=4) { | |
l--; | |
var v = c255lhexvalues[n.substr(l, 1)]; | |
if (v%2 == 1) { c255lsetbit(r, c); }; v = v >> 1; | |
if (v%2 == 1) { c255lsetbit(r, c+1, v%2); }; v = v >> 1; | |
if (v%2 == 1) { c255lsetbit(r, c+2, v%2); }; v = v >> 1; | |
if (v%2 == 1) { c255lsetbit(r, c+3, v%2); }; | |
} | |
return r; | |
} | |
var c255lprime = [0xffff-18, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x7fff]; | |
function c255lsetbit(n, c) { | |
var i = Math.floor(c / 16); | |
var a = n[i]; | |
a = a + Math.pow(2, c % 16); | |
n[i] = a; | |
} | |
function c255lgetbit(n, c) { | |
return Math.floor(n[Math.floor(c / 16)] / Math.pow(2, c % 16)) % 2; | |
} | |
function c255lzero() { | |
return [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; | |
} | |
function c255lone() { | |
return [1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; | |
} | |
function c255lbigintcmp(a, b) { | |
var c; | |
for (c = 15; c >= 0; c--) { | |
var x = a[c]; | |
var y = b[c]; | |
if (x > y) { | |
return 1; | |
} | |
if (x < y) { | |
return -1; | |
} | |
} | |
return 0; | |
} | |
function c255lbigintadd(a, b) { | |
var r = []; | |
var v; | |
r[0] = (v = a[0] + b[0]) % 0x10000; | |
r[1] = (v = Math.floor(v / 0x10000) + a[1] + b[1]) % 0x10000; | |
r[2] = (v = Math.floor(v / 0x10000) + a[2] + b[2]) % 0x10000; | |
r[3] = (v = Math.floor(v / 0x10000) + a[3] + b[3]) % 0x10000; | |
r[4] = (v = Math.floor(v / 0x10000) + a[4] + b[4]) % 0x10000; | |
r[5] = (v = Math.floor(v / 0x10000) + a[5] + b[5]) % 0x10000; | |
r[6] = (v = Math.floor(v / 0x10000) + a[6] + b[6]) % 0x10000; | |
r[7] = (v = Math.floor(v / 0x10000) + a[7] + b[7]) % 0x10000; | |
r[8] = (v = Math.floor(v / 0x10000) + a[8] + b[8]) % 0x10000; | |
r[9] = (v = Math.floor(v / 0x10000) + a[9] + b[9]) % 0x10000; | |
r[10] = (v = Math.floor(v / 0x10000) + a[10] + b[10]) % 0x10000; | |
r[11] = (v = Math.floor(v / 0x10000) + a[11] + b[11]) % 0x10000; | |
r[12] = (v = Math.floor(v / 0x10000) + a[12] + b[12]) % 0x10000; | |
r[13] = (v = Math.floor(v / 0x10000) + a[13] + b[13]) % 0x10000; | |
r[14] = (v = Math.floor(v / 0x10000) + a[14] + b[14]) % 0x10000; | |
r[15] = Math.floor(v / 0x10000) + a[15] + b[15]; | |
return r; | |
} | |
function c255lbigintsub(a, b) { | |
var r = []; | |
var v; | |
r[0] = (v = 0x80000 + a[0] - b[0]) % 0x10000; | |
r[1] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[1] - b[1]) % 0x10000; | |
r[2] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[2] - b[2]) % 0x10000; | |
r[3] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[3] - b[3]) % 0x10000; | |
r[4] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[4] - b[4]) % 0x10000; | |
r[5] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[5] - b[5]) % 0x10000; | |
r[6] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[6] - b[6]) % 0x10000; | |
r[7] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[7] - b[7]) % 0x10000; | |
r[8] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[8] - b[8]) % 0x10000; | |
r[9] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[9] - b[9]) % 0x10000; | |
r[10] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[10] - b[10]) % 0x10000; | |
r[11] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[11] - b[11]) % 0x10000; | |
r[12] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[12] - b[12]) % 0x10000; | |
r[13] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[13] - b[13]) % 0x10000; | |
r[14] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[14] - b[14]) % 0x10000; | |
r[15] = Math.floor(v / 0x10000) - 8 + a[15] - b[15]; | |
return r; | |
} | |
function c255lsqr8h(a7, a6, a5, a4, a3, a2, a1, a0) { | |
var r = []; | |
var v; | |
r[0] = (v = a0*a0) % 0x10000; | |
r[1] = (v = Math.floor(v / 0x10000) + 2*a0*a1) % 0x10000; | |
r[2] = (v = Math.floor(v / 0x10000) + 2*a0*a2 + a1*a1) % 0x10000; | |
r[3] = (v = Math.floor(v / 0x10000) + 2*a0*a3 + 2*a1*a2) % 0x10000; | |
r[4] = (v = Math.floor(v / 0x10000) + 2*a0*a4 + 2*a1*a3 + a2*a2) % 0x10000; | |
r[5] = (v = Math.floor(v / 0x10000) + 2*a0*a5 + 2*a1*a4 + 2*a2*a3) % 0x10000; | |
r[6] = (v = Math.floor(v / 0x10000) + 2*a0*a6 + 2*a1*a5 + 2*a2*a4 + a3*a3) % 0x10000; | |
r[7] = (v = Math.floor(v / 0x10000) + 2*a0*a7 + 2*a1*a6 + 2*a2*a5 + 2*a3*a4) % 0x10000; | |
r[8] = (v = Math.floor(v / 0x10000) + 2*a1*a7 + 2*a2*a6 + 2*a3*a5 + a4*a4) % 0x10000; | |
r[9] = (v = Math.floor(v / 0x10000) + 2*a2*a7 + 2*a3*a6 + 2*a4*a5) % 0x10000; | |
r[10] = (v = Math.floor(v / 0x10000) + 2*a3*a7 + 2*a4*a6 + a5*a5) % 0x10000; | |
r[11] = (v = Math.floor(v / 0x10000) + 2*a4*a7 + 2*a5*a6) % 0x10000; | |
r[12] = (v = Math.floor(v / 0x10000) + 2*a5*a7 + a6*a6) % 0x10000; | |
r[13] = (v = Math.floor(v / 0x10000) + 2*a6*a7) % 0x10000; | |
r[14] = (v = Math.floor(v / 0x10000) + a7*a7) % 0x10000; | |
r[15] = Math.floor(v / 0x10000); | |
return r; | |
} | |
function c255lsqrmodp(a) { | |
var x = c255lsqr8h(a[15], a[14], a[13], a[12], a[11], a[10], a[9], a[8]); | |
var z = c255lsqr8h(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0]); | |
var y = c255lsqr8h(a[15] + a[7], a[14] + a[6], a[13] + a[5], a[12] + a[4], a[11] + a[3], a[10] + a[2], a[9] + a[1], a[8] + a[0]); | |
var r = []; | |
var v; | |
r[0] = (v = 0x800000 + z[0] + (y[8] -x[8] -z[8] + x[0] -0x80) * 38) % 0x10000; | |
r[1] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[1] + (y[9] -x[9] -z[9] + x[1]) * 38) % 0x10000; | |
r[2] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[2] + (y[10] -x[10] -z[10] + x[2]) * 38) % 0x10000; | |
r[3] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[3] + (y[11] -x[11] -z[11] + x[3]) * 38) % 0x10000; | |
r[4] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[4] + (y[12] -x[12] -z[12] + x[4]) * 38) % 0x10000; | |
r[5] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[5] + (y[13] -x[13] -z[13] + x[5]) * 38) % 0x10000; | |
r[6] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[6] + (y[14] -x[14] -z[14] + x[6]) * 38) % 0x10000; | |
r[7] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[7] + (y[15] -x[15] -z[15] + x[7]) * 38) % 0x10000; | |
r[8] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[8] + y[0] -x[0] -z[0] + x[8] * 38) % 0x10000; | |
r[9] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[9] + y[1] -x[1] -z[1] + x[9] * 38) % 0x10000; | |
r[10] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[10] + y[2] -x[2] -z[2] + x[10] * 38) % 0x10000; | |
r[11] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[11] + y[3] -x[3] -z[3] + x[11] * 38) % 0x10000; | |
r[12] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[12] + y[4] -x[4] -z[4] + x[12] * 38) % 0x10000; | |
r[13] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[13] + y[5] -x[5] -z[5] + x[13] * 38) % 0x10000; | |
r[14] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[14] + y[6] -x[6] -z[6] + x[14] * 38) % 0x10000; | |
r[15] = 0x7fff80 + Math.floor(v / 0x10000) + z[15] + y[7] -x[7] -z[7] + x[15] * 38; | |
c255lreduce(r); | |
return r; | |
} | |
function c255lmul8h(a7, a6, a5, a4, a3, a2, a1, a0, b7, b6, b5, b4, b3, b2, b1, b0) { | |
var r = []; | |
var v; | |
r[0] = (v = a0*b0) % 0x10000; | |
r[1] = (v = Math.floor(v / 0x10000) + a0*b1 + a1*b0) % 0x10000; | |
r[2] = (v = Math.floor(v / 0x10000) + a0*b2 + a1*b1 + a2*b0) % 0x10000; | |
r[3] = (v = Math.floor(v / 0x10000) + a0*b3 + a1*b2 + a2*b1 + a3*b0) % 0x10000; | |
r[4] = (v = Math.floor(v / 0x10000) + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0) % 0x10000; | |
r[5] = (v = Math.floor(v / 0x10000) + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0) % 0x10000; | |
r[6] = (v = Math.floor(v / 0x10000) + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0) % 0x10000; | |
r[7] = (v = Math.floor(v / 0x10000) + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0) % 0x10000; | |
r[8] = (v = Math.floor(v / 0x10000) + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1) % 0x10000; | |
r[9] = (v = Math.floor(v / 0x10000) + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2) % 0x10000; | |
r[10] = (v = Math.floor(v / 0x10000) + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3) % 0x10000; | |
r[11] = (v = Math.floor(v / 0x10000) + a4*b7 + a5*b6 + a6*b5 + a7*b4) % 0x10000; | |
r[12] = (v = Math.floor(v / 0x10000) + a5*b7 + a6*b6 + a7*b5) % 0x10000; | |
r[13] = (v = Math.floor(v / 0x10000) + a6*b7 + a7*b6) % 0x10000; | |
r[14] = (v = Math.floor(v / 0x10000) + a7*b7) % 0x10000; | |
r[15] = Math.floor(v / 0x10000); | |
return r; | |
} | |
function | |
c255lmulmodp(a, b) { | |
// Karatsuba multiplication scheme: x*y = (b^2+b)*x1*y1 - b*(x1-x0)*(y1-y0) + (b+1)*x0*y0 | |
var x = c255lmul8h(a[15], a[14], a[13], a[12], a[11], a[10], a[9], a[8], b[15], b[14], b[13], b[12], b[11], b[10], b[9], b[8]); | |
var z = c255lmul8h(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0], b[7], b[6], b[5], b[4], b[3], b[2], b[1], b[0]); | |
var y = c255lmul8h(a[15] + a[7], a[14] + a[6], a[13] + a[5], a[12] + a[4], a[11] + a[3], a[10] + a[2], a[9] + a[1], a[8] + a[0], | |
b[15] + b[7], b[14] + b[6], b[13] + b[5], b[12] + b[4], b[11] + b[3], b[10] + b[2], b[9] + b[1], b[8] + b[0]); | |
var r = []; | |
var v; | |
r[0] = (v = 0x800000 + z[0] + (y[8] -x[8] -z[8] + x[0] -0x80) * 38) % 0x10000; | |
r[1] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[1] + (y[9] -x[9] -z[9] + x[1]) * 38) % 0x10000; | |
r[2] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[2] + (y[10] -x[10] -z[10] + x[2]) * 38) % 0x10000; | |
r[3] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[3] + (y[11] -x[11] -z[11] + x[3]) * 38) % 0x10000; | |
r[4] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[4] + (y[12] -x[12] -z[12] + x[4]) * 38) % 0x10000; | |
r[5] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[5] + (y[13] -x[13] -z[13] + x[5]) * 38) % 0x10000; | |
r[6] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[6] + (y[14] -x[14] -z[14] + x[6]) * 38) % 0x10000; | |
r[7] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[7] + (y[15] -x[15] -z[15] + x[7]) * 38) % 0x10000; | |
r[8] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[8] + y[0] -x[0] -z[0] + x[8] * 38) % 0x10000; | |
r[9] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[9] + y[1] -x[1] -z[1] + x[9] * 38) % 0x10000; | |
r[10] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[10] + y[2] -x[2] -z[2] + x[10] * 38) % 0x10000; | |
r[11] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[11] + y[3] -x[3] -z[3] + x[11] * 38) % 0x10000; | |
r[12] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[12] + y[4] -x[4] -z[4] + x[12] * 38) % 0x10000; | |
r[13] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[13] + y[5] -x[5] -z[5] + x[13] * 38) % 0x10000; | |
r[14] = (v = 0x7fff80 + Math.floor(v / 0x10000) + z[14] + y[6] -x[6] -z[6] + x[14] * 38) % 0x10000; | |
r[15] = 0x7fff80 + Math.floor(v / 0x10000) + z[15] + y[7] -x[7] -z[7] + x[15] * 38; | |
c255lreduce(r); | |
return r; | |
} | |
function c255lreduce(a) { | |
var v = a[15]; | |
if (v < 0x8000) return; | |
a[15] = v % 0x8000; | |
v = Math.floor(v / 0x8000) * 19; | |
a[0] = (v += a[0]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[1] = (v += a[1]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[2] = (v += a[2]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[3] = (v += a[3]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[4] = (v += a[4]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[5] = (v += a[5]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[6] = (v += a[6]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[7] = (v += a[7]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[8] = (v += a[8]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[9] = (v += a[9]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[10] = (v += a[10]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[11] = (v += a[11]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[12] = (v += a[12]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[13] = (v += a[13]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[14] = (v += a[14]) % 0x10000; | |
if ((v = Math.floor(v / 0x10000)) < 1) return; | |
a[15] += v; | |
} | |
function c255laddmodp(a, b) { | |
var r = []; | |
var v; | |
r[0] = (v = (Math.floor(a[15] / 0x8000) + Math.floor(b[15] / 0x8000)) * 19 + a[0] + b[0]) % 0x10000; | |
r[1] = (v = Math.floor(v / 0x10000) + a[1] + b[1]) % 0x10000; | |
r[2] = (v = Math.floor(v / 0x10000) + a[2] + b[2]) % 0x10000; | |
r[3] = (v = Math.floor(v / 0x10000) + a[3] + b[3]) % 0x10000; | |
r[4] = (v = Math.floor(v / 0x10000) + a[4] + b[4]) % 0x10000; | |
r[5] = (v = Math.floor(v / 0x10000) + a[5] + b[5]) % 0x10000; | |
r[6] = (v = Math.floor(v / 0x10000) + a[6] + b[6]) % 0x10000; | |
r[7] = (v = Math.floor(v / 0x10000) + a[7] + b[7]) % 0x10000; | |
r[8] = (v = Math.floor(v / 0x10000) + a[8] + b[8]) % 0x10000; | |
r[9] = (v = Math.floor(v / 0x10000) + a[9] + b[9]) % 0x10000; | |
r[10] = (v = Math.floor(v / 0x10000) + a[10] + b[10]) % 0x10000; | |
r[11] = (v = Math.floor(v / 0x10000) + a[11] + b[11]) % 0x10000; | |
r[12] = (v = Math.floor(v / 0x10000) + a[12] + b[12]) % 0x10000; | |
r[13] = (v = Math.floor(v / 0x10000) + a[13] + b[13]) % 0x10000; | |
r[14] = (v = Math.floor(v / 0x10000) + a[14] + b[14]) % 0x10000; | |
r[15] = Math.floor(v / 0x10000) + a[15] % 0x8000 + b[15] % 0x8000; | |
return r; | |
} | |
function c255lsubmodp(a, b) { | |
var r = []; | |
var v; | |
r[0] = (v = 0x80000 + (Math.floor(a[15] / 0x8000) - Math.floor(b[15] / 0x8000) - 1) * 19 + a[0] - b[0]) % 0x10000; | |
r[1] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[1] - b[1]) % 0x10000; | |
r[2] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[2] - b[2]) % 0x10000; | |
r[3] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[3] - b[3]) % 0x10000; | |
r[4] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[4] - b[4]) % 0x10000; | |
r[5] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[5] - b[5]) % 0x10000; | |
r[6] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[6] - b[6]) % 0x10000; | |
r[7] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[7] - b[7]) % 0x10000; | |
r[8] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[8] - b[8]) % 0x10000; | |
r[9] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[9] - b[9]) % 0x10000; | |
r[10] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[10] - b[10]) % 0x10000; | |
r[11] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[11] - b[11]) % 0x10000; | |
r[12] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[12] - b[12]) % 0x10000; | |
r[13] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[13] - b[13]) % 0x10000; | |
r[14] = (v = Math.floor(v / 0x10000) + 0x7fff8 + a[14] - b[14]) % 0x10000; | |
r[15] = Math.floor(v / 0x10000) + 0x7ff8 + a[15]%0x8000 - b[15]%0x8000; | |
return r; | |
} | |
function | |
c255linvmodp(a) { | |
var c = a; | |
var i = 250; | |
while (--i) { | |
a = c255lsqrmodp(a); | |
//if (i > 240) { tracev("invmodp a", a); } | |
a = c255lmulmodp(a, c); | |
//if (i > 240) { tracev("invmodp a 2", a); } | |
} | |
a = c255lsqrmodp(a); | |
a = c255lsqrmodp(a); a = c255lmulmodp(a, c); | |
a = c255lsqrmodp(a); | |
a = c255lsqrmodp(a); a = c255lmulmodp(a, c); | |
a = c255lsqrmodp(a); a = c255lmulmodp(a, c); | |
return a; | |
} | |
function c255lmulasmall(a) { | |
var m = 121665; | |
var r = []; | |
var v; | |
r[0] = (v = a[0] * m) % 0x10000; | |
r[1] = (v = Math.floor(v / 0x10000) + a[1]*m) % 0x10000; | |
r[2] = (v = Math.floor(v / 0x10000) + a[2]*m) % 0x10000; | |
r[3] = (v = Math.floor(v / 0x10000) + a[3]*m) % 0x10000; | |
r[4] = (v = Math.floor(v / 0x10000) + a[4]*m) % 0x10000; | |
r[5] = (v = Math.floor(v / 0x10000) + a[5]*m) % 0x10000; | |
r[6] = (v = Math.floor(v / 0x10000) + a[6]*m) % 0x10000; | |
r[7] = (v = Math.floor(v / 0x10000) + a[7]*m) % 0x10000; | |
r[8] = (v = Math.floor(v / 0x10000) + a[8]*m) % 0x10000; | |
r[9] = (v = Math.floor(v / 0x10000) + a[9]*m) % 0x10000; | |
r[10] = (v = Math.floor(v / 0x10000) + a[10]*m) % 0x10000; | |
r[11] = (v = Math.floor(v / 0x10000) + a[11]*m) % 0x10000; | |
r[12] = (v = Math.floor(v / 0x10000) + a[12]*m) % 0x10000; | |
r[13] = (v = Math.floor(v / 0x10000) + a[13]*m) % 0x10000; | |
r[14] = (v = Math.floor(v / 0x10000) + a[14]*m) % 0x10000; | |
r[15] = Math.floor(v / 0x10000) + a[15]*m; | |
c255lreduce(r); | |
return r; | |
} | |
function c255ldbl(x, z) { | |
var x_2, z_2, m, n, o; | |
///tracev("dbl x", x); | |
///tracev("dbl z", z); | |
m = c255lsqrmodp(c255laddmodp(x, z)); | |
//tracev("dbl m", c255laddmodp(x, z)); | |
n = c255lsqrmodp(c255lsubmodp(x, z)); | |
///tracev("dbl n", n); | |
o = c255lsubmodp(m, n); | |
///tracev("dbl o", o); | |
x_2 = c255lmulmodp(n, m); | |
//tracev("dbl x_2", x_2); | |
z_2 = c255lmulmodp(c255laddmodp(c255lmulasmall(o), m), o); | |
//tracev("dbl z_2", z_2); | |
return [x_2, z_2]; | |
} | |
function c255lsum(x, z, x_p, z_p, x_1) { | |
var x_3, z_3, k, l, p, q; | |
//tracev("sum x", x); | |
//tracev("sum z", z); | |
p = c255lmulmodp(c255lsubmodp(x, z), c255laddmodp(x_p, z_p)); | |
q = c255lmulmodp(c255laddmodp(x, z), c255lsubmodp(x_p, z_p)); | |
//tracev("sum p", p); | |
//tracev("sum q", q); | |
x_3 = c255lsqrmodp(c255laddmodp(p, q)); | |
z_3 = c255lmulmodp(c255lsqrmodp(c255lsubmodp(p, q)), x_1); | |
return [x_3, z_3]; | |
} | |
function curve25519(f, c) { | |
var a, x_1, q; | |
x_1 = c; | |
//tracev("c", c); | |
//tracev("x_1", x_1); | |
a = c255ldbl(x_1, c255lone()); | |
//tracev("x_a", a[0]); | |
//tracev("z_a", a[1]); | |
q = [ x_1, c255lone() ]; | |
var n = 255; | |
while (c255lgetbit(f, n) == 0) { | |
n--; | |
if (n < 0) { | |
return c255lzero(); | |
} | |
} | |
n--; | |
while (n >= 0) { | |
var nn, n_a; | |
var b = c255lgetbit(f, n); | |
if (b == 0) { | |
nn = c255ldbl(q[0], q[1]); | |
n_a = c255lsum(a[0], a[1], q[0], q[1], x_1); | |
} else { | |
nn = c255lsum(a[0], a[1], q[0], q[1], x_1); | |
n_a = c255ldbl(a[0], a[1]); | |
} | |
q = nn; a = n_a; | |
//tracev("xn", q[0]); | |
//tracev("zn", q[1]); | |
//tracev("x_a", &x_a); | |
//tracev("z_a", &z_a); | |
n--; | |
} | |
//tracev("x", q[0]); | |
//tracev("z", q[1]); | |
q[1] = c255linvmodp(q[1]); | |
//tracev("1/z", q[1]); | |
q[0] = c255lmulmodp(q[0], q[1]); | |
c255lreduce(q[0]); | |
return q[0]; | |
} | |
function curve25519b32(a, b) { | |
return c255lbase32encode(curve25519(c255lbase32decode(a), c255lbase32decode(b))); | |
} | |
function curve25519hex(a, b) { | |
if (!b) b = '9'; | |
return c255lhexencode(curve25519(c255lhexdecode(a), c255lhexdecode(b))); | |
} | |
function c255lformcomp(form) { | |
with (form) { | |
resultkey.value = curve25519b32(privatekey.value, publickey.value); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment