chedder
Version:
303 lines • 10.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.scalarmult = exports.scalarbase = exports.sign_keyPair_fromSeed = exports.sign_keyPair_fromSecretKey = exports.sign_keyPair = exports.sign_detached_verify = exports.sign_detached = exports.sign_open = exports.sign = void 0;
const array_js_1 = require("./core/array.js");
const verify_js_1 = require("./core/verify.js");
const core_js_1 = require("./core/core.js");
const random_js_1 = require("./core/random.js");
const curve25519_js_1 = require("./core/curve25519.js");
const hash_js_1 = require("./core/hash.js");
function sign(msg, secretKey) {
array_js_1.checkArrayTypes(msg, secretKey);
if (secretKey.length !== 64 /* SecretKey */)
throw new Error('bad secret key size');
const signedMsg = array_js_1.ByteArray(64 /* Signature */ + msg.length);
_sign(signedMsg, msg, msg.length, secretKey);
return signedMsg;
}
exports.sign = sign;
function sign_open(signedMsg, publicKey) {
array_js_1.checkArrayTypes(signedMsg, publicKey);
if (publicKey.length !== 32 /* PublicKey */)
throw new Error('bad public key size');
const tmp = array_js_1.ByteArray(signedMsg.length);
const mlen = _sign_open(tmp, signedMsg, signedMsg.length, publicKey);
if (mlen < 0)
return;
const m = array_js_1.ByteArray(mlen);
for (let i = 0; i < m.length; i++)
m[i] = tmp[i];
return m;
}
exports.sign_open = sign_open;
function sign_detached(msg, secretKey) {
const signedMsg = sign(msg, secretKey);
const sig = array_js_1.ByteArray(64 /* Signature */);
for (let i = 0; i < sig.length; i++)
sig[i] = signedMsg[i];
return sig;
}
exports.sign_detached = sign_detached;
function sign_detached_verify(msg, sig, publicKey) {
array_js_1.checkArrayTypes(msg, sig, publicKey);
if (sig.length !== 64 /* Signature */)
throw new Error('bad signature size');
if (publicKey.length !== 32 /* PublicKey */)
throw new Error('bad public key size');
const sm = array_js_1.ByteArray(64 /* Signature */ + msg.length);
const m = array_js_1.ByteArray(64 /* Signature */ + msg.length);
let i;
for (i = 0; i < 64 /* Signature */; i++)
sm[i] = sig[i];
for (i = 0; i < msg.length; i++)
sm[i + 64 /* Signature */] = msg[i];
return _sign_open(m, sm, sm.length, publicKey) >= 0;
}
exports.sign_detached_verify = sign_detached_verify;
function sign_keyPair() {
const pk = array_js_1.ByteArray(32 /* PublicKey */);
const sk = array_js_1.ByteArray(64 /* SecretKey */);
_sign_keypair(pk, sk, false);
return { publicKey: pk, secretKey: sk };
}
exports.sign_keyPair = sign_keyPair;
function sign_keyPair_fromSecretKey(secretKey) {
array_js_1.checkArrayTypes(secretKey);
if (secretKey.length !== 64 /* SecretKey */)
throw new Error('bad secret key size');
const pk = array_js_1.ByteArray(32 /* PublicKey */);
for (let i = 0; i < pk.length; i++)
pk[i] = secretKey[32 + i];
return { publicKey: pk, secretKey: array_js_1.ByteArray(secretKey) };
}
exports.sign_keyPair_fromSecretKey = sign_keyPair_fromSecretKey;
function sign_keyPair_fromSeed(seed) {
array_js_1.checkArrayTypes(seed);
if (seed.length !== 32 /* Seed */)
throw new Error('bad seed size');
const pk = array_js_1.ByteArray(32 /* PublicKey */);
const sk = array_js_1.ByteArray(64 /* SecretKey */);
for (let i = 0; i < 32; i++)
sk[i] = seed[i];
_sign_keypair(pk, sk, true);
return { publicKey: pk, secretKey: sk };
}
exports.sign_keyPair_fromSeed = sign_keyPair_fromSeed;
// low level
function _sign_keypair(pk, sk, seeded) {
const d = array_js_1.ByteArray(64);
const p = [core_js_1.gf(), core_js_1.gf(), core_js_1.gf(), core_js_1.gf()];
let i;
if (!seeded)
random_js_1._randomBytes(sk, 32);
hash_js_1._hash(d, sk, 32);
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
scalarbase(p, d);
pack(pk, p);
for (i = 0; i < 32; i++)
sk[i + 32] = pk[i];
return 0;
}
// Note: difference from C - smlen returned, not passed as argument.
function _sign(sm, m, n, sk) {
const d = array_js_1.ByteArray(64), h = array_js_1.ByteArray(64), r = array_js_1.ByteArray(64);
const x = array_js_1.NumArray(64);
const p = [core_js_1.gf(), core_js_1.gf(), core_js_1.gf(), core_js_1.gf()];
let i, j;
hash_js_1._hash(d, sk, 32);
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
const smlen = n + 64;
for (i = 0; i < n; i++)
sm[64 + i] = m[i];
for (i = 0; i < 32; i++)
sm[32 + i] = d[32 + i];
hash_js_1._hash(r, sm.subarray(32), n + 32);
reduce(r);
scalarbase(p, r);
pack(sm, p);
for (i = 32; i < 64; i++)
sm[i] = sk[i];
hash_js_1._hash(h, sm, n + 64);
reduce(h);
for (i = 0; i < 64; i++)
x[i] = 0;
for (i = 0; i < 32; i++)
x[i] = r[i];
for (i = 0; i < 32; i++) {
for (j = 0; j < 32; j++) {
x[i + j] += h[i] * d[j];
}
}
modL(sm.subarray(32), x);
return smlen;
}
function _sign_open(m, sm, n, pk) {
const t = array_js_1.ByteArray(32), h = array_js_1.ByteArray(64);
const p = [core_js_1.gf(), core_js_1.gf(), core_js_1.gf(), core_js_1.gf()], q = [core_js_1.gf(), core_js_1.gf(), core_js_1.gf(), core_js_1.gf()];
let i, mlen;
mlen = -1;
if (n < 64 || unpackneg(q, pk))
return -1;
for (i = 0; i < n; i++)
m[i] = sm[i];
for (i = 0; i < 32; i++)
m[i + 32] = pk[i];
hash_js_1._hash(h, m, n);
reduce(h);
scalarmult(p, q, h);
scalarbase(q, sm.subarray(32));
add(p, q);
pack(t, p);
n -= 64;
if (verify_js_1._verify_32(sm, 0, t, 0)) {
for (i = 0; i < n; i++)
m[i] = 0;
return -1;
}
for (i = 0; i < n; i++)
m[i] = sm[i + 64];
mlen = n;
return mlen;
}
function scalarbase(p, s) {
const q = [core_js_1.gf(), core_js_1.gf(), core_js_1.gf(), core_js_1.gf()];
curve25519_js_1.set25519(q[0], core_js_1.X);
curve25519_js_1.set25519(q[1], core_js_1.Y);
curve25519_js_1.set25519(q[2], core_js_1.gf1);
core_js_1.M(q[3], core_js_1.X, core_js_1.Y);
scalarmult(p, q, s);
}
exports.scalarbase = scalarbase;
function scalarmult(p, q, s) {
let b, i;
curve25519_js_1.set25519(p[0], core_js_1.gf0);
curve25519_js_1.set25519(p[1], core_js_1.gf1);
curve25519_js_1.set25519(p[2], core_js_1.gf1);
curve25519_js_1.set25519(p[3], core_js_1.gf0);
for (i = 255; i >= 0; --i) {
b = (s[(i / 8) | 0] >> (i & 7)) & 1;
cswap(p, q, b);
add(q, p);
add(p, p);
cswap(p, q, b);
}
}
exports.scalarmult = scalarmult;
function pack(r, p) {
const tx = core_js_1.gf(), ty = core_js_1.gf(), zi = core_js_1.gf();
curve25519_js_1.inv25519(zi, p[2]);
core_js_1.M(tx, p[0], zi);
core_js_1.M(ty, p[1], zi);
curve25519_js_1.pack25519(r, ty);
r[31] ^= curve25519_js_1.par25519(tx) << 7;
}
function unpackneg(r, p) {
const t = core_js_1.gf(), chk = core_js_1.gf(), num = core_js_1.gf(), den = core_js_1.gf(), den2 = core_js_1.gf(), den4 = core_js_1.gf(), den6 = core_js_1.gf();
curve25519_js_1.set25519(r[2], core_js_1.gf1);
curve25519_js_1.unpack25519(r[1], p);
core_js_1.S(num, r[1]);
core_js_1.M(den, num, core_js_1.D);
core_js_1.Z(num, num, r[2]);
core_js_1.A(den, r[2], den);
core_js_1.S(den2, den);
core_js_1.S(den4, den2);
core_js_1.M(den6, den4, den2);
core_js_1.M(t, den6, num);
core_js_1.M(t, t, den);
pow2523(t, t);
core_js_1.M(t, t, num);
core_js_1.M(t, t, den);
core_js_1.M(t, t, den);
core_js_1.M(r[0], t, den);
core_js_1.S(chk, r[0]);
core_js_1.M(chk, chk, den);
if (curve25519_js_1.neq25519(chk, num))
core_js_1.M(r[0], r[0], core_js_1.I);
core_js_1.S(chk, r[0]);
core_js_1.M(chk, chk, den);
if (curve25519_js_1.neq25519(chk, num))
return -1;
if (curve25519_js_1.par25519(r[0]) === (p[31] >> 7))
core_js_1.Z(r[0], core_js_1.gf0, r[0]);
core_js_1.M(r[3], r[0], r[1]);
return 0;
}
function reduce(r) {
const x = array_js_1.NumArray(64);
let i;
for (i = 0; i < 64; i++)
x[i] = r[i];
for (i = 0; i < 64; i++)
r[i] = 0;
modL(r, x);
}
const L = array_js_1.NumArray([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]);
function modL(r, x) {
let carry, i, j, k;
for (i = 63; i >= 32; --i) {
carry = 0;
for (j = i - 32, k = i - 12; j < k; ++j) {
x[j] += carry - 16 * x[i] * L[j - (i - 32)];
carry = (x[j] + 128) >> 8;
x[j] -= carry * 256;
}
x[j] += carry;
x[i] = 0;
}
carry = 0;
for (j = 0; j < 32; j++) {
x[j] += carry - (x[31] >> 4) * L[j];
carry = x[j] >> 8;
x[j] &= 255;
}
for (j = 0; j < 32; j++)
x[j] -= carry * L[j];
for (i = 0; i < 32; i++) {
x[i + 1] += x[i] >> 8;
r[i] = x[i] & 255;
}
}
function add(p, q) {
const a = core_js_1.gf(), b = core_js_1.gf(), c = core_js_1.gf(), d = core_js_1.gf(), e = core_js_1.gf(), f = core_js_1.gf(), g = core_js_1.gf(), h = core_js_1.gf(), t = core_js_1.gf();
core_js_1.Z(a, p[1], p[0]);
core_js_1.Z(t, q[1], q[0]);
core_js_1.M(a, a, t);
core_js_1.A(b, p[0], p[1]);
core_js_1.A(t, q[0], q[1]);
core_js_1.M(b, b, t);
core_js_1.M(c, p[3], q[3]);
core_js_1.M(c, c, core_js_1.D2);
core_js_1.M(d, p[2], q[2]);
core_js_1.A(d, d, d);
core_js_1.Z(e, b, a);
core_js_1.Z(f, d, c);
core_js_1.A(g, d, c);
core_js_1.A(h, b, a);
core_js_1.M(p[0], e, f);
core_js_1.M(p[1], h, g);
core_js_1.M(p[2], g, f);
core_js_1.M(p[3], e, h);
}
function cswap(p, q, b) {
for (let i = 0; i < 4; i++) {
curve25519_js_1.sel25519(p[i], q[i], b);
}
}
function pow2523(o, i) {
const c = core_js_1.gf();
let a;
for (a = 0; a < 16; a++)
c[a] = i[a];
for (a = 250; a >= 0; a--) {
core_js_1.S(c, c);
if (a !== 1)
core_js_1.M(c, c, i);
}
for (a = 0; a < 16; a++)
o[a] = c[a];
}
//# sourceMappingURL=sign.js.map