示例#1
0
文件: math.c 项目: ZerooCool/Shallot
uint8_t sane_key(RSA *rsa) { // checks sanity of a RSA key (PKCS#1 v2.1)
    uint8_t sane = 1;

    BN_CTX *ctx = BN_CTX_new();
    BN_CTX_start(ctx);
    BIGNUM *p1     = BN_CTX_get(ctx), // p - 1
            *q1     = BN_CTX_get(ctx), // q - 1
             *chk    = BN_CTX_get(ctx), // storage to run checks with
              *gcd    = BN_CTX_get(ctx), // GCD(p - 1, q - 1)
               *lambda = BN_CTX_get(ctx); // LCM(p - 1, q - 1)

    BN_sub(p1, rsa->p, BN_value_one()); // p - 1
    BN_sub(q1, rsa->q, BN_value_one()); // q - 1
    BN_gcd(gcd, p1, q1, ctx);           // gcd(p - 1, q - 1)
    BN_lcm(lambda, p1, q1, gcd, ctx);   // lambda(n)

    BN_gcd(chk, lambda, rsa->e, ctx); // check if e is coprime to lambda(n)
    if(!BN_is_one(chk))
        sane = 0;

    // check if public exponent e is less than n - 1
    BN_sub(chk, rsa->e, rsa->n); // subtract n from e to avoid checking BN_is_zero
    if(!chk->neg)
        sane = 0;

    BN_mod_inverse(rsa->d, rsa->e, lambda, ctx);    // d
    BN_mod(rsa->dmp1, rsa->d, p1, ctx);             // d mod (p - 1)
    BN_mod(rsa->dmq1, rsa->d, q1, ctx);             // d mod (q - 1)
    BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx); // q ^ -1 mod p
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);

    // this is excessive but you're better off safe than (very) sorry
    // in theory this should never be true unless I made a mistake ;)
    if((RSA_check_key(rsa) != 1) && sane) {
        fprintf(stderr, "WARNING: Key looked okay, but OpenSSL says otherwise!\n");
        sane = 0;
    }

    return sane;
}
int generateRandomKeys(paillierKeys *keys, int *key_len, BN_CTX *ctx)
{
    int ret = 1, final_key_l = 0;
    BIGNUM *p, *q, *tmp, *n, *n2, *g, *lamda, *mu;

    if (key_len != NULL && *key_len == 0)
    {
        *key_len = DEFAULT_KEY_LEN;
        final_key_l = *key_len;
    }
    else if (key_len != NULL)
    {
        final_key_l = *key_len;
    }
    else
    {
        final_key_l = DEFAULT_KEY_LEN;
    }

    if (final_key_l < 32)
    {
        fprintf(stderr, "Key lenght too short. Minimum lenght 32 bits");
        goto end;
    }

    BN_CTX_start(ctx);

    // Temp BIGNUMs
    p = BN_CTX_get(ctx);
    q = BN_CTX_get(ctx);
    tmp = BN_CTX_get(ctx);

    // Part of the keys BIGNUMs
    n = BN_new();
    n2 = BN_new();
    g = BN_new();
    lamda = BN_new();
    mu = BN_new();

    // 1. Choose two large prime numbers
    // This numbers have to hold gcd(pq, (p-1)(q-1)) = 1
    unsigned char buffer;
    do
    {
        if (!RAND_bytes(&buffer, sizeof(buffer)))
            goto end;
        srandom((int)buffer);

        if (!BN_generate_prime_ex(p, final_key_l / 2, 0, NULL, NULL, NULL))
            goto end;
        if (!BN_generate_prime_ex(q, final_key_l / 2, 0, NULL, NULL, NULL))
            goto end;

        // 2. Compute n = pq
        if (!BN_mul(n, p, q, ctx))
            goto end;

        // Test if primes are ok
        if (!BN_sub_word(p, 1))
            goto end;
        if (!BN_sub_word(q, 1))
            goto end;
        if (!BN_mul(tmp, p, q, ctx))
            goto end;

    }
    while (BN_cmp(p, q) == 0 || BN_gcd(tmp, tmp, n, ctx) != 1);

    // and lamda = lcm(p-1,q-1)
    if (!BN_lcm(lamda, p, q, ctx))
        goto end;

    if (!BN_mul(n2, n, n, ctx))
        goto end;
    do
    {
        // 3. Select a random integer g moz n2
        do
        {
            if (!BN_rand_range(g, n2))
                goto end;
        }
        while (BN_is_zero(g));

        // 4. Ensure n divides the order of g
        if (!BN_mod_exp(tmp, g, lamda, n2, ctx))
            goto end;
        if (L(tmp, tmp, n, ctx) != 0)
            goto end;

        BN_mod_inverse(mu, tmp, n, ctx);
    }
    while (mu == NULL);

    keys->pub.n = n;
    keys->pub.n2 = n2;
    keys->pub.g = g;

    keys->priv.n = BN_dup(n);
    keys->priv.n2 = BN_dup(n2);
    keys->priv.lamda = lamda;
    keys->priv.mu = mu;

    keys->n = BN_dup(n);
    keys->n2 = BN_dup(n2);

    ret = 0;
end:
    if (ret)
    {
        ERR_load_crypto_strings();
        fprintf(stderr, "Error generating keys: %s", ERR_error_string(ERR_get_error(), NULL));
    }

    BN_CTX_end(ctx);
    return ret;
}