diff --git a/rsa-md5-sign.c b/rsa-md5-sign.c
new file mode 100644
index 0000000000000000000000000000000000000000..4bcaf717a182cd39aa1973660796e833413d7b40
--- /dev/null
+++ b/rsa-md5-sign.c
@@ -0,0 +1,63 @@
+/* rsa-md5-sign.c
+ *
+ * Signatures using RSA and MD5.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2001, 2003 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 WITH_PUBLIC_KEY
+
+#include "rsa.h"
+
+#include "bignum.h"
+#include "pkcs1.h"
+
+#include <assert.h>
+
+void
+rsa_md5_sign(const struct rsa_private_key *key,
+             struct md5_ctx *hash,
+             mpz_t s)
+{
+  assert(key->size >= RSA_MINIMUM_N_OCTETS);
+
+  pkcs1_rsa_md5_encode(s, key->size - 1, hash);
+
+  rsa_compute_root(key, s, s);
+}
+
+void
+rsa_md5_sign_digest(const struct rsa_private_key *key,
+		    const uint8_t *digest,
+		    mpz_t s)
+{
+  assert(key->size >= RSA_MINIMUM_N_OCTETS);
+
+  pkcs1_rsa_md5_encode_digest(s, key->size - 1, digest);
+
+  rsa_compute_root(key, s, s);
+}
+
+#endif /* WITH_PUBLIC_KEY */
diff --git a/rsa-md5-verify.c b/rsa-md5-verify.c
new file mode 100644
index 0000000000000000000000000000000000000000..727cc8e6f24adec6f9f1d6168cbedfafa200fc63
--- /dev/null
+++ b/rsa-md5-verify.c
@@ -0,0 +1,78 @@
+/* rsa-md5-verify.c
+ *
+ * Verifying signatures created with RSA and MD5.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2001, 2003 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 WITH_PUBLIC_KEY
+
+#include "rsa.h"
+
+#include "bignum.h"
+#include "pkcs1.h"
+
+#include <assert.h>
+
+int
+rsa_md5_verify(const struct rsa_public_key *key,
+               struct md5_ctx *hash,
+               const mpz_t s)
+{
+  int res;
+  mpz_t m;
+
+  assert(key->size >= RSA_MINIMUM_N_OCTETS);
+  mpz_init(m);
+  
+  pkcs1_rsa_md5_encode(m, key->size - 1, hash);
+  res = _rsa_verify(key, m, s);
+
+  mpz_clear(m);
+
+  return res;
+}
+
+int
+rsa_md5_verify_digest(const struct rsa_public_key *key,
+		      const uint8_t *digest,
+		      const mpz_t s)
+{
+  int res;
+  mpz_t m;
+
+  assert(key->size >= RSA_MINIMUM_N_OCTETS);
+  
+  mpz_init(m);
+  
+  pkcs1_rsa_md5_encode_digest(m, key->size - 1, digest);
+  res = _rsa_verify(key, m, s);
+
+  mpz_clear(m);
+
+  return res;
+}
+
+#endif /* WITH_PUBLIC_KEY */
diff --git a/rsa-sha1-sign.c b/rsa-sha1-sign.c
new file mode 100644
index 0000000000000000000000000000000000000000..d48bb802af3a30d66af303cfcb2bb14e3a22be81
--- /dev/null
+++ b/rsa-sha1-sign.c
@@ -0,0 +1,63 @@
+/* rsa-sha1-sign.c
+ *
+ * Signatures using RSA and SHA1.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2001, 2003 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 WITH_PUBLIC_KEY
+
+#include "rsa.h"
+
+#include "bignum.h"
+#include "pkcs1.h"
+
+#include <assert.h>
+
+void
+rsa_sha1_sign(const struct rsa_private_key *key,
+              struct sha1_ctx *hash,
+              mpz_t s)
+{
+  assert(key->size >= RSA_MINIMUM_N_OCTETS);
+
+  pkcs1_rsa_sha1_encode(s, key->size - 1, hash);
+
+  rsa_compute_root(key, s, s);
+}
+
+void
+rsa_sha1_sign_digest(const struct rsa_private_key *key,
+		     const uint8_t *digest,
+		     mpz_t s)
+{
+  assert(key->size >= RSA_MINIMUM_N_OCTETS);
+
+  pkcs1_rsa_sha1_encode_digest(s, key->size - 1, digest);
+
+  rsa_compute_root(key, s, s);
+}
+
+#endif /* WITH_PUBLIC_KEY */
diff --git a/rsa-sha1-verify.c b/rsa-sha1-verify.c
new file mode 100644
index 0000000000000000000000000000000000000000..717a392d5a72640e47ba75c3c8ef4567f192577f
--- /dev/null
+++ b/rsa-sha1-verify.c
@@ -0,0 +1,77 @@
+/* rsa-sha1-verify.c
+ *
+ * Verifying signatures created with RSA and SHA1.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2001, 2003 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 WITH_PUBLIC_KEY
+
+#include "rsa.h"
+
+#include "bignum.h"
+#include "pkcs1.h"
+
+#include <assert.h>
+
+int
+rsa_sha1_verify(const struct rsa_public_key *key,
+                struct sha1_ctx *hash,
+                const mpz_t s)
+{
+  int res;
+  mpz_t m;
+
+  assert(key->size >= RSA_MINIMUM_N_OCTETS);
+  mpz_init(m);
+  
+  pkcs1_rsa_sha1_encode(m, key->size - 1, hash);
+  res = _rsa_verify(key, m, s);
+  
+  mpz_clear(m);
+
+  return res;
+}
+
+int
+rsa_sha1_verify_digest(const struct rsa_public_key *key,
+		       const uint8_t *digest,
+		       const mpz_t s)
+{
+  int res;
+  mpz_t m;
+
+  assert(key->size >= RSA_MINIMUM_N_OCTETS);
+  mpz_init(m);
+  
+  pkcs1_rsa_sha1_encode_digest(m, key->size - 1, digest);
+  res = _rsa_verify(key, m, s);
+  
+  mpz_clear(m);
+
+  return res;
+}
+     
+#endif /* WITH_PUBLIC_KEY */
diff --git a/rsa-sign.c b/rsa-sign.c
new file mode 100644
index 0000000000000000000000000000000000000000..6a50685feaaf0ebafd278461a6e6921ecb159c00
--- /dev/null
+++ b/rsa-sign.c
@@ -0,0 +1,142 @@
+/* rsa-sign.c
+ *
+ * Creating RSA signatures.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2001, 2003 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 WITH_PUBLIC_KEY
+
+#include "rsa.h"
+
+#include "bignum.h"
+
+void
+rsa_init_private_key(struct rsa_private_key *key)
+{
+  mpz_init(key->d);
+  mpz_init(key->p);
+  mpz_init(key->q);
+  mpz_init(key->a);
+  mpz_init(key->b);
+  mpz_init(key->c);
+
+  /* Not really necessary, but it seems cleaner to initialize all the
+   * storage. */
+  key->size = 0;
+}
+
+void
+rsa_clear_private_key(struct rsa_private_key *key)
+{
+  mpz_clear(key->d);
+  mpz_clear(key->p);
+  mpz_clear(key->q);
+  mpz_clear(key->a);
+  mpz_clear(key->b);
+  mpz_clear(key->c);
+}
+
+int
+rsa_prepare_private_key(struct rsa_private_key *key)
+{
+  /* FIXME: Add further sanity checks. */
+
+  mpz_t n;
+  
+  /* The size of the product is the sum of the sizes of the factors,
+   * or sometimes one less. It's possible but tricky to compute the
+   * size without computing the full product. */
+
+  mpz_init(n);
+  mpz_mul(n, key->p, key->q);
+
+  key->size = _rsa_check_size(n);
+
+  mpz_clear(n);
+  
+  return (key->size > 0);
+}
+
+/* Computing an rsa root. */
+void
+rsa_compute_root(const struct rsa_private_key *key,
+		 mpz_t x, const mpz_t m)
+{
+  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);
+}
+
+#endif /* WITH_PUBLIC_KEY */
diff --git a/rsa-verify.c b/rsa-verify.c
new file mode 100644
index 0000000000000000000000000000000000000000..7a6d381fd59b13f4775214bf08967f2d4f1343f7
--- /dev/null
+++ b/rsa-verify.c
@@ -0,0 +1,61 @@
+/* rsa-verify.c
+ *
+ * Verifying RSA signatures.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2001, 2003 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 WITH_PUBLIC_KEY
+
+#include "rsa.h"
+
+#include "bignum.h"
+
+int
+_rsa_verify(const struct rsa_public_key *key,
+	    const mpz_t m,
+	    const mpz_t s)
+{
+  int res;
+  
+  mpz_t m1;
+  
+  if ( (mpz_sgn(s) <= 0)
+       || (mpz_cmp(s, key->n) >= 0) )
+    return 0;
+       
+  mpz_init(m1);
+  
+  mpz_powm(m1, s, key->e, key->n);
+
+  /* FIXME: Is it cheaper to convert m1 to a string and check that? */
+  res = !mpz_cmp(m, m1);
+
+  mpz_clear(m1);
+
+  return res;
+}
+
+#endif /* WITH_PUBLIC_KEY */
diff --git a/rsa.c b/rsa.c
index 16a94bd71d154366173be87e7d326fd0a30e0314..35841789a43c3745463c206f49df44df19f7b64e 100644
--- a/rsa.c
+++ b/rsa.c
@@ -55,11 +55,11 @@ rsa_clear_public_key(struct rsa_public_key *key)
   mpz_clear(key->e);
 }
 
