| @@ -3,7 +3,7 @@ from gen_file import gen_file | |||||
| crypto_h = gen_file( | crypto_h = gen_file( | ||||
| name = "decaf/crypto_%(shortname)s.h", | name = "decaf/crypto_%(shortname)s.h", | ||||
| doc = """ | doc = """ | ||||
| @brief Example Decaf cyrpto routines. | |||||
| @brief Example Decaf crypto routines. | |||||
| @warning These are merely examples, though they ought to be secure. But real | @warning These are merely examples, though they ought to be secure. But real | ||||
| protocols will decide differently on magic numbers, formats, which items to | protocols will decide differently on magic numbers, formats, which items to | ||||
| hash, etc. | hash, etc. | ||||
| @@ -25,7 +25,7 @@ typedef unsigned char %(c_ns)s_public_key_t[%(C_NS)s_SER_BYTES]; | |||||
| typedef unsigned char %(c_ns)s_signature_t[%(C_NS)s_SER_BYTES + %(C_NS)s_SCALAR_BYTES]; | typedef unsigned char %(c_ns)s_signature_t[%(C_NS)s_SER_BYTES + %(C_NS)s_SCALAR_BYTES]; | ||||
| typedef struct { | typedef struct { | ||||
| /** @cond intetrnal */ | |||||
| /** @cond internal */ | |||||
| /** The symmetric key from which everything is expanded */ | /** The symmetric key from which everything is expanded */ | ||||
| %(c_ns)s_symmetric_key_t sym; | %(c_ns)s_symmetric_key_t sym; | ||||
| @@ -0,0 +1,172 @@ | |||||
| from gen_file import gen_file | |||||
| crypto_hxx = gen_file( | |||||
| name = "decaf/crypto_%(shortname)s.hxx", | |||||
| doc = """ | |||||
| @brief Example Decaf cyrpto routines, C++ wrapper. | |||||
| @warning These are merely examples, though they ought to be secure. But real | |||||
| protocols will decide differently on magic numbers, formats, which items to | |||||
| hash, etc. | |||||
| @warning Experimental! The names, parameter orders etc are likely to change. | |||||
| """, code = """ | |||||
| #include <decaf.hxx> | |||||
| #include <decaf/shake.hxx> | |||||
| /** @cond internal */ | |||||
| #if __cplusplus >= 201103L | |||||
| #define NOEXCEPT noexcept | |||||
| #else | |||||
| #define NOEXCEPT throw() | |||||
| #endif | |||||
| /** @endcond */ | |||||
| namespace decaf { | |||||
| template <typename Group> class PublicKey; | |||||
| template <typename Group> class PrivateKey; | |||||
| template<> class PublicKey<%(cxx_ns)s> | |||||
| : public Serializable< PublicKey<%(cxx_ns)s> > { | |||||
| private: | |||||
| typedef %(c_ns)s_public_key_t Wrapped; | |||||
| Wrapped wrapped; | |||||
| template<class Group> friend class PrivateKey; | |||||
| public: | |||||
| /** @brief Underlying group */ | |||||
| typedef %(cxx_ns)s Group; | |||||
| /** @brief Signature size. */ | |||||
| static const size_t SIG_BYTES = sizeof(%(c_ns)s_signature_t); | |||||
| /** @brief Serialization size. */ | |||||
| static const size_t SER_BYTES = sizeof(Wrapped); | |||||
| /* TODO: convenience types like signature? */ | |||||
| /** @brief Read a private key from a string*/ | |||||
| inline explicit PublicKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT { | |||||
| memcpy(wrapped,b.data(),sizeof(wrapped)); | |||||
| } | |||||
| /** @brief Read a private key from a string*/ | |||||
| inline explicit PublicKey(const PrivateKey<%(cxx_ns)s> &b) NOEXCEPT; | |||||
| /** @brief Create but don't initialize */ | |||||
| inline explicit PublicKey(const NOINIT&) NOEXCEPT { } | |||||
| /** @brief Serialize into a buffer. */ | |||||
| inline void serializeInto(unsigned char *x) const NOEXCEPT { | |||||
| memcpy(x,wrapped,sizeof(wrapped)); | |||||
| } | |||||
| /** @brief Serialization size. */ | |||||
| inline size_t serSize() const NOEXCEPT { return SER_BYTES; } | |||||
| /* TODO: verify_strobe? */ | |||||
| /** @brief Verify a message */ | |||||
| inline void verify( | |||||
| const Block &message, | |||||
| const FixedBlock<SIG_BYTES> &sig | |||||
| ) const throw(CryptoException) { | |||||
| if (DECAF_SUCCESS != %(c_ns)s_verify(sig.data(),wrapped,message.data(),message.size())) { | |||||
| throw(CryptoException()); | |||||
| } | |||||
| } | |||||
| }; | |||||
| template<> class PrivateKey<%(cxx_ns)s> | |||||
| : public Serializable< PrivateKey<%(cxx_ns)s> > { | |||||
| private: | |||||
| typedef %(c_ns)s_private_key_t Wrapped; | |||||
| Wrapped wrapped; | |||||
| template<class Group> friend class PublicKey; | |||||
| public: | |||||
| /** @brief Underlying group */ | |||||
| typedef %(cxx_ns)s Group; | |||||
| /** @brief Signature size. */ | |||||
| static const size_t SIG_BYTES = sizeof(%(c_ns)s_signature_t); | |||||
| /** @brief Serialization size. */ | |||||
| static const size_t SER_BYTES = sizeof(Wrapped); | |||||
| /** @brief Compressed size. */ | |||||
| static const size_t SYM_BYTES = %(C_NS)s_SYMMETRIC_KEY_BYTES; | |||||
| /** @brief Create but don't initialize */ | |||||
| inline explicit PrivateKey(const NOINIT&) NOEXCEPT { } | |||||
| /** @brief Read a private key from a string*/ | |||||
| inline explicit PrivateKey(const FixedBlock<SER_BYTES> &b) NOEXCEPT { | |||||
| memcpy(wrapped,b.data(),sizeof(wrapped)); | |||||
| } | |||||
| /** @brief Read a private key from a string*/ | |||||
| inline explicit PrivateKey(const FixedBlock<SYM_BYTES> &b) NOEXCEPT { | |||||
| %(c_ns)s_derive_private_key(wrapped, b.data()); | |||||
| } | |||||
| /** @brief Create at random */ | |||||
| inline explicit PrivateKey(Rng &r) NOEXCEPT { | |||||
| FixedArrayBuffer<SYM_BYTES> tmp(r); | |||||
| %(c_ns)s_derive_private_key(wrapped, tmp.data()); | |||||
| } | |||||
| /** @brief Secure destructor */ | |||||
| inline ~PrivateKey() NOEXCEPT { | |||||
| %(c_ns)s_destroy_private_key(wrapped); | |||||
| } | |||||
| /** @brief Serialization size. */ | |||||
| inline size_t serSize() const NOEXCEPT { return SER_BYTES; } | |||||
| /** @brief Serialize into a buffer. */ | |||||
| inline void serializeInto(unsigned char *x) const NOEXCEPT { | |||||
| memcpy(x,wrapped,sizeof(wrapped)); | |||||
| } | |||||
| /** @brief Compressed serialize. */ | |||||
| inline SecureBuffer compress() const throw(std::bad_alloc) { | |||||
| SecureBuffer ret(sizeof(wrapped->sym)); | |||||
| memcpy(ret.data(),wrapped->sym,sizeof(wrapped->sym)); | |||||
| return ret; | |||||
| } | |||||
| /** @brief Get the public key */ | |||||
| inline PublicKey<%(cxx_ns)s> pub() const NOEXCEPT { | |||||
| PublicKey<%(cxx_ns)s> ret(*this); return ret; | |||||
| } | |||||
| /** @brief Derive a shared secret */ | |||||
| inline SecureBuffer sharedSecret( | |||||
| const PublicKey<%(cxx_ns)s> &pub, | |||||
| size_t bytes, | |||||
| bool me_first | |||||
| ) const throw(CryptoException,std::bad_alloc) { | |||||
| SecureBuffer ret(bytes); | |||||
| if (DECAF_SUCCESS != %(c_ns)s_shared_secret(ret.data(),bytes,wrapped,pub.wrapped,me_first)) { | |||||
| throw(CryptoException()); | |||||
| } | |||||
| return ret; | |||||
| } | |||||
| /** @brief Sign a message. */ | |||||
| inline SecureBuffer sign(const Block &message) const { | |||||
| SecureBuffer sig(SIG_BYTES); | |||||
| %(c_ns)s_sign(sig.data(), wrapped, message.data(), message.size()); | |||||
| return sig; | |||||
| } | |||||
| }; | |||||
| /** @cond internal */ | |||||
| PublicKey<%(cxx_ns)s>::PublicKey(const PrivateKey<%(cxx_ns)s> &b) NOEXCEPT { | |||||
| %(c_ns)s_private_to_public(wrapped,b.wrapped); | |||||
| } | |||||
| /** @endcond */ | |||||
| #undef NOEXCEPT | |||||
| } /* namespace decaf */ | |||||
| """) | |||||
| @@ -14,6 +14,7 @@ prefixes = { "h" : args.hpre, "hxx" : args.hpre, "c" : args.cpre } | |||||
| from decaf_hxx import decaf_hxx | from decaf_hxx import decaf_hxx | ||||
| from decaf_h import decaf_h | from decaf_h import decaf_h | ||||
| from crypto_h import crypto_h | from crypto_h import crypto_h | ||||
| from crypto_hxx import crypto_hxx | |||||
| root_hxx_code = "\n".join(( | root_hxx_code = "\n".join(( | ||||
| "#include <%s>" % name | "#include <%s>" % name | ||||
| @@ -34,7 +35,7 @@ crypto_h_code = "\n".join(( | |||||
| crypto_h = gen_file( | crypto_h = gen_file( | ||||
| name = "decaf/crypto.h", | name = "decaf/crypto.h", | ||||
| doc = """@brief | doc = """@brief | ||||
| @brief Example Decaf cyrpto routines, metaheader. | |||||
| @brief Example Decaf crypto routines, metaheader. | |||||
| @warning These are merely examples, though they ought to be secure. But real | @warning These are merely examples, though they ought to be secure. But real | ||||
| protocols will decide differently on magic numbers, formats, which items to | protocols will decide differently on magic numbers, formats, which items to | ||||
| hash, etc. | hash, etc. | ||||
| @@ -42,6 +43,22 @@ crypto_h = gen_file( | |||||
| code = "\n"+crypto_h_code+"\n" | code = "\n"+crypto_h_code+"\n" | ||||
| ) | ) | ||||
| crypto_hxx_code = "\n".join(( | |||||
| "#include <%s>" % name | |||||
| for name in sorted(gend_files) | |||||
| if re.match("^decaf/crypto_\d+.hxx$",name) | |||||
| )) | |||||
| crypto_hxx = gen_file( | |||||
| name = "decaf/crypto.hxx", | |||||
| doc = """@brief | |||||
| @brief Example Decaf crypto routines, C++, metaheader. | |||||
| @warning These are merely examples, though they ought to be secure. But real | |||||
| protocols will decide differently on magic numbers, formats, which items to | |||||
| hash, etc. | |||||
| """, | |||||
| code = "\n"+crypto_hxx_code+"\n" | |||||
| ) | |||||
| root_h_code = "\n".join(( | root_h_code = "\n".join(( | ||||
| "#include <%s>" % name | "#include <%s>" % name | ||||
| for name in sorted(gend_files) | for name in sorted(gend_files) | ||||
| @@ -1,216 +0,0 @@ | |||||
| /** | |||||
| * @file decaf/crypto.hxx | |||||
| * @author Mike Hamburg | |||||
| * | |||||
| * @copyright | |||||
| * Copyright (c) 2015 Cryptography Research, Inc. \n | |||||
| * Released under the MIT License. See LICENSE.txt for license information. | |||||
| * | |||||
| * @brief Example cryptography using Decaf. | |||||
| * @warning FIXME: this is out of sync with crypto_*.h | |||||
| */ | |||||
| #ifndef __DECAF_CRYPTO_HXX__ | |||||
| #define __DECAF_CRYPTO_HXX__ 1 | |||||
| #include <decaf.hxx> | |||||
| #include <decaf/shake.hxx> | |||||
| /** @cond internal */ | |||||
| #if __cplusplus >= 201103L | |||||
| #define NOEXCEPT noexcept | |||||
| #else | |||||
| #define NOEXCEPT throw() | |||||
| #endif | |||||
| /** @endcond */ | |||||
| /* TODO: decide on copy vs reference */ | |||||
| namespace decaf { | |||||
| template <typename Group> class PrivateKey; | |||||
| /** @brief A public key using a particular EC group */ | |||||
| template <typename Group> class PublicKey : public Serializable<PublicKey<Group> > { | |||||
| private: | |||||
| /** @cond internal */ | |||||
| friend class PrivateKey<Group>; | |||||
| static const size_t CHALLENGE_BYTES = Group::Scalar::SER_BYTES; | |||||
| //const typename Group::Point p; | |||||
| FixedArrayBuffer<Group::Point::SER_BYTES> ser; | |||||
| /** @endcond */ | |||||
| public: | |||||
| /** Create without init */ | |||||
| PublicKey(NOINIT) : ser(NOINIT()) {} | |||||
| /** SHAKE instance size for sigs etc */ | |||||
| static const size_t SHAKE_BITS = 256; | |||||
| /** Size of a signature */ | |||||
| static const size_t SIG_BYTES = Group::Point::SER_BYTES + Group::Scalar::SER_BYTES; | |||||
| /** @brief Set the public key to a point */ | |||||
| inline explicit PublicKey(const typename Group::Point &p) NOEXCEPT : ser(p.serialize()) {} | |||||
| /** @brief Get the private key for a given public key */ | |||||
| inline explicit PublicKey(const PrivateKey<Group> &priv) NOEXCEPT; | |||||
| /** @brief Read a private key from a string*/ | |||||
| inline explicit PublicKey(const FixedBlock<Group::Point::SER_BYTES> &b) NOEXCEPT : ser(b) {} | |||||
| /** @brief Return the corresponding EC point */ | |||||
| inline typename Group::Point point() const throw(CryptoException) { | |||||
| return typename Group::Point(ser); | |||||
| } | |||||
| /** @brief Verify a sig. TODO: nothrow version? */ | |||||
| inline void verify_shake(const SHAKE<SHAKE_BITS> &ctx_, const FixedBlock<SIG_BYTES> &sig) throw(CryptoException) { | |||||
| SHAKE<SHAKE_BITS> ctx(ctx_); | |||||
| ctx << ser << sig.slice(0,Group::Point::SER_BYTES); | |||||
| FixedArrayBuffer<CHALLENGE_BYTES> challenge; | |||||
| ctx.output(challenge); | |||||
| typename Group::Scalar response; | |||||
| decaf_error_t scalar_OK = Group::Scalar::decode( | |||||
| response, | |||||
| sig.slice(Group::Point::SER_BYTES, Group::Scalar::SER_BYTES) | |||||
| ); | |||||
| const typename Group::Point combo = point().non_secret_combo_with_base( | |||||
| typename Group::Scalar(challenge), response | |||||
| ); | |||||
| if (!decaf_successful(scalar_OK) | |||||
| || combo != typename Group::Point(sig.slice(0,Group::Point::SER_BYTES))) | |||||
| throw CryptoException(); | |||||
| //return scalar_OK & (combo == typename Group::Point(sig.slice(0,Group::Point::SER_BYTES))); | |||||
| } | |||||
| /** @brief Sign from a message. */ | |||||
| inline void verify(const Block &message, const FixedBlock<SIG_BYTES> &sig) throw(CryptoException) { | |||||
| SHAKE<SHAKE_BITS> ctx; | |||||
| ctx << message; | |||||
| verify_shake(ctx,sig); | |||||
| } | |||||
| /** @brief Serialize into a buffer. */ | |||||
| inline void serializeInto(unsigned char *x) const NOEXCEPT { | |||||
| memcpy(x,ser.data(),Group::Point::SER_BYTES); | |||||
| } | |||||
| /** @brief Serialize into a buffer. */ | |||||
| inline size_t serSize() const NOEXCEPT { | |||||
| return Group::Point::SER_BYTES; | |||||
| } | |||||
| /** @brief Copy operator */ | |||||
| inline PublicKey &operator=(const PublicKey &x) NOEXCEPT { ser = x.ser; return *this; } | |||||
| }; | |||||
| /** @brief A private key using a particular EC group */ | |||||
| template <typename Group> class PrivateKey : public Serializable<PrivateKey<Group> > { | |||||
| public: | |||||
| /** Size of associated symmetric key */ | |||||
| static const size_t SYM_BYTES = 32; | |||||
| /** SHAKE instance size for sigs etc */ | |||||
| static const size_t SHAKE_BITS = PublicKey<Group>::SHAKE_BITS; | |||||
| private: | |||||
| /** @cond internal */ | |||||
| static const size_t SCALAR_HASH_BYTES = Group::Scalar::SER_BYTES + 8; | |||||
| friend class PublicKey<Group>; | |||||
| FixedArrayBuffer<SYM_BYTES> sym; | |||||
| typename Group::Scalar scalar; | |||||
| PublicKey<Group> pub_; | |||||
| /** @endcond */ | |||||
| public: | |||||
| /** @brief Don't initialize */ | |||||
| inline PrivateKey(const NOINIT &ni) NOEXCEPT : sym(ni), scalar(ni), pub_(ni) {} | |||||
| /** @brief Construct at random */ | |||||
| inline PrivateKey(Rng &r) : | |||||
| sym(r), | |||||
| scalar(SHAKE<SHAKE_BITS>::hash(sym, SCALAR_HASH_BYTES)), | |||||
| pub_((Group::Precomputed::base() * scalar).serialize()) {} | |||||
| /** @brief Construct from buffer */ | |||||
| inline PrivateKey(const FixedBlock<SYM_BYTES> &sym_) : | |||||
| sym(sym_), | |||||
| scalar(SHAKE<SHAKE_BITS>::hash(sym, SCALAR_HASH_BYTES)), | |||||
| pub_(SecureBuffer(Group::Precomputed::Base * scalar)) {} | |||||
| /** @brief Compressed representation */ | |||||
| inline const FixedBlock<SYM_BYTES> &ser_compressed() const NOEXCEPT { | |||||
| return sym; | |||||
| } | |||||
| /** @brief Serialize */ | |||||
| inline size_t serSize() const NOEXCEPT { | |||||
| return SYM_BYTES; | |||||
| } | |||||
| /** @brief Serialize */ | |||||
| inline void serializeInto(unsigned char *target) const NOEXCEPT { | |||||
| memcpy(target,sym.data(),serSize()); | |||||
| } | |||||
| /** @brief Uncompressed representation */ | |||||
| inline SecureBuffer ser_uncompressed() const throw(std::bad_alloc) { | |||||
| SecureBuffer b(SYM_BYTES + Group::Scalar::SER_BYTES + Group::Point::SER_BYTES); | |||||
| Buffer(b).slice(0,SYM_BYTES).assign(sym); | |||||
| Buffer(b).slice(SYM_BYTES,Group::Scalar::SER_BYTES).assign(scalar); | |||||
| Buffer(b).slice(SYM_BYTES+Group::Scalar::SER_BYTES,Group::Point::SER_BYTES).assign(pub_.ser); | |||||
| return b; | |||||
| } | |||||
| /** @brief Sign from a SHAKE context. TODO: double check random oracle eval of this; destructive version? */ | |||||
| inline SecureBuffer sign_shake(const SHAKE<SHAKE_BITS> &ctx_) throw(std::bad_alloc) { | |||||
| SHAKE<SHAKE_BITS> ctx(ctx_); | |||||
| ctx << sym << "decaf_255_sign_shake"; | |||||
| typename Group::Scalar nonce(ctx.output(SCALAR_HASH_BYTES)); | |||||
| SecureBuffer g_nonce = (Group::Precomputed::base() * nonce).serialize(); | |||||
| ctx = ctx_; | |||||
| ctx << pub_.ser << g_nonce; | |||||
| SecureBuffer challenge(ctx.output(PublicKey<Group>::CHALLENGE_BYTES)); | |||||
| SecureBuffer response((nonce - scalar * typename Group::Scalar(challenge)).serialize()); | |||||
| SecureBuffer ret(PublicKey<Group>::SIG_BYTES); | |||||
| Buffer(ret).slice(0,Group::Point::SER_BYTES).assign(g_nonce); | |||||
| Buffer(ret).slice(Group::Point::SER_BYTES, Group::Scalar::SER_BYTES).assign(response); | |||||
| return ret; | |||||
| } | |||||
| /** @brief Sign from a message. */ | |||||
| inline SecureBuffer sign(const Block &message) { | |||||
| SHAKE<SHAKE_BITS> ctx; | |||||
| ctx << message; | |||||
| return sign_shake(ctx); | |||||
| } | |||||
| /** @brief Get the corresponding public key */ | |||||
| inline const PublicKey<Group> &pub() const { return pub_; } | |||||
| /** @brief Copy operator */ | |||||
| inline PrivateKey &operator=(const PrivateKey &x) NOEXCEPT { | |||||
| sym = x.sym; | |||||
| scalar = x.scalar; | |||||
| pub_ = x.pub_; | |||||
| return *this; | |||||
| } | |||||
| }; | |||||
| /** @cond internal */ | |||||
| template <typename Group> | |||||
| inline PublicKey<Group>::PublicKey( | |||||
| const PrivateKey<Group> &priv | |||||
| ) NOEXCEPT : ser(priv.pub_.ser){} | |||||
| /** @endcond */ | |||||
| #undef NOEXCEPT | |||||
| } /* namespace decaf */ | |||||
| #endif /* __DECAF_CRYPTO_HXX__ */ | |||||
| @@ -376,14 +376,6 @@ int main(int argc, char **argv) { | |||||
| if (argc >= 2 && !strcmp(argv[1], "--micro")) | if (argc >= 2 && !strcmp(argv[1], "--micro")) | ||||
| micro = true; | micro = true; | ||||
| decaf_255_symmetric_key_t r1,r2; | |||||
| memset(r1,1,sizeof(r1)); | |||||
| memset(r2,2,sizeof(r2)); | |||||
| unsigned char umessage[] = {1,2,3,4,5}; | |||||
| size_t lmessage = sizeof(umessage); | |||||
| SpongeRng rng(Block("micro-benchmarks")); | SpongeRng rng(Block("micro-benchmarks")); | ||||
| if (micro) { | if (micro) { | ||||
| printf("\nMicro-benchmarks:\n"); | printf("\nMicro-benchmarks:\n"); | ||||
| @@ -417,76 +409,10 @@ int main(int argc, char **argv) { | |||||
| Benches<Ed448Goldilocks>::micro(); | Benches<Ed448Goldilocks>::micro(); | ||||
| } | } | ||||
| { | |||||
| decaf_255_public_key_t p1,p2; | |||||
| decaf_255_private_key_t s1,s2; | |||||
| decaf_255_signature_t sig1; | |||||
| unsigned char ss[32]; | |||||
| printf("\nMacro-benchmarks for IsoEd25519:\n"); | |||||
| for (Benchmark b("Keygen"); b.iter(); ) { | |||||
| decaf_255_derive_private_key(s1,r1); | |||||
| } | |||||
| decaf_255_private_to_public(p1,s1); | |||||
| decaf_255_derive_private_key(s2,r2); | |||||
| decaf_255_private_to_public(p2,s2); | |||||
| for (Benchmark b("Shared secret"); b.iter(); ) { | |||||
| decaf_bool_t ret = decaf_255_shared_secret(ss,sizeof(ss),s1,p2,1); | |||||
| ignore_result(ret); | |||||
| assert(ret); | |||||
| } | |||||
| for (Benchmark b("Sign"); b.iter(); ) { | |||||
| decaf_255_sign(sig1,s1,umessage,lmessage); | |||||
| } | |||||
| for (Benchmark b("Verify"); b.iter(); ) { | |||||
| decaf_bool_t ret = decaf_255_verify(sig1,p1,umessage,lmessage); | |||||
| rng.read(Buffer(umessage,lmessage)); | |||||
| // umessage[0]++; | |||||
| // umessage[1]^=umessage[0]; | |||||
| ignore_result(ret); | |||||
| } | |||||
| } | |||||
| { | |||||
| decaf_448_public_key_t p1,p2; | |||||
| decaf_448_private_key_t s1,s2; | |||||
| decaf_448_signature_t sig1; | |||||
| unsigned char ss[32]; | |||||
| printf("\nMacro-benchmarks for Ed448-Goldilocks:\n"); | |||||
| for (Benchmark b("Keygen"); b.iter(); ) { | |||||
| decaf_448_derive_private_key(s1,r1); | |||||
| } | |||||
| decaf_448_private_to_public(p1,s1); | |||||
| decaf_448_derive_private_key(s2,r2); | |||||
| decaf_448_private_to_public(p2,s2); | |||||
| for (Benchmark b("Shared secret"); b.iter(); ) { | |||||
| decaf_bool_t ret = decaf_448_shared_secret(ss,sizeof(ss),s1,p2,1); | |||||
| ignore_result(ret); | |||||
| assert(ret); | |||||
| } | |||||
| for (Benchmark b("Sign"); b.iter(); ) { | |||||
| decaf_448_sign(sig1,s1,umessage,lmessage); | |||||
| } | |||||
| for (Benchmark b("Verify"); b.iter(); ) { | |||||
| decaf_bool_t ret = decaf_448_verify(sig1,p1,umessage,lmessage); | |||||
| rng.read(Buffer(umessage,lmessage)); | |||||
| // umessage[0]++; | |||||
| // umessage[1]^=umessage[0]; | |||||
| ignore_result(ret); | |||||
| } | |||||
| } | |||||
| Benches<IsoEd25519>::macro(); | Benches<IsoEd25519>::macro(); | ||||
| Benches<Ed448Goldilocks>::macro(); | Benches<Ed448Goldilocks>::macro(); | ||||
| printf("\n"); | printf("\n"); | ||||
| Benchmark::calib(); | Benchmark::calib(); | ||||
| @@ -11,8 +11,7 @@ | |||||
| #include <decaf.hxx> | #include <decaf.hxx> | ||||
| #include <decaf/shake.hxx> | #include <decaf/shake.hxx> | ||||
| #include <decaf/crypto_255.h> | |||||
| #include <decaf/crypto_448.h> | |||||
| #include <decaf/crypto.h> | |||||
| #include <decaf/crypto.hxx> | #include <decaf/crypto.hxx> | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| @@ -342,75 +341,6 @@ static void test_crypto() { | |||||
| }; // template<GroupId GROUP> | }; // template<GroupId GROUP> | ||||
| static void test_decaf_255() { | |||||
| Test test("Sample crypto"); | |||||
| SpongeRng rng(Block("test_decaf")); | |||||
| decaf_255_symmetric_key_t proto1,proto2; | |||||
| decaf_255_private_key_t s1,s2; | |||||
| decaf_255_public_key_t p1,p2; | |||||
| decaf_255_signature_t sig; | |||||
| unsigned char shared1[1234],shared2[1234]; | |||||
| const char *message = "Hello, world!"; | |||||
| for (int i=0; i<NTESTS && test.passing_now; i++) { | |||||
| rng.read(Buffer(proto1,sizeof(proto1))); | |||||
| rng.read(Buffer(proto2,sizeof(proto2))); | |||||
| decaf_255_derive_private_key(s1,proto1); | |||||
| decaf_255_private_to_public(p1,s1); | |||||
| decaf_255_derive_private_key(s2,proto2); | |||||
| decaf_255_private_to_public(p2,s2); | |||||
| if (DECAF_SUCCESS != decaf_255_shared_secret (shared1,sizeof(shared1),s1,p2,0)) { | |||||
| test.fail(); printf("Fail ss12\n"); | |||||
| } | |||||
| if (DECAF_SUCCESS != decaf_255_shared_secret (shared2,sizeof(shared2),s2,p1,1)) { | |||||
| test.fail(); printf("Fail ss21\n"); | |||||
| } | |||||
| if (memcmp(shared1,shared2,sizeof(shared1))) { | |||||
| test.fail(); printf("Fail ss21 == ss12\n"); | |||||
| } | |||||
| decaf_255_sign (sig,s1,(const unsigned char *)message,strlen(message)); | |||||
| if (DECAF_SUCCESS != decaf_255_verify (sig,p1,(const unsigned char *)message,strlen(message))) { | |||||
| test.fail(); printf("Fail sig ver\n"); | |||||
| } | |||||
| } | |||||
| } | |||||
| /* TODO: don't copy-paste */ | |||||
| static void test_decaf_448() { | |||||
| Test test("Sample crypto"); | |||||
| SpongeRng rng(Block("test_decaf")); | |||||
| decaf_448_symmetric_key_t proto1,proto2; | |||||
| decaf_448_private_key_t s1,s2; | |||||
| decaf_448_public_key_t p1,p2; | |||||
| decaf_448_signature_t sig; | |||||
| unsigned char shared1[1234],shared2[1234]; | |||||
| const char *message = "Hello, world!"; | |||||
| for (int i=0; i<NTESTS && test.passing_now; i++) { | |||||
| rng.read(Buffer(proto1,sizeof(proto1))); | |||||
| rng.read(Buffer(proto2,sizeof(proto2))); | |||||
| decaf_448_derive_private_key(s1,proto1); | |||||
| decaf_448_private_to_public(p1,s1); | |||||
| decaf_448_derive_private_key(s2,proto2); | |||||
| decaf_448_private_to_public(p2,s2); | |||||
| if (DECAF_SUCCESS != decaf_448_shared_secret (shared1,sizeof(shared1),s1,p2,0)) { | |||||
| test.fail(); printf("Fail ss12\n"); | |||||
| } | |||||
| if (DECAF_SUCCESS != decaf_448_shared_secret (shared2,sizeof(shared2),s2,p1,1)) { | |||||
| test.fail(); printf("Fail ss21\n"); | |||||
| } | |||||
| if (memcmp(shared1,shared2,sizeof(shared1))) { | |||||
| test.fail(); printf("Fail ss21 == ss12\n"); | |||||
| } | |||||
| decaf_448_sign (sig,s1,(const unsigned char *)message,strlen(message)); | |||||
| if (DECAF_SUCCESS != decaf_448_verify (sig,p1,(const unsigned char *)message,strlen(message))) { | |||||
| test.fail(); printf("Fail sig ver\n"); | |||||
| } | |||||
| } | |||||
| } | |||||
| int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||
| (void) argc; (void) argv; | (void) argc; (void) argv; | ||||
| @@ -419,7 +349,6 @@ int main(int argc, char **argv) { | |||||
| Tests<IsoEd25519>::test_elligator(); | Tests<IsoEd25519>::test_elligator(); | ||||
| Tests<IsoEd25519>::test_ec(); | Tests<IsoEd25519>::test_ec(); | ||||
| Tests<IsoEd25519>::test_crypto(); | Tests<IsoEd25519>::test_crypto(); | ||||
| test_decaf_255(); | |||||
| printf("\n"); | printf("\n"); | ||||
| printf("Testing %s:\n", Ed448Goldilocks::name()); | printf("Testing %s:\n", Ed448Goldilocks::name()); | ||||
| @@ -427,7 +356,6 @@ int main(int argc, char **argv) { | |||||
| Tests<Ed448Goldilocks>::test_elligator(); | Tests<Ed448Goldilocks>::test_elligator(); | ||||
| Tests<Ed448Goldilocks>::test_ec(); | Tests<Ed448Goldilocks>::test_ec(); | ||||
| Tests<Ed448Goldilocks>::test_crypto(); | Tests<Ed448Goldilocks>::test_crypto(); | ||||
| test_decaf_448(); | |||||
| if (passing) printf("Passed all tests.\n"); | if (passing) printf("Passed all tests.\n"); | ||||