Add crypto_sign_sk2pk (PR #668)

This should allow users to convert a ed25519 seret key to a public key without rolling their own code
This commit is contained in:
Jeffrey Walton 2018-07-17 08:28:33 -04:00
parent e1433536bc
commit d8946df8eb
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
3 changed files with 41 additions and 3 deletions

View File

@ -3,6 +3,10 @@
// Daniel J. Bernstein, Bernard van Gastel, Wesley Janssen,
// Tanja Lange, Peter Schwabe and Sjaak Smetsers.
// The Tweet API was added to the Crypto++ library to cross-validate results.
// We debated over putting it in the Test namespace, but settled for the NaCl
// namespace to segreate it from other parts of the library.
/// \file naclite.h
/// \brief Crypto++ interface to TweetNaCl library (20140917)
/// \details TweetNaCl is a compact reimplementation of the NaCl library by
@ -373,6 +377,17 @@ int crypto_sign_open(byte *m,word64 *mlen,const byte *sm,word64 n,const byte *pk
/// \since Crypto++ 6.0
int crypto_sign_keypair(byte *pk, byte *sk);
/// \brief Generate a public key from a secret key
/// \param pk public key byte buffer
/// \param sk private key byte buffer
/// \details crypto_sign_sk2pk() creates an ed25519 public key from an existing
/// secret key without the tail public key bytes. The function is not part of
/// libsodium or Tweet API. It was added for interop with the I2P Java library.
/// \returns 0 on success, non-0 otherwise
/// \sa <A HREF="https://nacl.cr.yp.to/sign.html">NaCl crypto_sign documentation</A>
/// \since Crypto++ 7.1
int crypto_sign_sk2pk(byte *pk, const byte *sk);
/// \brief Produce a keystream using XSalsa20
/// \details crypto_stream() uses crypto_stream_xsalsa20
/// \returns 0 on success, non-0 otherwise

View File

@ -755,6 +755,25 @@ int crypto_sign_keypair(byte *pk, byte *sk)
return 0;
}
int crypto_sign_sk2pk(byte *pk, const byte *sk)
{
byte d[64];
gf p[4];
int i;
// randombytes(sk, 32);
crypto_hash(d, sk, 32);
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
scalarbase(p,d);
pack(pk,p);
// for(i=0; i<32; ++i) sk[32 + i] = pk[i];
return 0;
}
static const word64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10};
static void modL(byte *r,sword64 x[64])
@ -895,6 +914,3 @@ NAMESPACE_END // CryptoPP
NAMESPACE_END // NaCl
#endif // NO_OS_DEPENDENCE

View File

@ -455,6 +455,13 @@ bool TestCryptoSignKeys()
{
fail = (crypto_sign_keypair(pk, sk) != 0);
pass = !fail && pass;
byte xk[crypto_sign_PUBLICKEYBYTES];
fail = (crypto_sign_sk2pk(xk, sk) != 0);
pass = !fail && pass;
fail = std::memcmp(xk, pk, sizeof(xk)) != 0;
pass = !fail && pass;
const word32 len = (i == 0 ? 0 : GlobalRNG().GenerateWord32(1, MAX_MESSAGE));
SecByteBlock m(len), sm(len+crypto_sign_BYTES), rm(len+crypto_sign_BYTES);