diff --git a/ChangeLog b/ChangeLog
index 0c77dda24d31297f9d7eafc39eba27a27101075c..51fe70970830b0dfb7917ce2d96b5d51e7d0a6ce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,27 @@
 2015-03-18  Niels Möller  <nisse@diamant.hack.org>
 
+	EdDSA interface change, use plain strings to represent keys.
+	* eddsa.h (_ED25519_LIMB_SIZE): Deleted constant.
+	(struct ed25519_private_key, ed25519_public_key): Deleted.
+	* eddsa-expand.c (_eddsa_expand_key): Don't compute the public
+	key.
+	(_eddsa_expand_key_itch): Deleted function.
 	* eddsa-pubkey.c (_eddsa_public_key, _eddsa_public_key_itch): New
 	file, new functions.
+	* ed25519-sha512-pubkey.c (ed25519_sha512_public_key): New file
+	and function.
+	* ed25519-sha512-verify.c (ed25519_sha512_set_public_key): Deleted
+	function.
+	(ed25519_sha512_verify): Use a string to represent the public key.
+	* ed25519-sha512-sign.c (ed25519_sha512_set_private_key): Deleted
+	function.
+	(ed25519_sha512_sign): Use strings for the input key pair.
+	* Makefile.in (hogweed_SOURCES): Added eddsa-pubkey.c and
+	ed25519-sha512-pubkey.c.
+	* testsuite/eddsa-sign-test.c (test_eddsa_sign): Adapt to
+	_eddsa_expand_key changes, and use _eddsa_public_key.
+	* testsuite/ed25519-test.c (test_one): Test
+	ed25519_sha512_public_key, and adapt to new ed25519 interface.
 
 2015-03-14  Niels Möller  <nisse@diamant.hack.org>
 
diff --git a/Makefile.in b/Makefile.in
index 7362a02dc4f437e20a8dbe252513ba836ad116fc..dbe03f4d70f13a239eca57adc9f254702f76b022 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -180,6 +180,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \
 		  curve25519-mul-g.c curve25519-mul.c curve25519-eh-to-x.c \
 		  eddsa-compress.c eddsa-decompress.c eddsa-expand.c \
 		  eddsa-hash.c eddsa-pubkey.c eddsa-sign.c eddsa-verify.c \
+		  ed25519-sha512-pubkey.c \
 		  ed25519-sha512-sign.c ed25519-sha512-verify.c \
 		  $(OPT_HOGWEED_SOURCES)
 
