Пример #1
0
int mod_inverse(const Ptr<RCP<const Integer>> &b, const Integer &a,
                const Integer &m)
{
    int ret_val;
    integer_class inv_t;
    ret_val = mp_invert(inv_t, a.as_integer_class(), m.as_integer_class());
    *b = integer(std::move(inv_t));
    return ret_val;
}
Пример #2
0
void GaloisFieldDict::gf_div(const GaloisFieldDict &o,
                             const Ptr<GaloisFieldDict> &quo,
                             const Ptr<GaloisFieldDict> &rem) const
{
    if (modulo_ != o.modulo_)
        throw std::runtime_error("Error: field must be same.");
    if (o.dict_.empty())
        throw std::runtime_error("ZeroDivisionError");
    std::vector<integer_class> dict_out;
    if (dict_.empty()) {
        *quo = GaloisFieldDict::from_vec(dict_out, modulo_);
        *rem = GaloisFieldDict::from_vec(dict_, modulo_);
        return;
    }
    auto dict_divisor = o.dict_;
    unsigned int deg_dividend = this->degree();
    unsigned int deg_divisor = o.degree();
    if (deg_dividend < deg_divisor) {
        *quo = GaloisFieldDict::from_vec(dict_out, modulo_);
        *rem = GaloisFieldDict::from_vec(dict_, modulo_);
    } else {
        dict_out = dict_;
        integer_class inv;
        mp_invert(inv, *(dict_divisor.rbegin()), modulo_);
        integer_class coeff;
        for (auto it = deg_dividend + 1; it-- != 0;) {
            coeff = dict_out[it];
            auto lb = deg_divisor + it > deg_dividend
                          ? deg_divisor + it - deg_dividend
                          : 0;
            auto ub = std::min(it + 1, deg_divisor);
            for (size_t j = lb; j < ub; ++j) {
                mp_addmul(coeff, dict_out[it - j + deg_divisor],
                          -dict_divisor[j]);
            }
            if (it >= deg_divisor)
                coeff *= inv;
            mp_fdiv_r(coeff, coeff, modulo_);
            dict_out[it] = coeff;
        }
        std::vector<integer_class> dict_rem, dict_quo;
        dict_rem.resize(deg_divisor);
        dict_quo.resize(deg_dividend - deg_divisor + 1);
        for (unsigned it = 0; it < dict_out.size(); it++) {
            if (it < deg_divisor)
                dict_rem[it] = dict_out[it];
            else
                dict_quo[it - deg_divisor] = dict_out[it];
        }
        *quo = GaloisFieldDict::from_vec(dict_quo, modulo_);
        *rem = GaloisFieldDict::from_vec(dict_rem, modulo_);
    }
}
Пример #3
0
static void ecdsa_sign(ssh_key *key, ptrlen data,
                       unsigned flags, BinarySink *bs)
{
    struct ecdsa_key *ek = container_of(key, struct ecdsa_key, sshk);
    const struct ecsign_extra *extra =
        (const struct ecsign_extra *)ek->sshk.vt->extra;
    assert(ek->privateKey);

    mp_int *z = ecdsa_signing_exponent_from_data(ek->curve, extra, data);

    /* Generate k between 1 and curve->n, using the same deterministic
     * k generation system we use for conventional DSA. */
    mp_int *k;
    {
        unsigned char digest[20];
        hash_simple(&ssh_sha1, data, digest);
        k = dss_gen_k(
            "ECDSA deterministic k generator", ek->curve->w.G_order,
            ek->privateKey, digest, sizeof(digest));
    }

    WeierstrassPoint *kG = ecc_weierstrass_multiply(ek->curve->w.G, k);
    mp_int *x;
    ecc_weierstrass_get_affine(kG, &x, NULL);
    ecc_weierstrass_point_free(kG);

    /* r = kG.x mod order(G) */
    mp_int *r = mp_mod(x, ek->curve->w.G_order);
    mp_free(x);

    /* s = (z + r * priv)/k mod n */
    mp_int *rPriv = mp_modmul(r, ek->privateKey, ek->curve->w.G_order);
    mp_int *numerator = mp_modadd(z, rPriv, ek->curve->w.G_order);
    mp_free(z);
    mp_free(rPriv);
    mp_int *kInv = mp_invert(k, ek->curve->w.G_order);
    mp_free(k);
    mp_int *s = mp_modmul(numerator, kInv, ek->curve->w.G_order);
    mp_free(numerator);
    mp_free(kInv);

    /* Format the output */
    put_stringz(bs, ek->sshk.vt->ssh_id);

    strbuf *substr = strbuf_new();
    put_mp_ssh2(substr, r);
    put_mp_ssh2(substr, s);
    put_stringsb(bs, substr);

    mp_free(r);
    mp_free(s);
}
Пример #4
0
/*
 * Verify that the public data in an RSA key matches the private
 * data. We also check the private data itself: we ensure that p >
 * q and that iqmp really is the inverse of q mod p.
 */
