Add crypto_sign_publickey() API

This adds a new API crypto_sign_publickey, which works similarly to the
existing crypto_sign_keypair() API, but supports a 32-byte
user-specified seed value (k).

This API is necessary for implementing Ed25519 test vectors, for
example, since we need to pass in a known seed to ensure we're
computing the public key correctly.

The name and implementation are largely borrowed from Brian Warner's
python-ed25519 library. See:

https://github.com/warner/python-ed25519/blob/d42d4b7049baf323e7113359f4f6bf88703543bc/src/ed25519.c#L21

That said, perhaps a different name would be more descriptive, since it
still returns a keypair, not just the public key? Or perhaps that's
needless bikeshedding since this name is already in use.
This commit is contained in:
Tony Arcieri
2013-01-26 13:12:10 -08:00
parent 92e1e0c81c
commit 53d3b5969e
3 changed files with 22 additions and 7 deletions
@@ -6,6 +6,7 @@
#define crypto_sign crypto_sign_ed25519
#define crypto_sign_open crypto_sign_ed25519_open
#define crypto_sign_keypair crypto_sign_ed25519_keypair
#define crypto_sign_publickey crypto_sign_ed25519_publickey
#define crypto_sign_BYTES crypto_sign_ed25519_BYTES
#define crypto_sign_PUBLICKEYBYTES crypto_sign_ed25519_PUBLICKEYBYTES
#define crypto_sign_SECRETKEYBYTES crypto_sign_ed25519_SECRETKEYBYTES
@@ -24,24 +24,36 @@ int crypto_sign_keypair(
unsigned char *pk,
unsigned char *sk
)
{
unsigned char seed[32];
randombytes(seed, 32);
crypto_sign_publickey(pk, sk, seed);
}
int crypto_sign_publickey(
unsigned char *pk,
unsigned char *sk,
unsigned char *seed
)
{
sc25519 scsk;
ge25519 gepk;
unsigned char extsk[64];
int i;
randombytes(sk, 32);
crypto_hash_sha512(extsk, sk, 32);
extsk[0] &= 248;
extsk[31] &= 127;
extsk[31] |= 64;
crypto_hash_sha512(sk, seed, 32);
sk[0] &= 248;
sk[31] &= 127;
sk[31] |= 64;
sc25519_from32bytes(&scsk,extsk);
sc25519_from32bytes(&scsk,sk);
ge25519_scalarmult_base(&gepk, &scsk);
ge25519_pack(pk, &gepk);
for(i=0;i<32;i++)
sk[32 + i] = pk[i];
for(i=0;i<32;i++)
sk[i] = seed[i];
return 0;
}
@@ -12,6 +12,7 @@ extern "C" {
extern int crypto_sign_ed25519_ref(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
extern int crypto_sign_ed25519_ref_open(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *);
extern int crypto_sign_ed25519_ref_keypair(unsigned char *,unsigned char *);
extern int crypto_sign_ed25519_ref_publickey(unsigned char *,unsigned char *,unsigned char *);
#ifdef __cplusplus
}
#endif
@@ -19,6 +20,7 @@ extern int crypto_sign_ed25519_ref_keypair(unsigned char *,unsigned char *);
#define crypto_sign_ed25519 crypto_sign_ed25519_ref
#define crypto_sign_ed25519_open crypto_sign_ed25519_ref_open
#define crypto_sign_ed25519_keypair crypto_sign_ed25519_ref_keypair
#define crypto_sign_ed25519_publickey crypto_sign_ed25519_ref_publickey
#define crypto_sign_ed25519_BYTES crypto_sign_ed25519_ref_BYTES
#define crypto_sign_ed25519_PUBLICKEYBYTES crypto_sign_ed25519_ref_PUBLICKEYBYTES
#define crypto_sign_ed25519_SECRETKEYBYTES crypto_sign_ed25519_ref_SECRETKEYBYTES