diff --git a/ed25519-sha512-pubkey.c b/ed25519-sha512-pubkey.c
new file mode 100644
index 0000000000000000000000000000000000000000..8e4c52e82deed3a381b18ff2c07e5c272811d19b
--- /dev/null
+++ b/ed25519-sha512-pubkey.c
@@ -0,0 +1,59 @@
+/* ed25519-sha512-pubkey.c
+
+   Copyright (C) 2014, 2015 Niels Möller
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle 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
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "eddsa.h"
+
+#include "ecc-internal.h"
+#include "sha2.h"
+
+void
+ed25519_sha512_public_key (uint8_t *pub, const uint8_t *priv)
+{
+  const struct ecc_curve *ecc = &nettle_curve25519;
+  struct sha512_ctx ctx;
+  uint8_t digest[ED25519_KEY_SIZE];
+  mp_size_t itch = ecc->q.size + _eddsa_public_key_itch (ecc);
+  mp_limb_t *scratch = gmp_alloc_limbs (itch);
+
+#define k scratch
+#define scratch_out (scratch + ecc->q.size)
+
+  _eddsa_expand_key (ecc, &nettle_sha512, &ctx, priv, digest, k);
+  _eddsa_public_key (ecc, k, pub, scratch_out);
+
+  gmp_free_limbs (scratch, itch);
+#undef k
+#undef scratch_out
+}
diff --git a/ed25519-sha512-sign.c b/ed25519-sha512-sign.c
index bbcd133b371f243548a17bafe2fd0a729e66eacd..6adda23579dc0be347bc7bcabcf5ae9b7181fe42 100644
--- a/ed25519-sha512-sign.c
+++ b/ed25519-sha512-sign.c
@@ -1,6 +1,6 @@
 /* ed25519-sha512-sign.c
 
-   Copyright (C) 2014 Niels Möller
+   Copyright (C) 2014, 2015 Niels Möller
 
    This file is part of GNU Nettle.
 
@@ -39,32 +39,29 @@
 #include "sha2.h"
 
 void
-ed25519_sha512_set_private_key (struct ed25519_private_key *priv,
-				const uint8_t *key)
-{
-  mp_size_t itch = _eddsa_expand_key_itch (&nettle_curve25519);
-  mp_limb_t *scratch = gmp_alloc_limbs (itch);
-  struct sha512_ctx ctx;
-
-  _eddsa_expand_key (&nettle_curve25519, &nettle_sha512, &ctx,
-		     key, priv->pub, priv->k1, priv->k2, scratch);
-  gmp_free_limbs (scratch, itch);
-}
-
-void
-ed25519_sha512_sign (const struct ed25519_private_key *priv,
+ed25519_sha512_sign (const uint8_t *pub,
+		     const uint8_t *priv,
 		     size_t length, const uint8_t *msg,
 		     uint8_t *signature)
 {
-  mp_size_t itch = _eddsa_sign_itch (&nettle_curve25519);
+  const struct ecc_curve *ecc = &nettle_curve25519;
+  mp_size_t itch = ecc->q.size + _eddsa_sign_itch (&nettle_curve25519);
   mp_limb_t *scratch = gmp_alloc_limbs (itch);
+#define k2 scratch
+#define scratch_out (scratch + ecc->q.size)
   struct sha512_ctx ctx;
+  uint8_t digest[SHA512_DIGEST_SIZE];
+#define k1 (digest + ED25519_KEY_SIZE)
+
+  _eddsa_expand_key (ecc, &nettle_sha512, &ctx, priv, digest, k2);
 
-  sha512_init (&ctx);
-  sha512_update (&ctx, ED25519_KEY_SIZE, priv->k1);
-  _eddsa_sign (&nettle_curve25519, &nettle_sha512, priv->pub,
+  sha512_update (&ctx, ED25519_KEY_SIZE, k1);
+  _eddsa_sign (&nettle_curve25519, &nettle_sha512, pub,
 	       &ctx,
-	       priv->k2, length, msg, signature, scratch);
+	       k2, length, msg, signature, scratch_out);
 
   gmp_free_limbs (scratch, itch);
+#undef k1
+#undef k2
+#undef scratch_out
 }
diff --git a/ed25519-sha512-verify.c b/ed25519-sha512-verify.c
index 763a9b043f5b06ce455a020e92df1909e336f544..fc9cd01065e9869d5d8fe6e90b27fc9762d1e338 100644
--- a/ed25519-sha512-verify.c
+++ b/ed25519-sha512-verify.c
@@ -1,6 +1,6 @@
 /* ed25519-sha512-verify.c
 
-   Copyright (C) 2014 Niels Möller
+   Copyright (C) 2014, 2015 Niels Möller
 
    This file is part of GNU Nettle.
 
@@ -41,35 +41,25 @@
 #include "sha2.h"
 
 int
-ed25519_sha512_set_public_key (struct ed25519_public_key *pub,
-			       const uint8_t *key)
-{
-  mp_size_t itch = _eddsa_decompress_itch (&nettle_curve25519);
-  mp_limb_t *scratch = gmp_alloc_limbs (itch);
-  int res;
-
-  memcpy (pub->pub, key, sizeof(pub->pub));
-  res = _eddsa_decompress (&nettle_curve25519,
-			   pub->A, key, scratch);
-
-  gmp_free_limbs (scratch, itch);
-  return res;
-}
-
-int
-ed25519_sha512_verify (const struct ed25519_public_key *pub,
+ed25519_sha512_verify (const uint8_t *pub,
 		       size_t length, const uint8_t *msg,
 		       const uint8_t *signature)
 {
-  mp_size_t itch = _eddsa_verify_itch (&nettle_curve25519);
+  const struct ecc_curve *ecc = &nettle_curve25519;
+  mp_size_t itch = 3*ecc->p.size + _eddsa_verify_itch (&nettle_curve25519);
   mp_limb_t *scratch = gmp_alloc_limbs (itch);
   struct sha512_ctx ctx;
   int res;
-
-  res = _eddsa_verify (&nettle_curve25519, &nettle_sha512,
-		       pub->pub, pub->A, &ctx,
-		       length, msg, signature,
-		       scratch);
+#define A scratch
+#define scratch_out (scratch + 3*ecc->p.size)
+  res = (_eddsa_decompress (&nettle_curve25519,
+			    A, pub, scratch_out)
+	 && _eddsa_verify (ecc, &nettle_sha512,
+			   pub, A, &ctx,
+			   length, msg, signature,
+			   scratch_out));
   gmp_free_limbs (scratch, itch);
   return res;
+#undef A
+#undef scratch_out
 }
diff --git a/eddsa-expand.c b/eddsa-expand.c
index 9c0b0b239a7f53b489a58c615b08d8b31b3dd8cf..dc2bfaf199a031889b1fc2da54189fe5af637e48 100644
--- a/eddsa-expand.c
+++ b/eddsa-expand.c
@@ -42,38 +42,23 @@
 #include "ecc-internal.h"
 #include "nettle-meta.h"
 
-mp_size_t
-_eddsa_expand_key_itch (const struct ecc_curve *ecc)
-{
-  assert (_eddsa_compress_itch (ecc) <= ecc->mul_g_itch);
-  return 3*ecc->p.size + ecc->mul_g_itch;
-}
-
-/* Expands a private key, generating the key K1 for nonce generation,
-   the secret scalar K2, and, if PUB is non-NULL, the corresponding
-   public key (in compressed form). */
+/* Expands a private key, generating the secret scalar K2 and leaving
+   the key K1 for nonce generation, at the end of the digest. */
 void
 _eddsa_expand_key (const struct ecc_curve *ecc,
 		   const struct nettle_hash *H,
 		   void *ctx,
 		   const uint8_t *key,
-		   uint8_t *pub,
-		   uint8_t *k1,
-		   mp_limb_t *k2,
-		   mp_limb_t *scratch)
+		   uint8_t *digest,
+		   mp_limb_t *k2)
 {
   size_t nbytes = 1 + ecc->p.bit_size / 8;
-  uint8_t *digest = (uint8_t *) scratch;
-
-#define P scratch
-#define scratch_out (scratch + 3*ecc->p.size)
 
   assert (H->digest_size >= 2*nbytes);
 
   H->init (ctx);
   H->update (ctx, nbytes, key);
   H->digest (ctx, 2*nbytes, digest);
-  memcpy (k1, digest + nbytes, nbytes);
 
   mpn_set_base256_le (k2, ecc->p.size, digest, nbytes);
   /* Clear low 3 bits */
@@ -84,12 +69,4 @@ _eddsa_expand_key (const struct ecc_curve *ecc,
   /* Clear any higher bits. */
   k2[ecc->p.size - 1] &= ~(mp_limb_t) 0
     >> (GMP_NUMB_BITS * ecc->p.size - ecc->p.bit_size);
-
-  if (pub)
-    {
-      ecc->mul_g (ecc, P, k2, scratch_out);
-      _eddsa_compress (ecc, pub, P, scratch_out);
-    }
-#undef P
-#undef scratch_out
 }
diff --git a/eddsa.h b/eddsa.h
index b052ef8294ce446842b86eebe05bf608217c705d..49f1a025c0007f3d50ad137b5edc64cdcb4e2768 100644
--- a/eddsa.h
+++ b/eddsa.h
@@ -42,8 +42,8 @@ extern "C" {
 
 /* Name mangling */
 #define ed25519_sha512_set_private_key nettle_ed25519_sha512_set_private_key
+#define ed25519_sha512_public_key nettle_ed25519_sha512_public_key
 #define ed25519_sha512_sign nettle_ed25519_sha512_sign
-#define ed25519_sha512_set_public_key nettle_ed25519_sha512_set_public_key
 #define ed25519_sha512_verify nettle_ed25519_sha512_verify
 
 #define _eddsa_compress _nettle_eddsa_compress
@@ -51,7 +51,6 @@ extern "C" {
 #define _eddsa_decompress _nettle_eddsa_decompress
 #define _eddsa_decompress_itch _nettle_eddsa_decompress_itch
 #define _eddsa_hash _nettle_eddsa_hash
-#define _eddsa_expand_key_itch _nettle_eddsa_expand_key_itch
 #define _eddsa_expand_key _nettle_eddsa_expand_key
 #define _eddsa_sign _nettle_eddsa_sign
 #define _eddsa_sign_itch _nettle_eddsa_sign_itch
@@ -63,38 +62,17 @@ extern "C" {
 #define ED25519_KEY_SIZE 32
 #define ED25519_SIGNATURE_SIZE 64
 
-/* Number of limbs needed to represent a point coordinate, or a secret
-   exponent (note that exponents are 254 bits, larger than q). */
-#define _ED25519_LIMB_SIZE ((255 + (GMP_NUMB_BITS - 1)) / GMP_NUMB_BITS)
-
-struct ed25519_private_key
-{
-  uint8_t pub[ED25519_KEY_SIZE];
-  uint8_t k1[ED25519_KEY_SIZE];
-  mp_limb_t k2[_ED25519_LIMB_SIZE];
-};
-
 void
-ed25519_sha512_set_private_key (struct ed25519_private_key *priv,
-				const uint8_t *key);
+ed25519_sha512_public_key (uint8_t *pub, const uint8_t *priv);
 
 void
-ed25519_sha512_sign (const struct ed25519_private_key *priv,
+ed25519_sha512_sign (const uint8_t *pub,
+		     const uint8_t *priv,		     
 		     size_t length, const uint8_t *msg,
 		     uint8_t *signature);
 
-struct ed25519_public_key
-{
-  uint8_t pub[ED25519_KEY_SIZE];
-  mp_limb_t A[2*_ED25519_LIMB_SIZE];
-};
-
-int
-ed25519_sha512_set_public_key (struct ed25519_public_key *pub,
-			       const uint8_t *key);
-
 int
-ed25519_sha512_verify (const struct ed25519_public_key *pub,
+ed25519_sha512_verify (const uint8_t *pub,
 		       size_t length, const uint8_t *msg,
 		       const uint8_t *signature);
 
@@ -148,18 +126,13 @@ _eddsa_verify (const struct ecc_curve *ecc,
 	       const uint8_t *signature,
 	       mp_limb_t *scratch);
 
-mp_size_t
-_eddsa_expand_key_itch (const struct ecc_curve *ecc);
-
 void
 _eddsa_expand_key (const struct ecc_curve *ecc,
 		   const struct nettle_hash *H,
 		   void *ctx,
 		   const uint8_t *key,
-		   uint8_t *pub,
-		   uint8_t *k1,
-		   mp_limb_t *k2,
-		   mp_limb_t *scratch);
+		   uint8_t *digest,
+		   mp_limb_t *k2);
 
 mp_size_t
 _eddsa_public_key_itch (const struct ecc_curve *ecc);
diff --git a/testsuite/ed25519-test.c b/testsuite/ed25519-test.c
index 924ecea6e0d4a74e2797a83569035ddda8478596..83b6b84eca6d64113c791f4fda0215729ba01541 100644
--- a/testsuite/ed25519-test.c
+++ b/testsuite/ed25519-test.c
@@ -63,13 +63,12 @@ test_one (const char *line)
   const char *mp;
   uint8_t sk[ED25519_KEY_SIZE];
   uint8_t pk[ED25519_KEY_SIZE];
+  uint8_t t[ED25519_KEY_SIZE];
   uint8_t s[ED25519_SIGNATURE_SIZE];
   uint8_t *msg;
   size_t msg_size;
   uint8_t s2[ED25519_SIGNATURE_SIZE];
 
-  struct ed25519_public_key pub;
-  struct ed25519_private_key priv;
   decode_hex (ED25519_KEY_SIZE, sk, line);
 
   p = strchr (line, ':');
@@ -91,28 +90,27 @@ test_one (const char *line)
 
   decode_hex (msg_size, msg, mp);
 
-  ed25519_sha512_set_private_key (&priv, sk);
-  ASSERT (MEMEQ(ED25519_KEY_SIZE, priv.pub, pk));
+  ed25519_sha512_public_key (t, sk);
+  ASSERT (MEMEQ(ED25519_KEY_SIZE, t, pk));
 
-  ed25519_sha512_sign (&priv, msg_size, msg, s2);
+  ed25519_sha512_sign (pk, sk, msg_size, msg, s2);
   ASSERT (MEMEQ (ED25519_SIGNATURE_SIZE, s, s2));
-  ASSERT (ed25519_sha512_set_public_key (&pub, pk));
 
-  ASSERT (ed25519_sha512_verify (&pub, msg_size, msg, s));
+  ASSERT (ed25519_sha512_verify (pk, msg_size, msg, s));
 
   s2[ED25519_SIGNATURE_SIZE/3] ^= 0x40;
-  ASSERT (!ed25519_sha512_verify (&pub, msg_size, msg, s2));
+  ASSERT (!ed25519_sha512_verify (pk, msg_size, msg, s2));
 
   memcpy (s2, s, ED25519_SIGNATURE_SIZE);
   s2[2*ED25519_SIGNATURE_SIZE/3] ^= 0x40;
-  ASSERT (!ed25519_sha512_verify (&pub, msg_size, msg, s2));
+  ASSERT (!ed25519_sha512_verify (pk, msg_size, msg, s2));
 
-  ASSERT (!ed25519_sha512_verify (&pub, msg_size + 1, msg, s));
+  ASSERT (!ed25519_sha512_verify (pk, msg_size + 1, msg, s));
 
   if (msg_size > 0)
     {
       msg[msg_size-1] ^= 0x20;
-      ASSERT (!ed25519_sha512_verify (&pub, msg_size, msg, s));
+      ASSERT (!ed25519_sha512_verify (pk, msg_size, msg, s));
     }
   free (msg);
 }
diff --git a/testsuite/eddsa-sign-test.c b/testsuite/eddsa-sign-test.c
index 381601dbdbf08829b0225d62bf1ae42b91b93d04..b4d1ca98af75735e7252b41279ae832f39672f24 100644
--- a/testsuite/eddsa-sign-test.c
+++ b/testsuite/eddsa-sign-test.c
@@ -46,21 +46,21 @@ test_eddsa_sign (const struct ecc_curve *ecc,
   uint8_t *signature = xalloc (2*nbytes);
   void *ctx = xalloc (H->context_size);
   uint8_t *public_out = xalloc (nbytes);
-  uint8_t *k1 = xalloc (nbytes);
+  uint8_t *digest = xalloc (2*nbytes);
+  const uint8_t *k1 = digest + nbytes;
   mp_limb_t *k2 = xalloc_limbs (ecc->p.size);
 
   ASSERT (public->length == nbytes);
   ASSERT (private->length == nbytes);
   ASSERT (ref->length == 2*nbytes);
-  ASSERT (_eddsa_expand_key_itch (ecc) <= _eddsa_sign_itch (ecc));
 
   _eddsa_expand_key (ecc, H, ctx, private->data,
-		     public_out,
-		     k1, k2, scratch);
+		     digest, k2);
+  _eddsa_public_key (ecc, k2, public_out, scratch);
 
   if (!MEMEQ (nbytes, public_out, public->data))
     {
-      fprintf (stderr, "Bad public key from _eddsa_expand_key.\n");
+      fprintf (stderr, "Bad public key from _eddsa_expand_key + _eddsa_public_key.\n");
       fprintf (stderr, "got:");
       print_hex (nbytes, public_out);
       fprintf (stderr, "\nref:");
@@ -95,7 +95,7 @@ test_eddsa_sign (const struct ecc_curve *ecc,
   free (scratch);
   free (signature);
   free (ctx);
-  free (k1);
+  free (digest);
   free (k2);
   free (public_out);
 }