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::
 
  544  sha3.sha3_384_init();
 
  550void SHA3_512HashAlgorithm::
 
  553  sha3.sha3_512_init();
 
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
const T * data() const
Accès à la racine du tableau hors toute protection.
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.
constexpr __host__ __device__ pointer data() const noexcept
Pointeur sur le début de la vue.
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Vue d'un tableau d'éléments de type T.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Array< Byte > ByteArray
Tableau dynamique à une dimension de caractères.
Impl::SpanTypeFromSize< conststd::byte, SizeType >::SpanType asBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converti la vue en un tableau d'octets non modifiables.
ConstArrayView< Byte > ByteConstArrayView
Equivalent C d'un tableau à une dimension de caractères.