Qortal UI - Main Code Repository A User Interface for the Qortal Blockchain Project. Truly decentralized web hosting, application hosting, communications, data storage, and full infrastructure for the future global decentralized digital world.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

248 lines
4.9 KiB

/*
* 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,
}