aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--news.rst3
-rw-r--r--src/cli/speed.cpp14
-rw-r--r--src/lib/hash/hash.cpp15
-rw-r--r--src/lib/hash/keccak/keccak.cpp42
-rw-r--r--src/lib/hash/sha3/sha3.cpp77
-rw-r--r--src/lib/hash/sha3/sha3.h33
-rw-r--r--src/lib/hash/shake/info.txt5
-rw-r--r--src/lib/hash/shake/shake.cpp101
-rw-r--r--src/lib/hash/shake/shake.h81
-rw-r--r--src/lib/stream/shake_cipher/shake_cipher.cpp14
-rw-r--r--src/lib/stream/shake_cipher/shake_cipher.h6
-rw-r--r--src/lib/stream/stream_cipher.cpp2
-rw-r--r--src/tests/data/hash/shake.vec29
13 files changed, 329 insertions, 93 deletions
diff --git a/news.rst b/news.rst
index a8c6257c6..cbb5926a7 100644
--- a/news.rst
+++ b/news.rst
@@ -7,6 +7,9 @@ Version 1.11.34, Not Yet Released
* Fix TLS session resumption bugs which caused resumption failures if an
application used a single session cache for both TLS and DTLS. (GH #688)
+* Add SHAKE-128 and SHAKE-256 XOFs as hash functions supporting paramaterized
+ output lengths.
+
* Add MessageAuthenticationCode::start_msg interface, for MACs which require or
can use a nonce (GH #691)
diff --git a/src/cli/speed.cpp b/src/cli/speed.cpp
index 7fe2a3757..c89ae6046 100644
--- a/src/cli/speed.cpp
+++ b/src/cli/speed.cpp
@@ -347,7 +347,13 @@ class Speed final : public Command
{
using namespace std::placeholders;
- if(auto enc = Botan::get_cipher_mode(algo, Botan::ENCRYPTION))
+ if(Botan::HashFunction::providers(algo).size() > 0)
+ {
+ bench_providers_of<Botan::HashFunction>(
+ algo, provider, msec, buf_size,
+ std::bind(&Speed::bench_hash, this, _1, _2, _3, _4));
+ }
+ else if(auto enc = Botan::get_cipher_mode(algo, Botan::ENCRYPTION))
{
auto dec = Botan::get_cipher_mode(algo, Botan::DECRYPTION);
bench_cipher_mode(*enc, *dec, msec, buf_size);
@@ -364,12 +370,6 @@ class Speed final : public Command
algo, provider, msec, buf_size,
std::bind(&Speed::bench_stream_cipher, this, _1, _2, _3, _4));
}
- else if(Botan::HashFunction::providers(algo).size() > 0)
- {
- bench_providers_of<Botan::HashFunction>(
- algo, provider, msec, buf_size,
- std::bind(&Speed::bench_hash, this, _1, _2, _3, _4));
- }
else if(Botan::MessageAuthenticationCode::providers(algo).size() > 0)
{
bench_providers_of<Botan::MessageAuthenticationCode>(
diff --git a/src/lib/hash/hash.cpp b/src/lib/hash/hash.cpp
index ede2f8c99..112554127 100644
--- a/src/lib/hash/hash.cpp
+++ b/src/lib/hash/hash.cpp
@@ -56,6 +56,10 @@
#include <botan/sha3.h>
#endif
+#if defined(BOTAN_HAS_SHAKE)
+ #include <botan/shake.h>
+#endif
+
#if defined(BOTAN_HAS_SKEIN_512)
#include <botan/skein_512.h>
#endif
@@ -242,6 +246,17 @@ std::unique_ptr<HashFunction> HashFunction::create(const std::string& algo_spec,
}
#endif
+#if defined(BOTAN_HAS_SHAKE)
+ if(req.algo_name() == "SHAKE-128")
+ {
+ return std::unique_ptr<HashFunction>(new SHAKE_128(req.arg_as_integer(0, 128)));
+ }
+ if(req.algo_name() == "SHAKE-256")
+ {
+ return std::unique_ptr<HashFunction>(new SHAKE_256(req.arg_as_integer(0, 256)));
+ }
+#endif
+
#if defined(BOTAN_HAS_WHIRLPOOL)
if(req.algo_name() == "Whirlpool")
{
diff --git a/src/lib/hash/keccak/keccak.cpp b/src/lib/hash/keccak/keccak.cpp
index 60cb20696..e0c67131b 100644
--- a/src/lib/hash/keccak/keccak.cpp
+++ b/src/lib/hash/keccak/keccak.cpp
@@ -44,47 +44,7 @@ void Keccak_1600::clear()
void Keccak_1600::add_data(const byte input[], size_t length)
{
- if(length == 0)
- return;
-
- while(length)
- {
- size_t to_take = std::min(length, m_bitrate / 8 - m_S_pos);
-
- length -= to_take;
-
- while(to_take && m_S_pos % 8)
- {
- m_S[m_S_pos / 8] ^= static_cast<u64bit>(input[0]) << (8 * (m_S_pos % 8));
-
- ++m_S_pos;
- ++input;
- --to_take;
- }
-
- while(to_take && to_take % 8 == 0)
- {
- m_S[m_S_pos / 8] ^= load_le<u64bit>(input, 0);
- m_S_pos += 8;
- input += 8;
- to_take -= 8;
- }
-
- while(to_take)
- {
- m_S[m_S_pos / 8] ^= static_cast<u64bit>(input[0]) << (8 * (m_S_pos % 8));
-
- ++m_S_pos;
- ++input;
- --to_take;
- }
-
- if(m_S_pos == m_bitrate / 8)
- {
- SHA_3::permute(m_S.data());
- m_S_pos = 0;
- }
- }
+ m_S_pos = SHA_3::absorb(m_bitrate, m_S, m_S_pos, input, length);
}
void Keccak_1600::final_result(byte output[])
diff --git a/src/lib/hash/sha3/sha3.cpp b/src/lib/hash/sha3/sha3.cpp
index 3897f0588..2361d7d5b 100644
--- a/src/lib/hash/sha3/sha3.cpp
+++ b/src/lib/hash/sha3/sha3.cpp
@@ -109,16 +109,6 @@ SHA_3::SHA_3(size_t output_bits) :
std::to_string(output_bits));
}
-SHA_3::SHA_3(size_t output_bits, size_t capacity) :
- m_output_bits(output_bits),
- m_bitrate(1600 - capacity),
- m_S(25),
- m_S_pos(0)
- {
- if(capacity == 0 || capacity >= 1600)
- throw Invalid_Argument("Impossible SHA-3 capacity specified");
- }
-
std::string SHA_3::name() const
{
return "SHA-3(" + std::to_string(m_output_bits) + ")";
@@ -135,49 +125,84 @@ void SHA_3::clear()
m_S_pos = 0;
}
-void SHA_3::add_data(const byte input[], size_t length)
+//static
+size_t SHA_3::absorb(size_t bitrate,
+ secure_vector<uint64_t>& S, size_t S_pos,
+ const byte input[], size_t length)
{
- if(length == 0)
- return;
-
- while(length)
+ while(length > 0)
{
- size_t to_take = std::min(length, m_bitrate / 8 - m_S_pos);
+ size_t to_take = std::min(length, bitrate / 8 - S_pos);
length -= to_take;
- while(to_take && m_S_pos % 8)
+ while(to_take && S_pos % 8)
{
- m_S[m_S_pos / 8] ^= static_cast<u64bit>(input[0]) << (8 * (m_S_pos % 8));
+ S[S_pos / 8] ^= static_cast<u64bit>(input[0]) << (8 * (S_pos % 8));
- ++m_S_pos;
+ ++S_pos;
++input;
--to_take;
}
while(to_take && to_take % 8 == 0)
{
- m_S[m_S_pos / 8] ^= load_le<u64bit>(input, 0);
- m_S_pos += 8;
+ S[S_pos / 8] ^= load_le<u64bit>(input, 0);
+ S_pos += 8;
input += 8;
to_take -= 8;
}
while(to_take)
{
- m_S[m_S_pos / 8] ^= static_cast<u64bit>(input[0]) << (8 * (m_S_pos % 8));
+ S[S_pos / 8] ^= static_cast<u64bit>(input[0]) << (8 * (S_pos % 8));
- ++m_S_pos;
+ ++S_pos;
++input;
--to_take;
}
- if(m_S_pos == m_bitrate / 8)
+ if(S_pos == bitrate / 8)
{
- SHA_3::permute(m_S.data());
- m_S_pos = 0;
+ SHA_3::permute(S.data());
+ S_pos = 0;
}
}
+
+ return S_pos;
+ }
+
+//static
+void SHA_3::expand(size_t bitrate,
+ secure_vector<uint64_t>& S,
+ byte output[], size_t output_length)
+ {
+ BOTAN_ARG_CHECK(bitrate % 8 == 0);
+
+ size_t Si = 0;
+
+ for(size_t i = 0; i != output_length; ++i)
+ {
+ if(i > 0)
+ {
+ if(i % (bitrate / 8) == 0)
+ {
+ SHA_3::permute(S.data());
+ Si = 0;
+ }
+ else if(i % 8 == 0)
+ {
+ Si += 1;
+ }
+ }
+
+ output[i] = get_byte(7 - (i % 8), S[Si]);
+ }
+ }
+
+void SHA_3::add_data(const byte input[], size_t length)
+ {
+ m_S_pos = SHA_3::absorb(m_bitrate, m_S, m_S_pos, input, length);
}
void SHA_3::final_result(byte output[])
diff --git a/src/lib/hash/sha3/sha3.h b/src/lib/hash/sha3/sha3.h
index c877bd938..649aa12fd 100644
--- a/src/lib/hash/sha3/sha3.h
+++ b/src/lib/hash/sha3/sha3.h
@@ -27,14 +27,6 @@ class BOTAN_DLL SHA_3 : public HashFunction
*/
SHA_3(size_t output_bits);
- /**
- * @param output_bits the size of the hash output; must be a
- * multiple of 8 (ie, byte-wide outputs)
- * @param capacity the capacity of the spong, normally always
- * 2*output_bits with SHA-3.
- */
- SHA_3(size_t output_bits, size_t capacity);
-
size_t hash_block_size() const override { return m_bitrate / 8; }
size_t output_length() const override { return m_output_bits / 8; }
@@ -42,6 +34,31 @@ class BOTAN_DLL SHA_3 : public HashFunction
std::string name() const override;
void clear() override;
+ // Static functions for internal usage
+
+ /**
+ * Absorb data into the provided state
+ * @param bitrate the bitrate to absorb into the sponge
+ * @param S the sponge state
+ * @param S_pos where to begin absorbing into S
+ * @param input the input data
+ * @param length size of input in bytes
+ */
+ static size_t absorb(size_t bitrate,
+ secure_vector<uint64_t>& S, size_t S_pos,
+ const byte input[], size_t length);
+
+ /**
+ * Expand from provided state
+ * @param bitrate sponge parameter
+ * @param S the state
+ * @param output the output buffer
+ * @param output_length the size of output in bytes
+ */
+ static void expand(size_t bitrate,
+ secure_vector<uint64_t>& S,
+ byte output[], size_t output_length);
+
/**
* The bare Keccak-1600 permutation
*/
diff --git a/src/lib/hash/shake/info.txt b/src/lib/hash/shake/info.txt
new file mode 100644
index 000000000..f579383eb
--- /dev/null
+++ b/src/lib/hash/shake/info.txt
@@ -0,0 +1,5 @@
+define SHAKE 20161009
+
+<requires>
+sha3
+</requires>
diff --git a/src/lib/hash/shake/shake.cpp b/src/lib/hash/shake/shake.cpp
new file mode 100644
index 000000000..1ff6f1fd3
--- /dev/null
+++ b/src/lib/hash/shake/shake.cpp
@@ -0,0 +1,101 @@
+/*
+* SHAKE-128/256 as a hash
+* (C) 2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/shake.h>
+#include <botan/sha3.h>
+#include <botan/parsing.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+SHAKE_128::SHAKE_128(size_t output_bits) :
+ m_output_bits(output_bits), m_S(25), m_S_pos(0)
+ {
+ if(output_bits % 8 != 0)
+ throw Invalid_Argument("SHAKE_128: Invalid output length " +
+ std::to_string(output_bits));
+ }
+
+std::string SHAKE_128::name() const
+ {
+ return "SHAKE-128(" + std::to_string(m_output_bits) + ")";
+ }
+
+HashFunction* SHAKE_128::clone() const
+ {
+ return new SHAKE_128(m_output_bits);
+ }
+
+void SHAKE_128::clear()
+ {
+ zeroise(m_S);
+ m_S_pos = 0;
+ }
+
+void SHAKE_128::add_data(const byte input[], size_t length)
+ {
+ m_S_pos = SHA_3::absorb(SHAKE_128_BITRATE, m_S, m_S_pos, input, length);
+ }
+
+void SHAKE_128::final_result(byte output[])
+ {
+ std::vector<byte> padding(SHAKE_128_BITRATE / 8 - m_S_pos);
+
+ padding[0] = 0x1F;
+ padding[padding.size()-1] |= 0x80;
+
+ add_data(padding.data(), padding.size());
+
+ SHA_3::expand(SHAKE_128_BITRATE, m_S, output, output_length());
+
+ clear();
+ }
+
+SHAKE_256::SHAKE_256(size_t output_bits) :
+ m_output_bits(output_bits), m_S(25), m_S_pos(0)
+ {
+ if(output_bits % 8 != 0)
+ throw Invalid_Argument("SHAKE_256: Invalid output length " +
+ std::to_string(output_bits));
+ }
+
+std::string SHAKE_256::name() const
+ {
+ return "SHAKE-256(" + std::to_string(m_output_bits) + ")";
+ }
+
+HashFunction* SHAKE_256::clone() const
+ {
+ return new SHAKE_256(m_output_bits);
+ }
+
+void SHAKE_256::clear()
+ {
+ zeroise(m_S);
+ m_S_pos = 0;
+ }
+
+void SHAKE_256::add_data(const byte input[], size_t length)
+ {
+ m_S_pos = SHA_3::absorb(SHAKE_256_BITRATE, m_S, m_S_pos, input, length);
+ }
+
+void SHAKE_256::final_result(byte output[])
+ {
+ std::vector<byte> padding(SHAKE_256_BITRATE / 8 - m_S_pos);
+
+ padding[0] = 0x1F;
+ padding[padding.size()-1] |= 0x80;
+
+ add_data(padding.data(), padding.size());
+
+ SHA_3::expand(SHAKE_256_BITRATE, m_S, output, output_length());
+
+ clear();
+ }
+
+}
diff --git a/src/lib/hash/shake/shake.h b/src/lib/hash/shake/shake.h
new file mode 100644
index 000000000..96c171323
--- /dev/null
+++ b/src/lib/hash/shake/shake.h
@@ -0,0 +1,81 @@
+/*
+* SHAKE hash functions
+* (C) 2010,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_SHAKE_HASH_H__
+#define BOTAN_SHAKE_HASH_H__
+
+#include <botan/hash.h>
+#include <botan/secmem.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* SHAKE-128
+*/
+class BOTAN_DLL SHAKE_128 : public HashFunction
+ {
+ public:
+
+ /**
+ * @param output_bits the desired output size in bits
+ * must be a multiple of 8
+ */
+ SHAKE_128(size_t output_bits);
+
+ size_t hash_block_size() const override { return SHAKE_128_BITRATE / 8; }
+ size_t output_length() const override { return m_output_bits / 8; }
+
+ HashFunction* clone() const override;
+ std::string name() const override;
+ void clear() override;
+
+ private:
+ void add_data(const byte input[], size_t length) override;
+ void final_result(byte out[]) override;
+
+ static const size_t SHAKE_128_BITRATE = 1600 - 256;
+
+ size_t m_output_bits;
+ secure_vector<u64bit> m_S;
+ size_t m_S_pos;
+ };
+
+/**
+* SHAKE-256
+*/
+class BOTAN_DLL SHAKE_256 : public HashFunction
+ {
+ public:
+
+ /**
+ * @param output_bits the desired output size in bits
+ * must be a multiple of 8
+ */
+ SHAKE_256(size_t output_bits);
+
+ size_t hash_block_size() const override { return SHAKE_256_BITRATE / 8; }
+ size_t output_length() const override { return m_output_bits / 8; }
+
+ HashFunction* clone() const override;
+ std::string name() const override;
+ void clear() override;
+
+ private:
+ void add_data(const byte input[], size_t length) override;
+ void final_result(byte out[]) override;
+
+ static const size_t SHAKE_256_BITRATE = 1600 - 512;
+
+ size_t m_output_bits;
+ secure_vector<u64bit> m_S;
+ size_t m_S_pos;
+ };
+
+}
+
+#endif
diff --git a/src/lib/stream/shake_cipher/shake_cipher.cpp b/src/lib/stream/shake_cipher/shake_cipher.cpp
index 5701e7802..dc3c73299 100644
--- a/src/lib/stream/shake_cipher/shake_cipher.cpp
+++ b/src/lib/stream/shake_cipher/shake_cipher.cpp
@@ -11,13 +11,13 @@
namespace Botan {
-SHAKE_128::SHAKE_128() :
+SHAKE_128_Cipher::SHAKE_128_Cipher() :
m_state(25),
m_buffer((1600 - 256) / 8),
m_buf_pos(0)
{}
-void SHAKE_128::cipher(const byte in[], byte out[], size_t length)
+void SHAKE_128_Cipher::cipher(const byte in[], byte out[], size_t length)
{
while(length >= m_buffer.size() - m_buf_pos)
{
@@ -35,7 +35,7 @@ void SHAKE_128::cipher(const byte in[], byte out[], size_t length)
m_buf_pos += length;
}
-void SHAKE_128::key_schedule(const byte key[], size_t length)
+void SHAKE_128_Cipher::key_schedule(const byte key[], size_t length)
{
zeroise(m_state);
@@ -51,14 +51,14 @@ void SHAKE_128::key_schedule(const byte key[], size_t length)
copy_out_le(m_buffer.data(), m_buffer.size(), m_state.data());
}
-void SHAKE_128::clear()
+void SHAKE_128_Cipher::clear()
{
zeroise(m_state);
zeroise(m_buffer);
m_buf_pos = 0;
}
-void SHAKE_128::set_iv(const byte[], size_t length)
+void SHAKE_128_Cipher::set_iv(const byte[], size_t length)
{
/*
* This could be supported in some way (say, by treating iv as
@@ -68,8 +68,8 @@ void SHAKE_128::set_iv(const byte[], size_t length)
throw Invalid_IV_Length(name(), length);
}
-void SHAKE_128::seek(u64bit)
+void SHAKE_128_Cipher::seek(u64bit)
{
- throw Not_Implemented("SHAKE_128::seek");
+ throw Not_Implemented("SHAKE_128_Cipher::seek");
}
}
diff --git a/src/lib/stream/shake_cipher/shake_cipher.h b/src/lib/stream/shake_cipher/shake_cipher.h
index 57eda58a4..40915ecea 100644
--- a/src/lib/stream/shake_cipher/shake_cipher.h
+++ b/src/lib/stream/shake_cipher/shake_cipher.h
@@ -16,10 +16,10 @@ namespace Botan {
/**
* SHAKE-128 XOF presented as a stream cipher
*/
-class BOTAN_DLL SHAKE_128 final : public StreamCipher
+class BOTAN_DLL SHAKE_128_Cipher final : public StreamCipher
{
public:
- SHAKE_128();
+ SHAKE_128_Cipher();
/**
* Produce more XOF output
@@ -49,7 +49,7 @@ class BOTAN_DLL SHAKE_128 final : public StreamCipher
void clear() override;
std::string name() const override { return "SHAKE-128"; }
- StreamCipher* clone() const override { return new SHAKE_128; }
+ StreamCipher* clone() const override { return new SHAKE_128_Cipher; }
private:
void key_schedule(const byte key[], size_t key_len) override;
diff --git a/src/lib/stream/stream_cipher.cpp b/src/lib/stream/stream_cipher.cpp
index 4b27caafe..dfe1fa69b 100644
--- a/src/lib/stream/stream_cipher.cpp
+++ b/src/lib/stream/stream_cipher.cpp
@@ -74,7 +74,7 @@ std::unique_ptr<StreamCipher> StreamCipher::create(const std::string& algo_spec,
if(req.algo_name() == "SHAKE-128")
{
if(provider.empty() || provider == "base")
- return std::unique_ptr<StreamCipher>(new SHAKE_128);
+ return std::unique_ptr<StreamCipher>(new SHAKE_128_Cipher);
}
#endif
diff --git a/src/tests/data/hash/shake.vec b/src/tests/data/hash/shake.vec
new file mode 100644
index 000000000..9de8fd53d
--- /dev/null
+++ b/src/tests/data/hash/shake.vec
@@ -0,0 +1,29 @@
+# Selected values from the NIST CAVS file for SHAKE
+
+[SHAKE-128(128)]
+In = 84e950051876050dc851fbd99e6247b8
+Out = 8599bd89f63a848c49ca593ec37a12c6
+
+In = a6fe00064257aa318b621c5eb311d32bb8004c2fa1a969d205d71762cc5d2e633907992629d1b69d9557ff6d5e8deb454ab00f6e497c89a4fea09e257a6fa2074bd818ceb5981b3e3faefd6e720f2d1edd9c5e4a5c51e5009abf636ed5bca53fe159c8287014a1bd904f5c8a7501625f79ac81eb618f478ce21cae6664acffb30572f059e1ad0fc2912264e8f1ca52af26c8bf78e09d75f3dd9fc734afa8770abe0bd78c90cc2ff448105fb16dd2c5b7edd8611a62e537db9331f5023e16d6ec150cc6e706d7c7fcbfff930c7281831fd5c4aff86ece57ed0db882f59a5fe403105d0592ca38a081fed84922873f538ee774f13b8cc09bd0521db4374aec69f4bae6dcb66455822c0b84c91a3474ffac2ad06f0a4423cd2c6a49d4f0d6242d6a1890937b5d9835a5f0ea5b1d01884d22a6c1718e1f60b3ab5e232947c76ef70b344171083c688093b5f1475377e3069863
+Out = 3109d9472ca436e805c6b3db2251a9bc
+
+In = 9202e884fc1fc78b3ba2b78ff17b78a1f9e7e87840ef7713d732dba046e5059d2218533de23b070deee0f8d7f9c387c69107d5ccf4c2334126bcdacd4074dd870b645b5ecd86f9b963178f5a909b22889521136d02c895bdcb8264989e18b5b2746f68b1670985d6c3cee6e05f0d312d2ebe0a23110a86ceef0de2ca08da756486bfe3fc55cb94ae358e64310e209cfe836522b5c98eecbdbae3ba2b25c005e669de320842d40c87e2de711444dc4b43bd9ec3edd45eb1d3538e56839ed54d804454bf9dd42dd7aaf2467552a94a274403f15591d782bb55e3961c9a1a1e35793fa7f182b3dddb5f8c4ed8b3e67116487ee7406a7d00f48e9181763842a5a61b84612f8188ec02edd87f03ffa35a01995507ec406be242c586d9cb24be7186ac3809e360fb63329eff605cfe870bd17db1d9c1db4c308f41e9258327358abf75862874e8b34955b8297a4c783b8e6c3dbae62802c6f0c24be3ee060950f937be94454ae159a652847d533c3467ebbc2197b5877f812cc32b9cbbbb92b6c5d8cf8ae8cd139483114a247592fbb228a87071cf471826eb7a293b140c890ff688ef919a65460de77a524668b895c44f17746fbad1965d36cf8de98160b805953167d1e17a416cda75e309b214ca4667f373ba008cc0cd14aa9ecd8b20e53ea8ba80714874cd5864ea4698dd1062e07923b67928df601f8df3a510b9b2d9623a0b7f9954bbb2798ec1c419711224398c8f85d5bb343cfba992ead9947f5c1a500caf738fb7b8785fe2a3b5f484d9faa81f28f640f21e07716fb551a3ef360ef4a5572480d0a6fde0352b93f0cd49cad5bbe6033f80cceeec724e9f6e6b2ee52dbebed7af6f46af17a3a6dcec553c521c4b082541480e562284fced7d590d47043f2db2a5fa5e370e125ab771847a3a84b7d683cdb1aee81c8b096059229bde7f10ecdde9dbb73ccd6b904d06c2ca2916e798466b23724be170bb22892fa04fa9194381037819675a9790c53377f6c7d9c39695a3062427791c5b5b95e7e44587437ac67c3b4c60bf7da248800bc4bdd5341899fec38a26ed76303206b12e662374d8d3db8b17ce04040efe76e6fdb31220657903c06dee446584d062f7485a8495a6d1a8cf435a2f161b0e9c7069509971c65e3b66942786d39d5d3420f8cab28f2de76c7198ab4a9a13a17a12cf3d710d83702c1dc97abca7c4000194075eb648b23eadd8de6a5c773cde9932f822a2dee4d6604ed28eedc941e153ba3dbd97aa80fdf66cdd3e6e97dfee803aada535ca30b95f5f780d21205c29b1fc61905d9cde4dcc955dd087e143f8b790b47131bbb140afba839c60965d00a4c13d7e10051356b9bb25c7af3db225c79ed52c9e98ad94dac5bbe5b3128b8db3729730b9cf683f4446feccee93729d37cada7f84496ddc68eae890217d30f96675384d60e12531f69eb0874dcbcc878f7e8911ecb53941df90d145b3bd926b4533e87e0b239253552b039fd3ce080b5821ac8bddc659ebc91e3fab70bbf90cd9146e6bc47df6ceeb56bfbd89826e53191b099460631401adfefa6a605faf04a98194bb92d79bc94085ab8875d046845ad369d57c74b3ac1497ca2b8b92fb7a3de020177e19c76dda2190a9a1a0d7c9a4b393f539e27e1385517796fa3a24961e9adb268e2bc3e2439336c715db6a487d22519d9f93bd5f8894c852b4407382d3188d91ccf5d74f0342658bd867472970886975b770b8b7a5c88608c18d3063e4c1feff40604adca095e59cf12eb695024ea4248861b7446555795f2a08a364dafcf519f15266b3a4f67da46b17ffb4bddaca531a4f012d4fa46900f69813aa3c333c87e7b471f997ccf7484b0969ad2895a3a97620df9bec1b1e922d27ca6092cd99f02a6fb4d9ff7e19329bee3da9cbe7f6cfa3be99b6c2235fbed89c0eac6532d5fcc36977796676ac0a63adc4cf2f398d6ca90f77a55b25f62cfdde28b63bc9b854b98c0201531b7777a92e4348dbf12e2991fdc0913f87a983a7d760a79ffc09a014bf9c9a4fd544227759053b5779a2ae626fbea1f4b3416bdb6efda716329287dce98e6ce10cd9b3d41651d12c37b1a2244cb7fe040f868ea38b49dd2ad419b21af4219e9128ffd1c94d6e31e19522aee07ef4cff7053f9106168a72624867c9d6c79a58e7917e245ce6a585fef9bf799decbd3d53fb361f0df8098e46f74473164a44c46cb01e5597c93ef20ccd4eac637e5a70a25b31debe170e575f497758e4656607a7eba70c82de81a2927898ee3a1c128f6b8cf976235ce0f834a7ca214700474c20abe0f0240eb5bd186265e82bae2ec337f6569044afc9974e770376480330b9605992aa853f246a26f37d413d1cf6338d010fd427f90f5d3322ebfeed566976ee5b85e2ad5a14d24593a7a2794eb208f515eee9d620fb716d114a6240e23aac521b813fa548ce1dfcaaadb3e52daa69f79ab978590ed5fb84abe84a498deb8315ff4e6974ef9a72d4a0551b8c9f267f1cf83928b6a9e525fe578c5c0f40c322be71b3092239bff954dd6883738d6d71eb9736a2f7db7215657f00439ae40bb2d5d87ac7b80d87dc04c9ad92a4e0c868ede0788d248bc6f3408a0aa5f25f0c5ae39c694a3d5238406ccdeef1267e7f8ca839c69243a127e818e0732b209b0b436f24493bb9f21b4f154ff1470151da04a60be9595e04de1c74e9027c2b7e539401dae14134d4783186b97f3d3d4020f96fbfaa897c9e33b6dc0c81411bf22b762125fb05b7e0970e4771607be3329b9289bbcfcaa6566dded8b4b621f8deda11586d5d2e49febf0de1e15ca8fb1191f87e6920c6e314d6bef1466bc5cb29a98c2d1bd065f3163a56db6f3b6c8bc44b52d63067223bc0b47bae2b66d49cbde01029951c52bc104e12bd85c4719d3311c917776a89b643504098cb70f77181c7c4d244099cacd44469108ac05c38462b85cba8f2a15d83f233358e50d6545da5d1b3905feccb4b64825ae6f8d865e5e0ad792ac7123769e27c10ddd0184c39c45e51e2e5e9225bf5862600318b2bf8796aaa65b1854cdd6744ae1eb66561fd6a9436a0643cb8ed419cf942361d92673ee3e5c178a2a5c8cab399bbcb679c92e09be934a58c95ea8eed5d13ce37a21a7741b2a6e310491054f0581ad7c304de6e9af2046d82c23825a1d9dbc08164f96cab997cbc78409f4a2473a5a224a2ca5bb9da7a87c646c14edff603d5a2dfed654a23abc981935bf77672c2f3307c3ef12227fcbaff296b50cf3af1d5431bdca945d79bd3d4492ea20fdedb938f9d2376fa64f4cdd57420759a2f0e880b21b081c53eb4a1186aff92163f574bea0a5f336c16c989f22ec703685dc2b5a3f84f35f2de5ffdf6ffb510b41b9ee1e9ccdc709dc7e3b6fb5f4843604b7626b2a8a30df34202ad160f3a6411fc181d33ec8075b8feaa1c9b0f8b7dab8190a1e13a9250f1ef077a1fa275d654692dc971723589e3448682784777f970877aefd8b50648136fd42cbac04eaea6eb45ab4a64e2f54620dfb13a0ef6fed8e69ad83e21e63b8248d38b8e72ad332e09c88d67cc6f020b1a1d728a6df0d50b255a23bb871a7265056a5e44bf7aae154b1e356fb1c3f557baa88b106b4bc730cc219af9ee8935e52b036f83b09d678239af6b0b1cc8195589e8c47310f01a706356039d5e1dcc2a440584f44cffa69e5ce3f9e31465b52a0e46e75b64c716f273632752dfbd7e5bd8d8663e9b86b3903b23a69ea1821001d128ba7270b805df83afcebe7a5194a16de4dd0aa51bd5815ed539e5cb0873005bf7075d3bac2d5e1ca2bf8936c256238d90b10073a756994e637b5f9bdd264f331c94c7cd89d898c5a4c45c1cf60c0abf46a9c70c107cff923334b518ea7117e1fd29562f394cb4061da3df32d6fe7d8c6e8e08784090dcb2af2b8e4b179c80ee0490b268a2d1db677525b9824a74a57a6e286ac01dd957373d2a933a4deeb1e198908480aeb13571141292143bb5a913af3f96eb91a199a847f76cef72b0d34220f074804432e9ab633214ee8f0ab2df999b3301832eca8d345bc0726f2b0d9a0679296f4b9e209ec84de51a30bbe8659503ea0bdaca106f6c1e37c92da48870b1f34c55ad3b01d0ac2aada00410722d0941630f80bb96d457087afe93666b4c8926843b5152b5cb78921586f55079bf5e1b45185c4982475de1311988b8dfb6f6d97a281f2a6317924dc4d6eac524a4fd5a392b56befd4de6700420f6e10c3760d6d624ff0d343a64236498cab59c634cc6e65256602e705a7e991dc42a19
+Out = d785d35331bd7821c8b4a7672e920b2c
+
+[SHAKE-256(256)]
+In =
+Out = 46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762f
+
+In = 104fefe89f08d15d36a2233f42a7defa917c5ad2642e06cac56d5cc51ad914ecfb7d984f4199b9cf5fa5a03bf69207b9a353a9681c9cf6437bea0c49d9c3e3db1f3fc76519c70c40cc1dfdd70a9c150943c272cf9eeb861f485f10100c8f4a3e259c6470501932782512225ba64d70b219cf9d5013a21d25d6d65062dcc6b3deb49d58b90d18933f118df70ff42c807ccc851233a34a221eca56b38971ef858475488988794a975d3894633a19c1ae2f05e9b9c0756affd3cfe823ccf29228f60fa7e025bc39a79943325126409460926b057a3fb28a1b098b938872883804fd2bc245d7fd6d29bcda6ca6198f2eff6ea7e03ef78133de8ba65fc8c45a688160719fa1e7646d878ea44c4b5c2e16f48b
+Out = 46293a63c235750d58a24edca5ba637b96cae74325c6c8122c4155c0d15805e6
+
+In = e17d557607ae1b5bf061f3403ec424df0e8d5bbe208ef460388a75bcc3485beebee51a2dd46e5ffdc6af98a51045b6e4cafb31e0cc534d5f15629d396ee1c50e4a828334f180f1f3dd7a04f5648159f8987031c66c7bba67180b9095beca83704df99b73a60a59a7fd6b401682a09483419462584731c0e0072e56b6fc281d7e8ff567d23a35207fee2953f2b2c9efed8e10cc7fa79be932ab72f8866f261c9ed71cf13af728cde5775d45703c24f39e448c7721d2e1bcc5cc807dec61e9073aee164091230ce84062af1f7767da27ff2eaf6c27112cc10232ffedcf189c66b99d8c5cc10708f9f875c6e8f17d1314761322b27aaca4814fa4985019dd65c283aa264eb0eb458975794ba8c5c4f6406cba8d5100eb708315ebf3afb1f86ca100dd8b1d4816ea1f1e35e567db85ac354aec9652a316b94fbdcfb7117fb1da8e980064d16fd220445d733d2e1b075c7b7671e8bc4a74a66ead188d7f6b50d70eb3d958730f650f7f99f9fb046d942f985a112997dd4e60674f8e1c005d1c8aabb93210090f18de583b90c6f2b9724d165c9402eb43ec0ec20af90d9c3d5e1cec12d1339e5733b657a90046ffe7eadd7de6c11ac16696d9084520075bf35fb559267e6a37cffebe054c112433df4408535f611a202d94e9c06accb34667647b7b5d035dde5fc11fe98c8b089689c8f5222f3ca911802d6572e0c5b86482b899d92027b39aefc3008cd2359931cdbecd71bd1a709b47ab75a70fd3c0be2aa235fcd5b11574674d8a7484d8800b946db7c973c316c66a5443e55fbe705a4869786ae66a2a72afa7e42b0c3c652cc41edcb1b8fe449ad271f4b7384d7242c55689adb91a9b9faf193839d029ee9d471963b1f495a2206549b3a2024a6e7e87b1904db8890f0050ebab243a67c66503a67551904ed75f0c26a630257b0b1478c2b7d0497e2f9f78646776b0bd938ce20d3a1af2f28c5fb04ef5e809a8f20e7fd024c0d6c2a38310cd94b69cf5fe1bcb95d99383496829370ac952169bcb738325ffa4c61e12b4016e596d65d5ae19a5877b45ab1a14c48ba24af7b51b3d4c6e0771058157243b318fdf2273264c8e5a2b47b6d32f3738925e9f5e4ceff0a027bfa26a6f38821f8a784e5d2eaf7f83d1c96670614e7a8e3686f11045e08d779694b95bf888d468f371cda7fe3af0fef2a9fffbbf4085cd5d61679306b6bcdaa3d0de60840ec11e53c184864b8d460aa5133bdd53ccfffdf1382a71f93924cf36b93b027b93f24a94b19c847d722aacd24e42a087bc9127d953613184306e613799f5c845df0ff49d893d29fcae44ee61a33bcbc2d7e252fdfa355c116541958eb6373b4ababf2256918efc300c3bd73a5a4ee76be49b864575ce79079e4675235927e1f2ecaadea710b8858253b86f46bba57becac63cb990b5310cea42508dec9ed45a63c792f7850e24c584a62bf6b0d650facf7e32ae106ecaace3f8556a850b2eccc74d41eb19735da1bbbe2ce929ab92c138cc2aa05acc3ce6e360e6867349e60ce5a62b13a2ed9b6
+Out = 3c4a422bb47db5ef8e4e4029dd172d757258b1419444059799761138ce404944
+
+[SHAKE-128(1120)]
+In = 0a13ad2c7a239b4ba73ea6592ae84ea9
+Out = 5feaf99c15f48851943ff9baa6e5055d8377f0dd347aa4dbece51ad3a6d9ce0c01aee9fe2260b80a4673a909b532adcdd1e421c32d6460535b5fe392a58d2634979a5a104d6c470aa3306c400b061db91c463b2848297bca2bc26d1864ba49d7ff949ebca50fbf79a5e63716dc82b600bd52ca7437ed774d169f6bf02e46487956fba2230f34cd2a0485484d
+
+[SHAKE-256(2000)]
+In = 8d8001e2c096f1b88e7c9224a086efd4797fbf74a8033a2d422a2b6b8f6747e4
+Out = 2e975f6a8a14f0704d51b13667d8195c219f71e6345696c49fa4b9d08e9225d3d39393425152c97e71dd24601c11abcfa0f12f53c680bd3ae757b8134a9c10d429615869217fdd5885c4db174985703a6d6de94a667eac3023443a8337ae1bc601b76d7d38ec3c34463105f0d3949d78e562a039e4469548b609395de5a4fd43c46ca9fd6ee29ada5efc07d84d553249450dab4a49c483ded250c9338f85cd937ae66bb436f3b4026e859fda1ca571432f3bfc09e7c03ca4d183b741111ca0483d0edabc03feb23b17ee48e844ba2408d9dcfd0139d2e8c7310125aee801c61ab7900d1efc47c078281766f361c5e6111346235e1dc38325666c