mirror of
https://github.com/Qortal/qortal-ui.git
synced 2025-02-11 17:55:51 +00:00
249 lines
4.9 KiB
JavaScript
249 lines
4.9 KiB
JavaScript
/*
|
|
* ed2curve: convert Ed25519 signing key pair into Curve25519
|
|
* key pair suitable for Diffie-Hellman key exchange.
|
|
*
|
|
* Written by Dmitry Chestnykh in 2014. Public domain.
|
|
*/
|
|
/* jshint newcap: false */
|
|
|
|
/*
|
|
Change to es6 import/export
|
|
*/
|
|
|
|
import nacl from './nacl-fast'
|
|
|
|
// -- Operations copied from TweetNaCl.js. --
|
|
|
|
var gf = function (init) {
|
|
var i, r = new Float64Array(16);
|
|
if (init) for (i = 0; i < init.length; i++) r[i] = init[i];
|
|
return r;
|
|
};
|
|
|
|
var gf0 = gf(),
|
|
gf1 = gf([1]),
|
|
D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]),
|
|
I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]);
|
|
|
|
function car25519(o) {
|
|
var c;
|
|
var i;
|
|
for (i = 0; i < 16; i++) {
|
|
o[i] += 65536;
|
|
c = Math.floor(o[i] / 65536);
|
|
o[(i + 1) * (i < 15 ? 1 : 0)] += c - 1 + 37 * (c - 1) * (i === 15 ? 1 : 0);
|
|
o[i] -= (c * 65536);
|
|
}
|
|
}
|
|
|
|
function sel25519(p, q, b) {
|
|
var t, c = ~(b - 1);
|
|
for (var i = 0; i < 16; i++) {
|
|
t = c & (p[i] ^ q[i]);
|
|
p[i] ^= t;
|
|
q[i] ^= t;
|
|
}
|
|
}
|
|
|
|
function unpack25519(o, n) {
|
|
var i;
|
|
for (i = 0; i < 16; i++) o[i] = n[2 * i] + (n[2 * i + 1] << 8);
|
|
o[15] &= 0x7fff;
|
|
}
|
|
|
|
// addition
|
|
function A(o, a, b) {
|
|
var i;
|
|
for (i = 0; i < 16; i++) o[i] = (a[i] + b[i]) | 0;
|
|
}
|
|
|
|
// subtraction
|
|
function Z(o, a, b) {
|
|
var i;
|
|
for (i = 0; i < 16; i++) o[i] = (a[i] - b[i]) | 0;
|
|
}
|
|
|
|
// multiplication
|
|
function M(o, a, b) {
|
|
var i, j, t = new Float64Array(31);
|
|
for (i = 0; i < 31; i++) t[i] = 0;
|
|
for (i = 0; i < 16; i++) {
|
|
for (j = 0; j < 16; j++) {
|
|
t[i + j] += a[i] * b[j];
|
|
}
|
|
}
|
|
for (i = 0; i < 15; i++) {
|
|
t[i] += 38 * t[i + 16];
|
|
}
|
|
for (i = 0; i < 16; i++) o[i] = t[i];
|
|
car25519(o);
|
|
car25519(o);
|
|
}
|
|
|
|
// squaring
|
|
function S(o, a) {
|
|
M(o, a, a);
|
|
}
|
|
|
|
// inversion
|
|
function inv25519(o, i) {
|
|
var c = gf();
|
|
var a;
|
|
for (a = 0; a < 16; a++) c[a] = i[a];
|
|
for (a = 253; a >= 0; a--) {
|
|
S(c, c);
|
|
if (a !== 2 && a !== 4) M(c, c, i);
|
|
}
|
|
for (a = 0; a < 16; a++) o[a] = c[a];
|
|
}
|
|
|
|
function pack25519(o, n) {
|
|
var i, j, b;
|
|
var m = gf(), t = gf();
|
|
for (i = 0; i < 16; i++) t[i] = n[i];
|
|
car25519(t);
|
|
car25519(t);
|
|
car25519(t);
|
|
for (j = 0; j < 2; j++) {
|
|
m[0] = t[0] - 0xffed;
|
|
for (i = 1; i < 15; i++) {
|
|
m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
|
|
m[i - 1] &= 0xffff;
|
|
}
|
|
m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
|
|
b = (m[15] >> 16) & 1;
|
|
m[14] &= 0xffff;
|
|
sel25519(t, m, 1 - b);
|
|
}
|
|
for (i = 0; i < 16; i++) {
|
|
o[2 * i] = t[i] & 0xff;
|
|
o[2 * i + 1] = t[i] >> 8;
|
|
}
|
|
}
|
|
|
|
function par25519(a) {
|
|
var d = new Uint8Array(32);
|
|
pack25519(d, a);
|
|
return d[0] & 1;
|
|
}
|
|
|
|
function vn(x, xi, y, yi, n) {
|
|
var i, d = 0;
|
|
for (i = 0; i < n; i++) d |= x[xi + i] ^ y[yi + i];
|
|
return (1 & ((d - 1) >>> 8)) - 1;
|
|
}
|
|
|
|
function crypto_verify_32(x, xi, y, yi) {
|
|
return vn(x, xi, y, yi, 32);
|
|
}
|
|
|
|
function neq25519(a, b) {
|
|
var c = new Uint8Array(32), d = new Uint8Array(32);
|
|
pack25519(c, a);
|
|
pack25519(d, b);
|
|
return crypto_verify_32(c, 0, d, 0);
|
|
}
|
|
|
|
function pow2523(o, i) {
|
|
var c = gf();
|
|
var a;
|
|
for (a = 0; a < 16; a++) c[a] = i[a];
|
|
for (a = 250; a >= 0; a--) {
|
|
S(c, c);
|
|
if (a !== 1) M(c, c, i);
|
|
}
|
|
for (a = 0; a < 16; a++) o[a] = c[a];
|
|
}
|
|
|
|
function set25519(r, a) {
|
|
var i;
|
|
for (i = 0; i < 16; i++) r[i] = a[i] | 0;
|
|
}
|
|
|
|
function unpackneg(r, p) {
|
|
var t = gf(), chk = gf(), num = gf(),
|
|
den = gf(), den2 = gf(), den4 = gf(),
|
|
den6 = gf();
|
|
|
|
set25519(r[2], gf1);
|
|
unpack25519(r[1], p);
|
|
S(num, r[1]);
|
|
M(den, num, D);
|
|
Z(num, num, r[2]);
|
|
A(den, r[2], den);
|
|
|
|
S(den2, den);
|
|
S(den4, den2);
|
|
M(den6, den4, den2);
|
|
M(t, den6, num);
|
|
M(t, t, den);
|
|
|
|
pow2523(t, t);
|
|
M(t, t, num);
|
|
M(t, t, den);
|
|
M(t, t, den);
|
|
M(r[0], t, den);
|
|
|
|
S(chk, r[0]);
|
|
M(chk, chk, den);
|
|
if (neq25519(chk, num)) M(r[0], r[0], I);
|
|
|
|
S(chk, r[0]);
|
|
M(chk, chk, den);
|
|
if (neq25519(chk, num)) return -1;
|
|
|
|
if (par25519(r[0]) === (p[31] >> 7)) Z(r[0], gf0, r[0]);
|
|
|
|
M(r[3], r[0], r[1]);
|
|
return 0;
|
|
}
|
|
|
|
// ----
|
|
|
|
// Converts Ed25519 public key to Curve25519 public key.
|
|
// montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p
|
|
function convertPublicKey(pk) {
|
|
var z = new Uint8Array(32),
|
|
q = [gf(), gf(), gf(), gf()],
|
|
a = gf(), b = gf();
|
|
|
|
if (unpackneg(q, pk)) return null; // reject invalid key
|
|
|
|
var y = q[1];
|
|
|
|
A(a, gf1, y);
|
|
Z(b, gf1, y);
|
|
inv25519(b, b);
|
|
M(a, a, b);
|
|
|
|
pack25519(z, a);
|
|
return z;
|
|
}
|
|
|
|
// Converts Ed25519 secret key to Curve25519 secret key.
|
|
function convertSecretKey(sk) {
|
|
var d = new Uint8Array(64), o = new Uint8Array(32), i;
|
|
nacl.lowlevel.crypto_hash(d, sk, 32);
|
|
d[0] &= 248;
|
|
d[31] &= 127;
|
|
d[31] |= 64;
|
|
for (i = 0; i < 32; i++) o[i] = d[i];
|
|
for (i = 0; i < 64; i++) d[i] = 0;
|
|
return o;
|
|
}
|
|
|
|
function convertKeyPair(edKeyPair) {
|
|
var publicKey = convertPublicKey(edKeyPair.publicKey);
|
|
if (!publicKey) return null;
|
|
return {
|
|
publicKey: publicKey,
|
|
secretKey: convertSecretKey(edKeyPair.secretKey)
|
|
};
|
|
}
|
|
|
|
export default {
|
|
convertPublicKey: convertPublicKey,
|
|
convertSecretKey: convertSecretKey,
|
|
convertKeyPair: convertKeyPair,
|
|
}
|