PHP WebShell

Текущая директория: /opt/BitGoJS/node_modules/tweetnacl-ts/src

Просмотр файла: sign.ts

import { ByteArray, NumArray } from './array';
import { _verify_32 } from './verify';
import { gf, gf0, gf1, D2, A, D, S, M, X, Y, Z, I } from './core';
import { _randomBytes } from './random';
import { set25519, sel25519, inv25519, pack25519, unpack25519, par25519, neq25519 } from './curve25519';
import { _hash } from './hash';
import { checkArrayTypes } from './check';

export const enum SignLength {
    PublicKey = 32, // public key bytes
    SecretKey = 64, // secret key bytes
    Seed = 32,      // seed bytes
    Signature = 64, // signature bytes
}

export interface SignKeyPair {
    publicKey: ByteArray;
    secretKey: ByteArray;
}

export function sign(msg: ByteArray, secretKey: ByteArray): ByteArray {
    checkArrayTypes(msg, secretKey);

    if (secretKey.length !== SignLength.SecretKey)
        throw new Error('bad secret key size');

    const signedMsg = ByteArray(SignLength.Signature + msg.length);

    _sign(signedMsg, msg, msg.length, secretKey);

    return signedMsg;
}

export function sign_open(signedMsg: ByteArray, publicKey: ByteArray): ByteArray | undefined {
    checkArrayTypes(signedMsg, publicKey);

    if (publicKey.length !== SignLength.PublicKey)
        throw new Error('bad public key size');

    const tmp = ByteArray(signedMsg.length);

    const mlen = _sign_open(tmp, signedMsg, signedMsg.length, publicKey);

    if (mlen < 0) return;

    const m = ByteArray(mlen);

    for (let i = 0; i < m.length; i++) m[i] = tmp[i];

    return m;
}

export function sign_detached(msg: ByteArray, secretKey: ByteArray): ByteArray {
    const signedMsg = sign(msg, secretKey);

    const sig = ByteArray(SignLength.Signature);

    for (let i = 0; i < sig.length; i++) sig[i] = signedMsg[i];

    return sig;
}

export function sign_detached_verify(msg: ByteArray, sig: ByteArray, publicKey: ByteArray): boolean {
    checkArrayTypes(msg, sig, publicKey);

    if (sig.length !== SignLength.Signature)
        throw new Error('bad signature size');

    if (publicKey.length !== SignLength.PublicKey)
        throw new Error('bad public key size');

    const sm = ByteArray(SignLength.Signature + msg.length);
    const m = ByteArray(SignLength.Signature + msg.length);

    let i;
    for (i = 0; i < SignLength.Signature; i++) sm[i] = sig[i];
    for (i = 0; i < msg.length; i++) sm[i + SignLength.Signature] = msg[i];

    return _sign_open(m, sm, sm.length, publicKey) >= 0;
}

export function sign_keyPair(): SignKeyPair {
    const pk = ByteArray(SignLength.PublicKey);
    const sk = ByteArray(SignLength.SecretKey);

    _sign_keypair(pk, sk, false);

    return { publicKey: pk, secretKey: sk };
}

export function sign_keyPair_fromSecretKey(secretKey: ByteArray): SignKeyPair {
    checkArrayTypes(secretKey);

    if (secretKey.length !== SignLength.SecretKey)
        throw new Error('bad secret key size');

    const pk = ByteArray(SignLength.PublicKey);

    for (let i = 0; i < pk.length; i++) pk[i] = secretKey[32 + i];

    return { publicKey: pk, secretKey: ByteArray(secretKey) };
}

export function sign_keyPair_fromSeed(seed: ByteArray): SignKeyPair {
    checkArrayTypes(seed);

    if (seed.length !== SignLength.Seed)
        throw new Error('bad seed size');

    const pk = ByteArray(SignLength.PublicKey);
    const sk = ByteArray(SignLength.SecretKey);

    for (let i = 0; i < 32; i++) sk[i] = seed[i];

    _sign_keypair(pk, sk, true);

    return { publicKey: pk, secretKey: sk };
}

// low level

function _sign_keypair(pk: ByteArray, sk: ByteArray, seeded: boolean): number {
    const d = ByteArray(64);
    const p = [gf(), gf(), gf(), gf()];
    let i;

    if (!seeded) _randomBytes(sk, 32);

    _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: ByteArray, m: ByteArray, n: number, sk: ByteArray): number {
    const d = ByteArray(64), h = ByteArray(64), r = ByteArray(64);
    const x = NumArray(64);
    const p = [gf(), gf(), gf(), gf()];
    let i, j;

    _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(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(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: ByteArray, sm: ByteArray, n: number, pk: ByteArray): number {
    const t = ByteArray(32), h = ByteArray(64);
    const p = [gf(), gf(), gf(), gf()], q = [gf(), gf(), gf(), 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(h, m, n);
    reduce(h);
    scalarmult(p, q, h);

    scalarbase(q, sm.subarray(32));

    add(p, q);
    pack(t, p);

    n -= 64;

    if (_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;
}

export function scalarbase(p: ByteArray[], s: ByteArray) {
    const q = [gf(), gf(), gf(), gf()];

    set25519(q[0], X);
    set25519(q[1], Y);
    set25519(q[2], gf1);

    M(q[3], X, Y);

    scalarmult(p, q, s);
}

export function scalarmult(p: ByteArray[], q: NumArray[], s: ByteArray) {
    let b, i;

    set25519(p[0], gf0);
    set25519(p[1], gf1);
    set25519(p[2], gf1);
    set25519(p[3], 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);
    }
}

function pack(r: ByteArray, p: NumArray[]) {
    const tx = gf(), ty = gf(), zi = gf();

    inv25519(zi, p[2]);

    M(tx, p[0], zi);
    M(ty, p[1], zi);

    pack25519(r, ty);

    r[31] ^= par25519(tx) << 7;
}

function unpackneg(r: NumArray[], p: ByteArray) {
    const
        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;
}

function reduce(r: ByteArray) {
    const x = 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 = 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: ByteArray, x: NumArray) {
    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: NumArray[], q: NumArray[]) {
    const
        a = gf(), b = gf(), c = gf(),
        d = gf(), e = gf(), f = gf(),
        g = gf(), h = gf(), t = gf();

    Z(a, p[1], p[0]);
    Z(t, q[1], q[0]);
    M(a, a, t);
    A(b, p[0], p[1]);
    A(t, q[0], q[1]);
    M(b, b, t);
    M(c, p[3], q[3]);
    M(c, c, D2);
    M(d, p[2], q[2]);
    A(d, d, d);
    Z(e, b, a);
    Z(f, d, c);
    A(g, d, c);
    A(h, b, a);

    M(p[0], e, f);
    M(p[1], h, g);
    M(p[2], g, f);
    M(p[3], e, h);
}

function cswap(p: NumArray[], q: NumArray[], b: number) {
    for (let i = 0; i < 4; i++) {
        sel25519(p[i], q[i], b);
    }
}

function pow2523(o: NumArray, i: NumArray) {
    const c = gf();
    let 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];
}

Выполнить команду


Для локальной разработки. Не используйте в интернете!