diff --git a/include/decaf.hxx b/include/decaf.hxx index 5ce71ce..1c103b3 100644 --- a/include/decaf.hxx +++ b/include/decaf.hxx @@ -135,7 +135,7 @@ public: /** @brief Assign from arbitrary-length little-endian byte sequence in C++ string. */ inline Scalar &operator=(const std::string &str) NOEXCEPT { - decaf_448_scalar_decode_long(s,GET_DATA(str),str.length()); return *this; + decaf_448_scalar_decode_long(s,GET_DATA(str),str.size()); return *this; } /** diff --git a/include/shake.h b/include/shake.h index 443882e..000f846 100644 --- a/include/shake.h +++ b/include/shake.h @@ -73,6 +73,18 @@ void sha3_output ( size_t len ) API_VIS; +/** + * @brief Return the default output length of the sponge construction, + * for the purpose of C++ default operators. + * + * Returns n/8 for SHA3-n and 2n/8 for SHAKE-n. + * + * @param [inout] sponge The context. + */ +size_t sponge_default_output_bytes ( + const keccak_sponge_t sponge +) API_VIS; + /** * @brief Destroy a SHA3 or SHAKE sponge context by overwriting it with 0. * @param [out] sponge The context. diff --git a/include/shake.hxx b/include/shake.hxx new file mode 100644 index 0000000..94f8240 --- /dev/null +++ b/include/shake.hxx @@ -0,0 +1,152 @@ +/** + * @file shake.hxx + * @copyright + * Based on CC0 code by David Leon Gil, 2015 \n + * Copyright (c) 2015 Cryptography Research, Inc. \n + * Released under the MIT License. See LICENSE.txt for license information. + * @author Mike Hamburg + * @brief SHA-3-n and SHAKE-n instances, C++ wrapper. + * @warning EXPERIMENTAL! The names, parameter orders etc are likely to change. + */ + +#ifndef __SHAKE_HXX__ +#define __SHAKE_HXX__ + +#include "shake.h" +#include +#include + +/** @cond internal */ +#if __cplusplus >= 201103L +#define NOEXCEPT noexcept +#define EXPLICIT_CON explicit +#define GET_DATA(str) ((const unsigned char *)&(str)[0]) +#else +#define NOEXCEPT throw() +#define EXPLICIT_CON +#define GET_DATA(str) ((const unsigned char *)((str).data())) +#endif +/** @endcond */ + +namespace decaf { + +/** A Keccak sponge internal class */ +class KeccakSponge { +protected: + /** The C-wrapper sponge state */ + keccak_sponge_t sp; + + /** Initialize from parameters */ + inline KeccakSponge(const struct kparams_s *params) NOEXCEPT { sponge_init(sp, params); } + + /** No initialization */ + inline KeccakSponge(const NOINIT &) NOEXCEPT { } + +public: + /** Destructor zeroizes state */ + inline ~KeccakSponge() NOEXCEPT { sponge_destroy(sp); } +}; + +/** + * Hash function derived from Keccak + * @todo throw exceptions when hash is misused. + */ +class KeccakHash : public KeccakSponge { +protected: + /** Initialize from parameters */ + inline KeccakHash(const kparams_s *params) NOEXCEPT : KeccakSponge(params) {} + +public: + /** Add more data to running hash */ + inline void update(const uint8_t *__restrict__ in, size_t len) { sha3_update(sp,in,len); } + + /** Add more data to running hash, C++ version. */ + inline void update(const std::string &s) { sha3_update(sp,GET_DATA(s),s.size()); } + + /** Add more data, stream version. */ + inline KeccakHash &operator<<(const std::string &s) { update(s); return *this; } + + /** Same as <<. */ + inline KeccakHash &operator+=(const std::string &s) { return *this << s; } + + /** + * @brief Output bytes from the sponge. + * @todo make this throw exceptions. + */ + inline void output(unsigned char *c, size_t len) { + sha3_output(sp,c,len); + } + + /** @brief Output bytes from the sponge. */ + inline std::string output(size_t len) { + unsigned char *buffer = new unsigned char[len]; + sha3_output(sp,buffer,len); + std::string out((char *)buffer, len); + delete[] buffer; + return out; + } + + /** @brief Return the sponge's default output size. */ + inline size_t default_output_size() const NOEXCEPT { + return sponge_default_output_bytes(sp); + } + + /** Output the default number of bytes. */ + inline std::string output() { + return output(default_output_size()); + } +}; + +/** Fixed-output-length SHA3 */ +template class SHA3 : public KeccakSponge { +private: + /** Get the parameter template block for this hash */ + const struct kparams_s *get_params(); +public: + /** Initializer */ + inline SHA3() NOEXCEPT : KeccakHash(get_params()) {} +}; + +/** Variable-output-length SHAKE */ +template +class SHAKE : public KeccakSponge { +private: + /** Get the parameter template block for this hash */ + const struct kparams_s *get_params(); +public: + /** Initializer */ + inline SHAKE() NOEXCEPT : KeccakHash(get_params()) {} +}; + +/** @cond internal */ +template<> const struct kparams_s *SHAKE<128>::get_params() { return &SHAKE128_params_s; } +template<> const struct kparams_s *SHAKE<256>::get_params() { return &SHAKE256_params_s; } +template<> const struct kparams_s *SHA3<224>::get_params() { return &SHA3_224_params_s; } +template<> const struct kparams_s *SHA3<256>::get_params() { return &SHA3_256_params_s; } +template<> const struct kparams_s *SHA3<384>::get_params() { return &SHA3_384_params_s; } +template<> const struct kparams_s *SHA3<512>::get_params() { return &SHA3_512_params_s; } +/** @endcond */ + +/** Sponge-based random-number generator */ +class SpongeRng : public KeccakSponge { +public: + /** Initialize, deterministically by default, from C buffer */ + inline SpongeRng( const uint8_t *in, size_t len, bool deterministic = true ) NOEXCEPT + : KeccakSponge(NI) { + spongerng_init_from_buffer(sp,in,len,deterministic); + } + + /** Initialize, deterministically by default, from C++ string */ + inline SpongeRng( const std::string &in, bool deterministic = true ) NOEXCEPT + : KeccakSponge(NI) { + spongerng_init_from_buffer(sp,GET_DATA(in),in.size(),deterministic); + } +}; + +} /* namespace decaf */ + +#undef NOEXCEPT +#undef EXPLICIT_CON +#undef GET_DATA + +#endif /* __SHAKE_HXX__ */ diff --git a/src/shake.c b/src/shake.c index b9e4fcc..c5806b4 100644 --- a/src/shake.c +++ b/src/shake.c @@ -257,6 +257,14 @@ void sponge_hash ( const struct kparams_s SHA3_##n##_params_s = \ { 0, FLAG_ABSORBING, 200-n/4, 0, 0x06, 0x80, n/8, 0 }; +size_t sponge_default_output_bytes ( + const keccak_sponge_t s +) { + return (s->params->maxOut == 0xFF) + ? (200-s->params->rate) + : ((200-s->params->rate)/2); +} + DEFSHAKE(128) DEFSHAKE(256) DEFSHA3(224) diff --git a/test/test_decaf.cxx b/test/test_decaf.cxx index 742e38e..2ae2c40 100644 --- a/test/test_decaf.cxx +++ b/test/test_decaf.cxx @@ -10,7 +10,7 @@ */ #include "decaf.hxx" -#include "shake.h" +#include "shake.hxx" #include typedef decaf::decaf<448>::Scalar Scalar;