// donna.h - written and placed in public domain by Jeffrey Walton // Crypto++ specific implementation wrapped around Andrew // Moon's public domain curve25519-donna and ed25519-donna, // https://github.com/floodyberry/curve25519-donna and // https://github.com/floodyberry/ed25519-donna. // The curve25519 and ed25519 source files multiplex different repos and // architectures using namespaces. The repos are Andrew Moon's // curve25519-donna and ed25519-donna. The architectures are 32-bit, 64-bit // and SSE. For example, 32-bit x25519 uses symbols from Donna::X25519 and // Donna::Arch32. // If needed, see Moon's commit "Go back to ignoring 256th bit [sic]", // https://github.com/floodyberry/curve25519-donna/commit/57a683d18721a658 /// \file donna.h /// \details Functions for curve25519 and ed25519 operations /// \details This header provides the entry points into Andrew Moon's /// curve25519 and ed25519 curve functions. The Crypto++ classes x25519 /// and ed25519 use the functions. The functions are in the Donna /// namespace and are curve25519_mult(), ed25519_publickey(), /// ed25519_sign() and ed25519_sign_open(). /// \details At the moment the hash function for signing is fixed at /// SHA512. #ifndef CRYPTOPP_DONNA_H #define CRYPTOPP_DONNA_H #include "cryptlib.h" #include "stdcpp.h" NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(Donna) //***************************** curve25519 *****************************// /// \brief Generate a public key /// \param publicKey byte array for the public key /// \param secretKey byte array with the private key /// \return 0 on success, non-0 otherwise /// \details curve25519_mult() generates a public key from an existing /// secret key. Internally curve25519_mult() performs a scalar /// multiplication using the base point and writes the result to /// pubkey. int curve25519_mult(byte publicKey[32], const byte secretKey[32]); /// \brief Generate a shared key /// \param sharedKey byte array for the shared secret /// \param secretKey byte array with the private key /// \param othersKey byte array with the peer's public key /// \return 0 on success, non-0 otherwise /// \details curve25519_mult() generates a shared key from an existing /// secret key and the other party's public key. Internally /// curve25519_mult() performs a scalar multiplication using the two keys /// and writes the result to sharedKey. int curve25519_mult(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]); //******************************* ed25519 *******************************// /// \brief Creates a public key from a secret key /// \param publicKey byte array for the public key /// \param secretKey byte array with the private key /// \return 0 on success, non-0 otherwise /// \details ed25519_publickey() generates a public key from a secret key. /// Internally ed25519_publickey() performs a scalar multiplication /// using the secret key and then writes the result to publicKey. int ed25519_publickey(byte publicKey[32], const byte secretKey[32]); /// \brief Creates a signature on a message /// \param message byte array with the message /// \param messageLength size of the message, in bytes /// \param publicKey byte array with the public key /// \param secretKey byte array with the private key /// \param signature byte array for the signature /// \return 0 on success, non-0 otherwise /// \details ed25519_sign() generates a signature on a message using /// the public and private keys. The various buffers can be exact /// sizes, and do not require extra space like when using the /// NaCl library functions. /// \details At the moment the hash function for signing is fixed at /// SHA512. int ed25519_sign(const byte* message, size_t messageLength, const byte secretKey[32], const byte publicKey[32], byte signature[64]); /// \brief Creates a signature on a message /// \param stream std::istream derived class /// \param publicKey byte array with the public key /// \param secretKey byte array with the private key /// \param signature byte array for the signature /// \return 0 on success, non-0 otherwise /// \details ed25519_sign() generates a signature on a message using /// the public and private keys. The various buffers can be exact /// sizes, and do not require extra space like when using the /// NaCl library functions. /// \details This ed25519_sign() overload handles large streams. It /// was added for signing and verifying files that are too large /// for a memory allocation. /// \details At the moment the hash function for signing is fixed at /// SHA512. int ed25519_sign(std::istream& stream, const byte secretKey[32], const byte publicKey[32], byte signature[64]); /// \brief Verifies a signature on a message /// \param message byte array with the message /// \param messageLength size of the message, in bytes /// \param publicKey byte array with the public key /// \param signature byte array with the signature /// \return 0 on success, non-0 otherwise /// \details ed25519_sign_open() verifies a signature on a message using /// the public key. The various buffers can be exact sizes, and do not /// require extra space like when using the NaCl library functions. /// \details At the moment the hash function for signing is fixed at /// SHA512. int ed25519_sign_open(const byte *message, size_t messageLength, const byte publicKey[32], const byte signature[64]); /// \brief Verifies a signature on a message /// \param stream std::istream derived class /// \param publicKey byte array with the public key /// \param signature byte array with the signature /// \return 0 on success, non-0 otherwise /// \details ed25519_sign_open() verifies a signature on a message using /// the public key. The various buffers can be exact sizes, and do not /// require extra space like when using the NaCl library functions. /// \details This ed25519_sign_open() overload handles large streams. It /// was added for signing and verifying files that are too large /// for a memory allocation. /// \details At the moment the hash function for signing is fixed at /// SHA512. int ed25519_sign_open(std::istream& stream, const byte publicKey[32], const byte signature[64]); //****************************** Internal ******************************// #ifndef CRYPTOPP_DOXYGEN_PROCESSING // CRYPTOPP_WORD128_AVAILABLE mostly depends upon GCC support for // __SIZEOF_INT128__. If __SIZEOF_INT128__ is not available then Moon // provides routines for MSC and GCC. It should cover most platforms, // but there are gaps like MS ARM64 and XLC. We tried to enable the // 64-bit path for SunCC from 12.5 but we got the dreaded compile // error "The operand ___LCM cannot be assigned to". #if defined(CRYPTOPP_WORD128_AVAILABLE) || \ (defined(_MSC_VER) && defined(_M_X64)) # define CRYPTOPP_CURVE25519_64BIT 1 #else # define CRYPTOPP_CURVE25519_32BIT 1 #endif // Benchmarking on a modern 64-bit Core i5-6400 @2.7 GHz shows SSE2 on Linux // is not profitable. Here are the numbers in milliseconds/operation: // // * Langley, C++, 0.050 // * Moon, C++: 0.040 // * Moon, SSE2: 0.061 // * Moon, native: 0.045 // // However, a modern 64-bit Core i5-3200 @2.5 GHz shows SSE2 is profitable // for MS compilers. Here are the numbers in milliseconds/operation: // // * x86, no SSE2, 0.294 // * x86, SSE2, 0.097 // * x64, no SSE2, 0.081 // * x64, SSE2, 0.071 #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) && defined(_MSC_VER) # define CRYPTOPP_CURVE25519_SSE2 1 #endif #if (CRYPTOPP_CURVE25519_SSE2) extern int curve25519_mult_SSE2(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]); #endif #endif // CRYPTOPP_DOXYGEN_PROCESSING NAMESPACE_END // Donna NAMESPACE_END // CryptoPP #endif // CRYPTOPP_DONNA_H