-/* Computes the size, in octets, of a size BITS modulo.
- * Returns 0 if the modulo is too small to be useful. */
+/* Computes the size, in octets, of a the modulo. Returns 0 if the
+ * modulo is too small to be useful. */
 
-static unsigned
-rsa_check_size(mpz_t n)
+unsigned
+_rsa_check_size(mpz_t n)
 {
   /* Round upwards */
   unsigned size = (mpz_sizeinbase(n, 2) + 7) / 8;
@@ -80,115 +80,9 @@ rsa_prepare_public_key(struct rsa_public_key *key)
     return 0;
 #endif
   
-  key->size = rsa_check_size(key->n);
+  key->size = _rsa_check_size(key->n);
   
   return (key->size > 0);
 }
 
-void
-rsa_init_private_key(struct rsa_private_key *key)
-{
-  mpz_init(key->d);
-  mpz_init(key->p);
-  mpz_init(key->q);
-  mpz_init(key->a);
-  mpz_init(key->b);
-  mpz_init(key->c);
-
-  /* Not really necessary, but it seems cleaner to initialize all the
-   * storage. */
-  key->size = 0;
-}
-
-void
-rsa_clear_private_key(struct rsa_private_key *key)
-{
-  mpz_clear(key->d);
-  mpz_clear(key->p);
-  mpz_clear(key->q);
-  mpz_clear(key->a);
-  mpz_clear(key->b);
-  mpz_clear(key->c);
-}
-
-int
-rsa_prepare_private_key(struct rsa_private_key *key)
-{
-  /* FIXME: Add further sanity checks. */
-
-  mpz_t n;
-  
-  /* The size of the product is the sum of the sizes of the factors,
-   * or sometimes one less. It's possible but tricky to compute the
-   * size without computing the full product. */
-
-  mpz_init(n);
-  mpz_mul(n, key->p, key->q);
-
-  key->size = rsa_check_size(n);
-
-  mpz_clear(n);
-  
-  return (key->size > 0);
-}
-
-/* Computing an rsa root. */
-void
-rsa_compute_root(const struct rsa_private_key *key,
-		 mpz_t x, const mpz_t m)
-{
-  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);
-}
-
 #endif /* WITH_PUBLIC_KEY */