bool rsa_verify(RSAKey *key)
{
    mp_int *n, *ed, *pm1, *qm1;
    unsigned ok = 1;

    /* Preliminary checks: p,q must actually be nonzero. */
    if (mp_eq_integer(key->p, 0) | mp_eq_integer(key->q, 0))
        return false;

    /* n must equal pq. */
    n = mp_mul(key->p, key->q);
    ok &= mp_cmp_eq(n, key->modulus);
    mp_free(n);

    /* e * d must be congruent to 1, modulo (p-1) and modulo (q-1). */
    pm1 = mp_copy(key->p);
    mp_sub_integer_into(pm1, pm1, 1);
    ed = mp_modmul(key->exponent, key->private_exponent, pm1);
    mp_free(pm1);
    ok &= mp_eq_integer(ed, 1);
    mp_free(ed);

    qm1 = mp_copy(key->q);
    mp_sub_integer_into(qm1, qm1, 1);
    ed = mp_modmul(key->exponent, key->private_exponent, qm1);
    mp_free(qm1);
    ok &= mp_eq_integer(ed, 1);
    mp_free(ed);

    /*
     * Ensure p > q.
     *
     * I have seen key blobs in the wild which were generated with
     * p < q, so instead of rejecting the key in this case we
     * should instead flip them round into the canonical order of
     * p > q. This also involves regenerating iqmp.
     */
    mp_int *p_new = mp_max(key->p, key->q);
    mp_int *q_new = mp_min(key->p, key->q);
    mp_free(key->p);
    mp_free(key->q);
    mp_free(key->iqmp);
    key->p = p_new;
    key->q = q_new;
    key->iqmp = mp_invert(key->q, key->p);

    return ok;
}
Пример #5
0
void GaloisFieldDict::gf_monic(integer_class &res,
                               const Ptr<GaloisFieldDict> &monic) const
{
    *monic = static_cast<GaloisFieldDict>(*this);
    if (dict_.empty()) {
        res = integer_class(0);
    } else {
        res = *dict_.rbegin();
        if (res != integer_class(1)) {
            integer_class inv, temp;
            mp_invert(inv, res, modulo_);
            for (auto &iter : monic->dict_) {
                temp = inv;
                temp *= iter;
                mp_fdiv_r(iter, temp, modulo_);
            }
        }
    }
}
Пример #6
0
static bool ecdsa_verify(ssh_key *key, ptrlen sig, ptrlen data)
{
    struct ecdsa_key *ek = container_of(key, struct ecdsa_key, sshk);
    const struct ecsign_extra *extra =
        (const struct ecsign_extra *)ek->sshk.vt->extra;

    BinarySource src[1];
    BinarySource_BARE_INIT_PL(src, sig);

    /* Check the signature starts with the algorithm name */
    if (!ptrlen_eq_string(get_string(src), ek->sshk.vt->ssh_id))
        return false;

    /* Everything else is nested inside a sub-string. Descend into that. */
    ptrlen sigstr = get_string(src);
    if (get_err(src))
        return false;
    BinarySource_BARE_INIT_PL(src, sigstr);

    /* Extract the signature integers r,s */
    mp_int *r = get_mp_ssh2(src);
    mp_int *s = get_mp_ssh2(src);
    if (get_err(src)) {
        mp_free(r);
        mp_free(s);
        return false;
    }

    /* Basic sanity checks: 0 < r,s < order(G) */
    unsigned invalid = 0;
    invalid |= mp_eq_integer(r, 0);
    invalid |= mp_eq_integer(s, 0);
    invalid |= mp_cmp_hs(r, ek->curve->w.G_order);
    invalid |= mp_cmp_hs(s, ek->curve->w.G_order);

    /* Get the hash of the signed data, converted to an integer */
    mp_int *z = ecdsa_signing_exponent_from_data(ek->curve, extra, data);

    /* Verify the signature integers against the hash */
    mp_int *w = mp_invert(s, ek->curve->w.G_order);
    mp_int *u1 = mp_modmul(z, w, ek->curve->w.G_order);
    mp_free(z);
    mp_int *u2 = mp_modmul(r, w, ek->curve->w.G_order);
    mp_free(w);
    WeierstrassPoint *u1G = ecc_weierstrass_multiply(ek->curve->w.G, u1);
    mp_free(u1);
    WeierstrassPoint *u2P = ecc_weierstrass_multiply(ek->publicKey, u2);
    mp_free(u2);
    WeierstrassPoint *sum = ecc_weierstrass_add_general(u1G, u2P);
    ecc_weierstrass_point_free(u1G);
    ecc_weierstrass_point_free(u2P);

    mp_int *x;
    ecc_weierstrass_get_affine(sum, &x, NULL);
    ecc_weierstrass_point_free(sum);

    mp_divmod_into(x, ek->curve->w.G_order, NULL, x);
    invalid |= (1 ^ mp_cmp_eq(r, x));
    mp_free(x);

    mp_free(r);
    mp_free(s);

    return !invalid;
}