/* rsa.c * * The RSA publickey algorithm. */ /* nettle, low-level cryptographics library * * Copyright (C) 2001 Niels M�ller * * The nettle library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your * option) any later version. * * The nettle library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the nettle library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. */ #if HAVE_CONFIG_H #include "config.h" #endif #if HAVE_LIBGMP #include "rsa.h" #include "bignum.h" /* FIXME: Perhaps we should split this into several functions, so that * one can link in the signature functions without also getting the * verify functions. */ int rsa_init_public_key(struct rsa_public_key *key) { unsigned size = (mpz_sizeinbase(key->n, 2) + 7) / 8; /* For PKCS#1 to make sense, the size of the modulo, in octets, must * be at least 11 + the length of the DER-encoded Digest Info. * * And a DigestInfo is 34 octets for md5, and 35 octets for sha1. * 46 octets is 368 bits. */ if (size < 46) { /* Make sure the signing and verification functions doesn't * try to use this key. */ key->size = 0; return 0; } else { key->size = size; return 1; } } int rsa_init_private_key(struct rsa_private_key *key) { return rsa_init_public_key(&key->pub); } #ifndef RSA_CRT #define RSA_CRT 1 #endif /* Internal function for computing an rsa root. * * NOTE: We don't really need n not e, so we could delete the public * key info from struct rsa_private_key. We do need the size, * though. */ void rsa_compute_root(struct rsa_private_key *key, mpz_t x, mpz_t m) { #if RSA_CRT { mpz_t xp; /* modulo p */ mpz_t xq; /* modulo q */ mpz_init(xp); mpz_init(xq); /* Compute xq = m^d % q = (m%q)^b % q */ mpz_fdiv_r(xq, m, key->q); mpz_powm(xq, xq, key->b, key->q); /* Compute xp = m^d % p = (m%p)^a % p */ mpz_fdiv_r(xp, m, key->p); mpz_powm(xp, xp, key->a, key->p); /* Set xp' = (xp - xq) c % p. */ mpz_sub(xp, xp, xq); mpz_mul(xp, xp, key->c); mpz_fdiv_r(xp, xp, key->p); /* Finally, compute x = xq + q xp' * * To prove that this works, note that * * xp = x + i p, * xq = x + j q, * c q = 1 + k p * * for some integers i, j and k. Now, for some integer l, * * xp' = (xp - xq) c + l p * = (x + i p - (x + j q)) c + l p * = (i p - j q) c + l p * = (i c + l) p - j (c q) * = (i c + l) p - j (1 + kp) * = (i c + l - j k) p - j * * which shows that xp' = -j (mod p). We get * * xq + q xp' = x + j q + (i c + l - j k) p q - j q * = x + (i c + l - j k) p q * * so that * * xq + q xp' = x (mod pq) * * We also get 0 <= xq + q xp' < p q, because * * 0 <= xq < q and 0 <= xp' < p. */ mpz_mul(x, key->q, xp); mpz_add(x, x, xq); mpz_clear(xp); mpz_clear(xq); } #else /* !RSA_CRT */ mpz_powm(x, m, key->d, key->pub->n); #endif /* !RSA_CRT */ } #endif /* HAVE_LIBGMP */