diff --git a/rsa.h b/rsa.h
index 6d1c8c9eb12d83e0590ffc5d3fe7d276e3d23ef2..450893810c1deed6dfe4a4b925368f3f5d220ffe 100644
--- a/rsa.h
+++ b/rsa.h
@@ -153,6 +153,27 @@ rsa_sha1_verify(const struct rsa_public_key *key,
                 struct sha1_ctx *hash,
 		const mpz_t signature);
 
+/* Variants taking the digest as argument. */
+void
+rsa_md5_sign_digest(const struct rsa_private_key *key,
+		    const uint8_t *digest,
+		    mpz_t s);
+
+int
+rsa_md5_verify_digest(const struct rsa_public_key *key,
+		      const uint8_t *digest,
+		      const mpz_t signature);
+
+void
+rsa_sha1_sign_digest(const struct rsa_private_key *key,
+		     const uint8_t *digest,
+		     mpz_t s);
+
+int
+rsa_sha1_verify_digest(const struct rsa_public_key *key,
+		       const uint8_t *digest,
+		       const mpz_t signature);
+
 
 /* RSA encryption, using PKCS#1 */
 /* FIXME: These functions uses the v1.5 padding. What should the v2
@@ -177,7 +198,6 @@ rsa_decrypt(const struct rsa_private_key *key,
 	    unsigned *length, uint8_t *cleartext,
 	    const mpz_t ciphertext);
 
-
 /* Compute x, the e:th root of m. Calling it with x == m is allowed. */
 void
 rsa_compute_root(const struct rsa_private_key *key,
@@ -250,4 +270,13 @@ rsa_keypair_to_openpgp(struct nettle_buffer *buffer,
 		       /* A single user id. NUL-terminated utf8. */
 		       const char userid);
 
+/* Internal functions. */
+int
+_rsa_verify(const struct rsa_public_key *key,
+	    const mpz_t m,
+	    const mpz_t s);
+
+unsigned
+_rsa_check_size(mpz_t n);
+
 #endif /* NETTLE_RSA_H_INCLUDED */