summaryrefslogtreecommitdiff
path: root/rsa.c
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2001-10-30 16:34:21 +0100
committerNiels Möller <nisse@lysator.liu.se>2001-10-30 16:34:21 +0100
commitbaea8c8e0dbc593605f398e70525855f09ae975d (patch)
treea24a31ce1b5f62ae2a457c1dae7e532ebef5e72f /rsa.c
parent365388bae39333165e5c07d3cdb3deb89bd54f74 (diff)
downloadnettle-baea8c8e0dbc593605f398e70525855f09ae975d.tar.gz
New file with general rsa functions.
Rev: src/nettle/rsa.c:1.1
Diffstat (limited to 'rsa.c')
-rw-r--r--rsa.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/rsa.c b/rsa.c
new file mode 100644
index 00000000..2e360fb9
--- /dev/null
+++ b/rsa.c
@@ -0,0 +1,145 @@
+/* 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 */