14#include "arcane/utils/Array.h"
15#include "arcane/utils/FatalErrorException.h"
16#include "arcane/utils/SHA3HashAlgorithm.h"
56namespace Arcane::SHA3Algorithm
62 constexpr int sha3_max_permutation_size = 25;
63 constexpr int sha3_max_rate_in_qwords = 24;
65 constexpr int NumberOfRounds = 24;
68 constexpr uint64_t keccak_round_constants[NumberOfRounds] = {
69 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000,
70 0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
71 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A,
72 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003,
73 0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A,
74 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
78 static uint64_t _rotateLeft(uint64_t qword,
int n)
80 return ((qword) << (n) ^ ((qword) >> (64 - (n))));
91 uint64_t hash[sha3_max_permutation_size];
93 uint64_t message[sha3_max_rate_in_qwords];
97 unsigned int block_size;
112 static void sha3_permutation(uint64_t* state);
113 static void sha3_process_block(uint64_t hash[25],
const uint64_t* block,
size_t block_size);
120#define le2me_64(x) (x)
121#define me64_to_le_str(to, from, length) std::memcpy((to), (from), (length))
124#define IS_ALIGNED_64(p) (0 == (7 & (uintptr_t)(p)))
134 unsigned rate = 1600 - bits * 2;
136 std::memset(&m_context, 0,
sizeof(sha3_ctx));
137 m_context.block_size = rate / 8;
138 bool is_ok = (rate <= 1600 && (rate % 64) == 0);
143 if (m_context.block_size > 144)
144 ARCANE_FATAL(
"Block size is too big (v={0}) max_allowed=144", m_context.block_size);
191#define XORED_A(i) A[(i)] ^ A[(i) + 5] ^ A[(i) + 10] ^ A[(i) + 15] ^ A[(i) + 20]
192#define THETA_STEP(i) \
194 A[(i) + 5] ^= D[(i)]; \
195 A[(i) + 10] ^= D[(i)]; \
196 A[(i) + 15] ^= D[(i)]; \
197 A[(i) + 20] ^= D[(i)]
207 D[0] = _rotateLeft(XORED_A(1), 1) ^ XORED_A(4);
208 D[1] = _rotateLeft(XORED_A(2), 1) ^ XORED_A(0);
209 D[2] = _rotateLeft(XORED_A(3), 1) ^ XORED_A(1);
210 D[3] = _rotateLeft(XORED_A(4), 1) ^ XORED_A(2);
211 D[4] = _rotateLeft(XORED_A(0), 1) ^ XORED_A(3);
261 A[0 + (i)] ^= ~A1 & A[2 + (i)]; \
262 A[1 + (i)] ^= ~A[2 + (i)] & A[3 + (i)]; \
263 A[2 + (i)] ^= ~A[3 + (i)] & A[4 + (i)]; \
264 A[3 + (i)] ^= ~A[4 + (i)] & A0; \
265 A[4 + (i)] ^= ~A0 & A1
286sha3_permutation(uint64_t* state)
289 for (round = 0; round < NumberOfRounds; round++) {
293 state[1] = _rotateLeft(state[1], 1);
294 state[2] = _rotateLeft(state[2], 62);
295 state[3] = _rotateLeft(state[3], 28);
296 state[4] = _rotateLeft(state[4], 27);
297 state[5] = _rotateLeft(state[5], 36);
298 state[6] = _rotateLeft(state[6], 44);
299 state[7] = _rotateLeft(state[7], 6);
300 state[8] = _rotateLeft(state[8], 55);
301 state[9] = _rotateLeft(state[9], 20);
302 state[10] = _rotateLeft(state[10], 3);
303 state[11] = _rotateLeft(state[11], 10);
304 state[12] = _rotateLeft(state[12], 43);
305 state[13] = _rotateLeft(state[13], 25);
306 state[14] = _rotateLeft(state[14], 39);
307 state[15] = _rotateLeft(state[15], 41);
308 state[16] = _rotateLeft(state[16], 45);
309 state[17] = _rotateLeft(state[17], 15);
310 state[18] = _rotateLeft(state[18], 21);
311 state[19] = _rotateLeft(state[19], 8);
312 state[20] = _rotateLeft(state[20], 18);
313 state[21] = _rotateLeft(state[21], 2);
314 state[22] = _rotateLeft(state[22], 61);
315 state[23] = _rotateLeft(state[23], 56);
316 state[24] = _rotateLeft(state[24], 14);
322 *state ^= keccak_round_constants[round];
342 hash[0] ^= le2me_64(block[0]);
343 hash[1] ^= le2me_64(block[1]);
344 hash[2] ^= le2me_64(block[2]);
345 hash[3] ^= le2me_64(block[3]);
346 hash[4] ^= le2me_64(block[4]);
347 hash[5] ^= le2me_64(block[5]);
348 hash[6] ^= le2me_64(block[6]);
349 hash[7] ^= le2me_64(block[7]);
350 hash[8] ^= le2me_64(block[8]);
352 if (block_size > 72) {
353 hash[9] ^= le2me_64(block[9]);
354 hash[10] ^= le2me_64(block[10]);
355 hash[11] ^= le2me_64(block[11]);
356 hash[12] ^= le2me_64(block[12]);
358 if (block_size > 104) {
359 hash[13] ^= le2me_64(block[13]);
360 hash[14] ^= le2me_64(block[14]);
361 hash[15] ^= le2me_64(block[15]);
362 hash[16] ^= le2me_64(block[16]);
364 if (block_size > 136) {
365 hash[17] ^= le2me_64(block[17]);
370 sha3_permutation(hash);
373#define SHA3_FINALIZED 0x80000000
388 sha3_ctx* ctx = &m_context;
389 const unsigned char* msg =
reinterpret_cast<const unsigned char*
>(bytes.
data());
390 size_t size = bytes.
size();
392 const size_t index = (size_t)ctx->rest;
393 const size_t block_size = (size_t)ctx->block_size;
395 if (ctx->rest & SHA3_FINALIZED)
397 ctx->rest = (unsigned)((ctx->rest + size) % block_size);
401 size_t left = block_size - index;
402 std::memcpy((
char*)ctx->message + index, msg, (size < left ? size : left));
411 while (size >= block_size) {
412 uint64_t* aligned_message_block;
413 if (IS_ALIGNED_64(msg)) {
416 aligned_message_block = (uint64_t*)msg;
419 std::memcpy(ctx->message, msg, block_size);
420 aligned_message_block = ctx->message;
428 std::memcpy(ctx->message, msg, size);
442 sha3_ctx* ctx = &m_context;
443 size_t digest_length = 100 - ctx->block_size / 2;
444 const size_t block_size = ctx->block_size;
445 output_hash.
resize(digest_length);
446 auto* result =
reinterpret_cast<unsigned char*
>(output_hash.
data());
448 if (!(ctx->rest & SHA3_FINALIZED)) {
450 std::memset((
char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);
451 ((
char*)ctx->message)[ctx->rest] |= 0x06;
452 ((
char*)ctx->message)[block_size - 1] |= (char)0x80;
456 ctx->rest = SHA3_FINALIZED;
459 if (block_size <= digest_length)
460 ARCANE_FATAL(
"Bad value: block_size={0} digest_length={1}", block_size, digest_length);
463 me64_to_le_str(result, ctx->hash, digest_length);
480void SHA3HashAlgorithm::
483 using namespace SHA3Algorithm;
486 this->_initialize(sha3);
487 sha3.sha3_update(input);
488 sha3.sha3_final(output);
498 return _computeHash64(asBytes(input64), output);
508 return _computeHash64(bytes, output);
517 return _computeHash64(input, output);
523void SHA3_256HashAlgorithm::
532void SHA3_224HashAlgorithm::
533_initialize(SHA3Algorithm::SHA3& sha3)
535 sha3.sha3_224_init();
541void SHA3_384HashAlgorithm::
542_initialize(SHA3Algorithm::SHA3& sha3)
544 sha3.sha3_384_init();
550void SHA3_512HashAlgorithm::
551_initialize(SHA3Algorithm::SHA3& sha3)
553 sha3.sha3_512_init();
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
void sha3_512_init()
Initialize context before calculating hash.
static void keccak_pi(uint64_t *A)
Keccak pi() transformation.
void sha3_224_init()
Initialize context before calculating hash.
static void sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size)
The core transformation. Process the specified block of data.
static void keccak_theta(uint64_t *A)
Keccak theta() transformation.
void sha3_384_init()
Initialize context before calculating hash.
void sha3_256_init()
Initialize context before calculating hash.
void sha3_final(ByteArray &output_hash)
Store calculated hash into the given array.
void keccak_init(unsigned int bits)
Initializing a sha3 context for given number of output bits.
static void keccak_chi(uint64_t *A)
Keccak chi() transformation.
void sha3_update(Span< const std::byte > bytes)
Calculate message hash.
void computeHash64(Span< const Byte > input, ByteArray &output) final
Calcule la valeur du hash pour le tableau input.
void computeHash(ByteConstArrayView input, ByteArray &output) final
Calcule la valeur du hash pour le tableau input.
Classe de base des vecteurs 1D de données.
const T * data() const
Accès à la racine du tableau hors toute protection.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
Vue constante d'un tableau de type T.
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
constexpr __host__ __device__ pointer data() const noexcept
Pointeur sur le début de la vue.
Vue d'un tableau d'éléments de type T.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-