2026-08-11 17:33:10 -05:00
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//| SHA3.mqh |
|
|
|
|
|
|
//| Copyright 2026, Niquel Mendoza |
|
|
|
|
|
|
//| https://www.mql5.com |
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
#property copyright "Copyright 2026, Niquel Mendoza"
|
|
|
|
|
|
#property link "https://www.mql5.com"
|
|
|
|
|
|
#property strict
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef CRYPTOBYLEO_SRC_HASH_SHA3_MQH
|
|
|
|
|
|
#define CRYPTOBYLEO_SRC_HASH_SHA3_MQH
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//| |
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
#include "Base.mqh"
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//| |
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-08-20 12:57:05 -05:00
|
|
|
|
//---
|
2026-08-11 17:33:10 -05:00
|
|
|
|
#define SHA3_DELIM_SHA3 (0x06)
|
|
|
|
|
|
#define SHA3_DELIM_SHAKE (0x1F)
|
|
|
|
|
|
|
2026-08-20 12:57:05 -05:00
|
|
|
|
//---
|
2026-08-20 22:15:18 -05:00
|
|
|
|
#define SHA3_256_OUT_BSIZE (32)
|
|
|
|
|
|
#define SHA3_256_BLOCK_SIZE (136)
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
|
#define SHA3_512_OUT_BSIZE (64)
|
|
|
|
|
|
#define SHA3_512_BLOCK_SIZE (72)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
|
#define SHA3_384_OUT_BSIZE (48)
|
|
|
|
|
|
#define SHA3_384_BLOCK_SIZE (104)
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
2026-08-20 12:57:05 -05:00
|
|
|
|
#define SHA3_SHAKE_128_BLOCK_SIZE (168)
|
|
|
|
|
|
#define SHA3_SHAKE_256_BLOCK_SIZE (136)
|
|
|
|
|
|
|
2026-08-11 17:33:10 -05:00
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//| |
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
namespace TSN
|
|
|
|
|
|
{
|
2026-08-20 13:19:48 -05:00
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//| |
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
#define SHA3_LOADINLINE(idx) \
|
|
|
|
|
|
s[idx] ^= ((uint64_t)in[pos++]) | \
|
|
|
|
|
|
((uint64_t)in[pos++] << 8) | \
|
|
|
|
|
|
((uint64_t)in[pos++] << 16) | \
|
|
|
|
|
|
((uint64_t)in[pos++] << 24) | \
|
|
|
|
|
|
((uint64_t)in[pos++] << 32) | \
|
|
|
|
|
|
((uint64_t)in[pos++] << 40) | \
|
|
|
|
|
|
((uint64_t)in[pos++] << 48) | \
|
|
|
|
|
|
((uint64_t)in[pos++] << 56);
|
|
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//| |
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
class CCryptoHashSHA3
|
2026-08-20 11:04:12 -05:00
|
|
|
|
{
|
2026-08-20 13:19:48 -05:00
|
|
|
|
private:
|
|
|
|
|
|
static void SHA3_KECCAK_F(ulong &s[]);
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
CCryptoHashSHA3(void) {}
|
|
|
|
|
|
~CCryptoHashSHA3(void) {}
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
|
union SHA3_UN
|
|
|
|
|
|
{
|
|
|
|
|
|
uchar block[200];
|
|
|
|
|
|
ulong uv[25];
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//--- Por limitaciones del compilador de que no se permite tempaltes medio raras
|
|
|
|
|
|
// en static class lo hare inline
|
|
|
|
|
|
//---
|
|
|
|
|
|
// TChunkBytes = tamaño del bloquje en bytes que se procesar en cada it
|
|
|
|
|
|
// ins= tmaño del inpunt (in)
|
|
|
|
|
|
// in= input
|
|
|
|
|
|
// out=salida
|
|
|
|
|
|
// outl= tamaño de salida
|
|
|
|
|
|
template <typename TChunkBytes, typename TDelimBytes>
|
2026-08-20 17:10:56 -05:00
|
|
|
|
static void SHA3_HASH(const uchar &in[], int ins, uchar &out[], int outl, int o_s)
|
2026-08-20 13:19:48 -05:00
|
|
|
|
{
|
|
|
|
|
|
//--- Iniciales
|
|
|
|
|
|
ulong s[25] = {0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL,
|
|
|
|
|
|
0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL
|
|
|
|
|
|
};
|
|
|
|
|
|
const int rho[25] = {0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14};
|
|
|
|
|
|
const int pi[25] = {0, 10, 20, 5, 15, 16, 1, 11, 21, 6, 7, 17, 2, 12, 22, 23, 8, 18, 3, 13, 14, 24, 9, 19, 4};
|
|
|
|
|
|
const ulong rc[24] =
|
|
|
|
|
|
{
|
|
|
|
|
|
0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
|
|
|
|
|
|
0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
|
|
|
|
|
|
0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
|
|
|
|
|
|
0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
|
|
|
|
|
|
0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
|
|
|
|
|
|
0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--- paso 1 absorcion
|
|
|
|
|
|
int pos = 0;
|
|
|
|
|
|
while(ins - pos >= sizeof(TChunkBytes))
|
|
|
|
|
|
{
|
2026-08-20 13:24:23 -05:00
|
|
|
|
//---- carga inline (72 bytes iniciales el minimo comun entre todos.. de ahi algunos cargan mas..)
|
2026-08-20 13:19:48 -05:00
|
|
|
|
SHA3_LOADINLINE(0)
|
|
|
|
|
|
SHA3_LOADINLINE(1)
|
|
|
|
|
|
SHA3_LOADINLINE(2)
|
|
|
|
|
|
SHA3_LOADINLINE(3)
|
|
|
|
|
|
SHA3_LOADINLINE(4)
|
|
|
|
|
|
SHA3_LOADINLINE(5)
|
|
|
|
|
|
SHA3_LOADINLINE(6)
|
|
|
|
|
|
SHA3_LOADINLINE(7)
|
|
|
|
|
|
SHA3_LOADINLINE(8)
|
|
|
|
|
|
|
|
|
|
|
|
//---- carga manual
|
|
|
|
|
|
for(int idx = 9; idx < (sizeof(TChunkBytes) >> 3); idx++)
|
|
|
|
|
|
{
|
|
|
|
|
|
s[idx] ^= ((uint64_t)in[pos++]) |
|
|
|
|
|
|
((uint64_t)in[pos++] << 8) |
|
|
|
|
|
|
((uint64_t)in[pos++] << 16) |
|
|
|
|
|
|
((uint64_t)in[pos++] << 24) |
|
|
|
|
|
|
((uint64_t)in[pos++] << 32) |
|
|
|
|
|
|
((uint64_t)in[pos++] << 40) |
|
|
|
|
|
|
((uint64_t)in[pos++] << 48) |
|
|
|
|
|
|
((uint64_t)in[pos++] << 56);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
|
// HOT PATH inline aqui mismo
|
|
|
|
|
|
//------- statart of mixing
|
|
|
|
|
|
// Nuestro "valor" en el cual operamos..
|
|
|
|
|
|
/*
|
|
|
|
|
|
mapa=
|
|
|
|
|
|
5 filas 5 columnas y cada valor es un lane de 64 bits
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
//--- Temp
|
|
|
|
|
|
ulong c[5], d[5];
|
|
|
|
|
|
ulong b[25];
|
|
|
|
|
|
|
|
|
|
|
|
//--- Rondas.
|
|
|
|
|
|
for(int r = 0; r < 24; r++)
|
|
|
|
|
|
{
|
|
|
|
|
|
//--- theta
|
|
|
|
|
|
/* wiki
|
|
|
|
|
|
Calcula la paridad de cada una de las 5 w (320, cuando w = 64 )
|
|
|
|
|
|
columnas de 5 bits y realiza la operación OR exclusiva con dos columnas cercanas siguiendo un patrón regular.
|
|
|
|
|
|
Para ser precisos, a [ i ][ j ][ k ] ← a [ i ][ j ][ k ] ⊕ paridad(a[0...4][ j -1][ k ]) ⊕ paridad(a[0...4][ j +1][ k −1] )
|
|
|
|
|
|
*/
|
|
|
|
|
|
// Por cada columna
|
|
|
|
|
|
/*for(int x = 0; x < 5; x++)
|
|
|
|
|
|
c[x] = s[x] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20];
|
|
|
|
|
|
*/ // Denserollado:
|
|
|
|
|
|
c[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
|
|
|
|
|
|
c[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
|
|
|
|
|
|
c[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
|
|
|
|
|
|
c[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
|
|
|
|
|
|
c[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
|
|
|
|
|
|
|
|
|
|
|
|
// Final
|
|
|
|
|
|
//for(int x = 0; x < 5; x++)
|
|
|
|
|
|
/*{
|
|
|
|
|
|
const ulong cr = c[(x + 1) % 5];
|
|
|
|
|
|
d[x] = c[(x + 4) % 5] ^ ((cr << 1) | (cr >> 63));
|
|
|
|
|
|
}*/
|
|
|
|
|
|
// Denserollado
|
|
|
|
|
|
{
|
|
|
|
|
|
const ulong cr = c[1];
|
|
|
|
|
|
d[0] = c[4] ^ ((cr << 1) | (cr >> 63));
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
const ulong cr = c[2];
|
|
|
|
|
|
d[1] = c[0] ^ ((cr << 1) | (cr >> 63));
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
const ulong cr = c[3];
|
|
|
|
|
|
d[2] = c[1] ^ ((cr << 1) | (cr >> 63));
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
const ulong cr = c[4];
|
|
|
|
|
|
d[3] = c[2] ^ ((cr << 1) | (cr >> 63));
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
const ulong cr = c[0];
|
|
|
|
|
|
d[4] = c[3] ^ ((cr << 1) | (cr >> 63));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// unrrolled
|
|
|
|
|
|
s[0] ^= d[0];
|
|
|
|
|
|
s[1] ^= d[1];
|
|
|
|
|
|
s[2] ^= d[2];
|
|
|
|
|
|
s[3] ^= d[3];
|
|
|
|
|
|
s[4] ^= d[4];
|
|
|
|
|
|
s[5] ^= d[0];
|
|
|
|
|
|
s[6] ^= d[1];
|
|
|
|
|
|
s[7] ^= d[2];
|
|
|
|
|
|
s[8] ^= d[3];
|
|
|
|
|
|
s[9] ^= d[4];
|
|
|
|
|
|
s[10] ^= d[0];
|
|
|
|
|
|
s[11] ^= d[1];
|
|
|
|
|
|
s[12] ^= d[2];
|
|
|
|
|
|
s[13] ^= d[3];
|
|
|
|
|
|
s[14] ^= d[4];
|
|
|
|
|
|
s[15] ^= d[0];
|
|
|
|
|
|
s[16] ^= d[1];
|
|
|
|
|
|
s[17] ^= d[2];
|
|
|
|
|
|
s[18] ^= d[3];
|
|
|
|
|
|
s[19] ^= d[4];
|
|
|
|
|
|
s[20] ^= d[0];
|
|
|
|
|
|
s[21] ^= d[1];
|
|
|
|
|
|
s[22] ^= d[2];
|
|
|
|
|
|
s[23] ^= d[3];
|
|
|
|
|
|
s[24] ^= d[4];
|
|
|
|
|
|
|
|
|
|
|
|
//--- RHO+PI
|
|
|
|
|
|
for(int i = 0; i < 25; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
/*
|
|
|
|
|
|
Gire bit a bit cada una de las 25 palabras por un número triangular diferente 0, 1, 3, 6, 10, 15, .... (rho[])
|
|
|
|
|
|
Para ser precisos, a [0][0] no se rota, y para todo 0 ≤ t < 24 ,
|
|
|
|
|
|
a [ i ][ j ][ k ] ← a [ i ][ j ][ k −( t +1)( t +2)/2] , donde
|
|
|
|
|
|
*/
|
|
|
|
|
|
const int n = rho[i];
|
|
|
|
|
|
b[pi[i]] = (n == 0) ? s[i] : ((s[i] << n) | (s[i] >> (64 - n)));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//--- CHI fila a fila
|
|
|
|
|
|
for(int y = 0; y < 5; y++)
|
|
|
|
|
|
{
|
|
|
|
|
|
/*
|
|
|
|
|
|
Combinación bit a bit a lo largo de las filas, usando x ← x ⊕ (¬ y & z ) . Para ser precisos, a
|
|
|
|
|
|
[ i ][ j ][ k ] ← a [ i ][ j ][ k ] ⊕ (¬ a [ i ][ j + 1 ][ k ] &a a
|
|
|
|
|
|
[ i ][ j + 2 ][ k ]) . Esta es la única operación no lineal en SHA-3.
|
|
|
|
|
|
*/
|
|
|
|
|
|
//---
|
|
|
|
|
|
ulong row0 = b[5 * y], row1 = b[1 + 5 * y], row2 = b[2 + 5 * y], row3 = b[3 + 5 * y], row4 = b[4 + 5 * y];
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
|
s[5 * y] = row0 ^ ((~row1) & row2);
|
|
|
|
|
|
s[1 + 5 * y] = row1 ^ ((~row2) & row3);
|
|
|
|
|
|
s[2 + 5 * y] = row2 ^ ((~row3) & row4);
|
|
|
|
|
|
s[3 + 5 * y] = row3 ^ ((~row4) & row0);
|
|
|
|
|
|
s[4 + 5 * y] = row4 ^ ((~row0) & row1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//--- iota
|
|
|
|
|
|
s[0] ^= rc[r];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----
|
|
|
|
|
|
//------- end of mixing
|
|
|
|
|
|
//pos += sizeof(TChunkBytes);
|
|
|
|
|
|
}
|
|
|
|
|
|
// Lo demas ya no inline dado que no da una ganancia sinficativa por lo visto
|
|
|
|
|
|
// dado qeu se llama poco...
|
|
|
|
|
|
|
|
|
|
|
|
//--- ultimo bloque parcial + padding (0x06 o 0x1F ... 0x80)
|
|
|
|
|
|
SHA3_UN v;
|
|
|
|
|
|
ArrayInitialize(v.block, 0);
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
|
const int rem = ins - pos;
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
|
for(int i = 0; i < rem; i++)
|
2026-08-20 17:10:56 -05:00
|
|
|
|
v.block[i] = in[pos + i];
|
2026-08-20 13:19:48 -05:00
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
|
v.block[rem] = sizeof(TDelimBytes);
|
|
|
|
|
|
v.block[sizeof(TChunkBytes) - 1] |= 0x80;
|
|
|
|
|
|
|
|
|
|
|
|
//--- Ahora lo que sobra..
|
|
|
|
|
|
const int fin = (sizeof(TChunkBytes) >> 3);
|
|
|
|
|
|
for(int i = 0; i < fin; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
/*const ulong w = ((ulong)block[i]) | ((ulong)block[i + 1] << 8) |
|
|
|
|
|
|
((ulong)block[i + 2] << 16) | ((ulong)block[i + 3] << 24) |
|
|
|
|
|
|
((ulong)block[i + 4] << 32) | ((ulong)block[i + 5] << 40) |
|
|
|
|
|
|
((ulong)block[i + 6] << 48) | ((ulong)block[i + 7] << 56);*/
|
|
|
|
|
|
s[i] ^= v.uv[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
SHA3_KECCAK_F(s);
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
|
// Print("hola", sizeof(TDelimBytes));
|
|
|
|
|
|
if(sizeof(TDelimBytes) == SHA3_DELIM_SHA3)
|
|
|
|
|
|
{
|
2026-08-20 17:10:56 -05:00
|
|
|
|
const int fin = (outl >> 3); // / 8
|
|
|
|
|
|
for(int k = 0; k < fin;)
|
2026-08-20 13:19:48 -05:00
|
|
|
|
{
|
|
|
|
|
|
const ulong t = s[k++];
|
2026-08-20 17:10:56 -05:00
|
|
|
|
out[o_s++] = uchar(t);
|
|
|
|
|
|
out[o_s++] = uchar(t >> 8);
|
|
|
|
|
|
out[o_s++] = uchar(t >> 16);
|
|
|
|
|
|
out[o_s++] = uchar(t >> 24);
|
|
|
|
|
|
out[o_s++] = uchar(t >> 32);
|
|
|
|
|
|
out[o_s++] = uchar(t >> 40);
|
|
|
|
|
|
out[o_s++] = uchar(t >> 48);
|
|
|
|
|
|
out[o_s++] = uchar(t >> 56);
|
2026-08-20 13:19:48 -05:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-08-20 13:24:23 -05:00
|
|
|
|
else // dinamico
|
2026-08-20 13:19:48 -05:00
|
|
|
|
{
|
2026-08-20 17:10:56 -05:00
|
|
|
|
outl += o_s;
|
|
|
|
|
|
while(o_s < outl)
|
2026-08-20 13:24:23 -05:00
|
|
|
|
{
|
|
|
|
|
|
//---
|
2026-08-20 17:10:56 -05:00
|
|
|
|
int t = outl - o_s; // tomado
|
2026-08-20 13:24:23 -05:00
|
|
|
|
if(t > sizeof(TChunkBytes))
|
|
|
|
|
|
t = sizeof(TChunkBytes); // clamp a lo maximo a tomar..
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
|
for(int i = 0; i < t; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
// en que lane
|
|
|
|
|
|
// const int w = ; // i / 8
|
|
|
|
|
|
const int sh = (i & 7) << 3; // i % 8 * 8 - cuanto demzpasmroes del lane de 64 desde cuando se mrpiza
|
2026-08-20 17:10:56 -05:00
|
|
|
|
out[o_s + i] = (uchar)(s[i >> 3] >> sh); // escribimos
|
2026-08-20 13:24:23 -05:00
|
|
|
|
}
|
2026-08-20 17:10:56 -05:00
|
|
|
|
o_s += t; // aumentaos lo que ya tenemos
|
2026-08-20 13:19:48 -05:00
|
|
|
|
|
2026-08-20 13:24:23 -05:00
|
|
|
|
//---
|
2026-08-20 17:10:56 -05:00
|
|
|
|
if(o_s < outl) // volvemos.. se requier mas de lo normal asi qeu aplicanos denuevo para la nueva salida
|
2026-08-20 13:24:23 -05:00
|
|
|
|
SHA3_KECCAK_F(s);
|
|
|
|
|
|
}
|
2026-08-20 13:19:48 -05:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-20 17:10:56 -05:00
|
|
|
|
//---- Especificos
|
|
|
|
|
|
static __forceinline void SHA3_256(const uchar &in[], int ins, uchar &out[], const int o_s);
|
2026-08-20 22:15:18 -05:00
|
|
|
|
static __forceinline void SHA3_384(const uchar &in[], int ins, uchar &out[], const int o_s);
|
2026-08-20 17:10:56 -05:00
|
|
|
|
static __forceinline void SHA3_512(const uchar &in[], int ins, uchar &out[], const int o_s);
|
|
|
|
|
|
static __forceinline void SHAKE128(const uchar &in[], int ins, uchar &out[], int outl, const int o_s);
|
|
|
|
|
|
static __forceinline void SHAKE256(const uchar &in[], int ins, uchar &out[], int outl, const int o_s);
|
2026-08-20 11:04:12 -05:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-08-20 13:19:48 -05:00
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//| |
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-08-11 17:33:10 -05:00
|
|
|
|
//--- keccak-f[1600] funcion base
|
|
|
|
|
|
// s =arrya de entarad (25) size ya con
|
2026-08-20 13:19:48 -05:00
|
|
|
|
static void CCryptoHashSHA3::SHA3_KECCAK_F(ulong &s[])
|
2026-08-11 17:33:10 -05:00
|
|
|
|
{
|
|
|
|
|
|
//--- Constatnes
|
|
|
|
|
|
static const int rho[25] = {0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14};
|
|
|
|
|
|
static const int pi[25] = {0, 10, 20, 5, 15, 16, 1, 11, 21, 6, 7, 17, 2, 12, 22, 23, 8, 18, 3, 13, 14, 24, 9, 19, 4};
|
|
|
|
|
|
static const ulong rc[24] =
|
|
|
|
|
|
{
|
|
|
|
|
|
0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
|
|
|
|
|
|
0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
|
|
|
|
|
|
0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
|
|
|
|
|
|
0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
|
|
|
|
|
|
0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
|
|
|
|
|
|
0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
|
|
|
|
|
|
};
|
|
|
|
|
|
// Nuestro "valor" en el cual operamos..
|
|
|
|
|
|
/*
|
|
|
|
|
|
mapa=
|
|
|
|
|
|
5 filas 5 columnas y cada valor es un lane de 64 bits
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
//--- Temp
|
|
|
|
|
|
ulong c[5], d[5];
|
|
|
|
|
|
ulong b[25];
|
|
|
|
|
|
|
|
|
|
|
|
//--- Rondas.
|
|
|
|
|
|
for(int r = 0; r < 24; r++)
|
|
|
|
|
|
{
|
|
|
|
|
|
//--- theta
|
|
|
|
|
|
/* wiki
|
|
|
|
|
|
Calcula la paridad de cada una de las 5 w (320, cuando w = 64 )
|
|
|
|
|
|
columnas de 5 bits y realiza la operación OR exclusiva con dos columnas cercanas siguiendo un patrón regular.
|
|
|
|
|
|
Para ser precisos, a [ i ][ j ][ k ] ← a [ i ][ j ][ k ] ⊕ paridad(a[0...4][ j -1][ k ]) ⊕ paridad(a[0...4][ j +1][ k −1] )
|
|
|
|
|
|
*/
|
|
|
|
|
|
// Por cada columna
|
2026-08-11 18:00:24 -05:00
|
|
|
|
/*for(int x = 0; x < 5; x++)
|
2026-08-11 17:33:10 -05:00
|
|
|
|
c[x] = s[x] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20];
|
2026-08-11 18:00:24 -05:00
|
|
|
|
*/ // Denserollado:
|
|
|
|
|
|
c[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
|
|
|
|
|
|
c[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
|
|
|
|
|
|
c[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
|
|
|
|
|
|
c[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
|
|
|
|
|
|
c[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
|
2026-08-11 17:33:10 -05:00
|
|
|
|
|
|
|
|
|
|
// Final
|
2026-08-11 18:00:24 -05:00
|
|
|
|
//for(int x = 0; x < 5; x++)
|
|
|
|
|
|
/*{
|
|
|
|
|
|
const ulong cr = c[(x + 1) % 5];
|
|
|
|
|
|
d[x] = c[(x + 4) % 5] ^ ((cr << 1) | (cr >> 63));
|
|
|
|
|
|
}*/
|
|
|
|
|
|
// Denserollado
|
2026-08-11 17:33:10 -05:00
|
|
|
|
{
|
2026-08-11 18:00:24 -05:00
|
|
|
|
const ulong cr = c[1];
|
|
|
|
|
|
d[0] = c[4] ^ ((cr << 1) | (cr >> 63));
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
const ulong cr = c[2];
|
|
|
|
|
|
d[1] = c[0] ^ ((cr << 1) | (cr >> 63));
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
const ulong cr = c[3];
|
|
|
|
|
|
d[2] = c[1] ^ ((cr << 1) | (cr >> 63));
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
const ulong cr = c[4];
|
|
|
|
|
|
d[3] = c[2] ^ ((cr << 1) | (cr >> 63));
|
|
|
|
|
|
}
|
|
|
|
|
|
{
|
|
|
|
|
|
const ulong cr = c[0];
|
|
|
|
|
|
d[4] = c[3] ^ ((cr << 1) | (cr >> 63));
|
2026-08-11 17:33:10 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// unrrolled
|
|
|
|
|
|
s[0] ^= d[0];
|
|
|
|
|
|
s[1] ^= d[1];
|
|
|
|
|
|
s[2] ^= d[2];
|
|
|
|
|
|
s[3] ^= d[3];
|
|
|
|
|
|
s[4] ^= d[4];
|
|
|
|
|
|
s[5] ^= d[0];
|
|
|
|
|
|
s[6] ^= d[1];
|
|
|
|
|
|
s[7] ^= d[2];
|
|
|
|
|
|
s[8] ^= d[3];
|
|
|
|
|
|
s[9] ^= d[4];
|
|
|
|
|
|
s[10] ^= d[0];
|
|
|
|
|
|
s[11] ^= d[1];
|
|
|
|
|
|
s[12] ^= d[2];
|
|
|
|
|
|
s[13] ^= d[3];
|
|
|
|
|
|
s[14] ^= d[4];
|
|
|
|
|
|
s[15] ^= d[0];
|
|
|
|
|
|
s[16] ^= d[1];
|
|
|
|
|
|
s[17] ^= d[2];
|
|
|
|
|
|
s[18] ^= d[3];
|
|
|
|
|
|
s[19] ^= d[4];
|
|
|
|
|
|
s[20] ^= d[0];
|
|
|
|
|
|
s[21] ^= d[1];
|
|
|
|
|
|
s[22] ^= d[2];
|
|
|
|
|
|
s[23] ^= d[3];
|
|
|
|
|
|
s[24] ^= d[4];
|
|
|
|
|
|
|
|
|
|
|
|
//--- RHO+PI
|
|
|
|
|
|
for(int i = 0; i < 25; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
/*
|
|
|
|
|
|
Gire bit a bit cada una de las 25 palabras por un número triangular diferente 0, 1, 3, 6, 10, 15, .... (rho[])
|
|
|
|
|
|
Para ser precisos, a [0][0] no se rota, y para todo 0 ≤ t < 24 ,
|
|
|
|
|
|
a [ i ][ j ][ k ] ← a [ i ][ j ][ k −( t +1)( t +2)/2] , donde
|
|
|
|
|
|
*/
|
|
|
|
|
|
const int n = rho[i];
|
|
|
|
|
|
b[pi[i]] = (n == 0) ? s[i] : ((s[i] << n) | (s[i] >> (64 - n)));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//--- CHI fila a fila
|
|
|
|
|
|
for(int y = 0; y < 5; y++)
|
|
|
|
|
|
{
|
|
|
|
|
|
/*
|
|
|
|
|
|
Combinación bit a bit a lo largo de las filas, usando x ← x ⊕ (¬ y & z ) . Para ser precisos, a
|
|
|
|
|
|
[ i ][ j ][ k ] ← a [ i ][ j ][ k ] ⊕ (¬ a [ i ][ j + 1 ][ k ] &a a
|
|
|
|
|
|
[ i ][ j + 2 ][ k ]) . Esta es la única operación no lineal en SHA-3.
|
|
|
|
|
|
*/
|
|
|
|
|
|
//---
|
|
|
|
|
|
ulong row0 = b[5 * y], row1 = b[1 + 5 * y], row2 = b[2 + 5 * y], row3 = b[3 + 5 * y], row4 = b[4 + 5 * y];
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
|
s[5 * y] = row0 ^ ((~row1) & row2);
|
|
|
|
|
|
s[1 + 5 * y] = row1 ^ ((~row2) & row3);
|
|
|
|
|
|
s[2 + 5 * y] = row2 ^ ((~row3) & row4);
|
|
|
|
|
|
s[3 + 5 * y] = row3 ^ ((~row4) & row0);
|
|
|
|
|
|
s[4 + 5 * y] = row4 ^ ((~row0) & row1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//--- iota
|
|
|
|
|
|
s[0] ^= rc[r];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-11 18:27:38 -05:00
|
|
|
|
|
2026-08-11 17:33:10 -05:00
|
|
|
|
|
2026-08-20 12:57:05 -05:00
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//| |
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
#define SHA3_CHUNKT_IMP(BYTES, DLIM, P) \
|
|
|
|
|
|
struct SHA3_CHUNKT_BUFFER_##P \
|
|
|
|
|
|
{ \
|
|
|
|
|
|
const uchar data[BYTES]; \
|
|
|
|
|
|
}; \
|
|
|
|
|
|
struct SHA3_DLIM_BUFFER_##P \
|
|
|
|
|
|
{ \
|
2026-08-20 13:19:48 -05:00
|
|
|
|
const uchar data[DLIM]; \
|
2026-08-20 12:57:05 -05:00
|
|
|
|
};
|
2026-08-20 22:15:18 -05:00
|
|
|
|
|
2026-08-20 12:57:05 -05:00
|
|
|
|
//---
|
|
|
|
|
|
SHA3_CHUNKT_IMP(SHA3_256_BLOCK_SIZE, SHA3_DELIM_SHA3, SHA3_256)
|
2026-08-20 22:15:18 -05:00
|
|
|
|
SHA3_CHUNKT_IMP(SHA3_384_BLOCK_SIZE, SHA3_DELIM_SHA3, SHA3_384)
|
2026-08-20 12:57:05 -05:00
|
|
|
|
SHA3_CHUNKT_IMP(SHA3_512_BLOCK_SIZE, SHA3_DELIM_SHA3, SHA3_512)
|
|
|
|
|
|
SHA3_CHUNKT_IMP(SHA3_SHAKE_128_BLOCK_SIZE, SHA3_DELIM_SHAKE, SHA3_SHAKE_128)
|
|
|
|
|
|
SHA3_CHUNKT_IMP(SHA3_SHAKE_256_BLOCK_SIZE, SHA3_DELIM_SHAKE, SHA3_SHAKE_256)
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-08-11 18:00:24 -05:00
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
|
//| Esepcific implemtantion |
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-08-20 17:10:56 -05:00
|
|
|
|
static __forceinline void CCryptoHashSHA3::SHA3_256(const uchar &in[], int ins, uchar &out[], const int o_s)
|
2026-08-11 18:00:24 -05:00
|
|
|
|
{
|
2026-08-20 22:15:18 -05:00
|
|
|
|
CCryptoHashSHA3::SHA3_HASH<SHA3_CHUNKT_BUFFER_SHA3_256, SHA3_DLIM_BUFFER_SHA3_256>(in, ins, out, SHA3_256_OUT_BSIZE, o_s);
|
|
|
|
|
|
}
|
|
|
|
|
|
static __forceinline void CCryptoHashSHA3::SHA3_384(const uchar &in[], int ins, uchar &out[], const int o_s)
|
|
|
|
|
|
{
|
|
|
|
|
|
CCryptoHashSHA3::SHA3_HASH<SHA3_CHUNKT_BUFFER_SHA3_384, SHA3_DLIM_BUFFER_SHA3_384>(in, ins, out, SHA3_384_OUT_BSIZE, o_s);
|
2026-08-11 18:00:24 -05:00
|
|
|
|
}
|
2026-08-20 17:10:56 -05:00
|
|
|
|
static __forceinline void CCryptoHashSHA3::SHA3_512(const uchar &in[], int ins, uchar &out[], const int o_s)
|
2026-08-11 18:00:24 -05:00
|
|
|
|
{
|
2026-08-20 22:15:18 -05:00
|
|
|
|
CCryptoHashSHA3::SHA3_HASH<SHA3_CHUNKT_BUFFER_SHA3_512, SHA3_DLIM_BUFFER_SHA3_512>(in, ins, out, SHA3_512_OUT_BSIZE, o_s);
|
2026-08-11 18:00:24 -05:00
|
|
|
|
}
|
2026-08-20 17:10:56 -05:00
|
|
|
|
static __forceinline void CCryptoHashSHA3::SHAKE128(const uchar &in[], int ins, uchar &out[], int outl, const int o_s)
|
2026-08-11 18:00:24 -05:00
|
|
|
|
{
|
2026-08-20 17:10:56 -05:00
|
|
|
|
CCryptoHashSHA3::SHA3_HASH<SHA3_CHUNKT_BUFFER_SHA3_SHAKE_128, SHA3_DLIM_BUFFER_SHA3_SHAKE_128>(in, ins, out, outl, o_s);
|
2026-08-11 18:00:24 -05:00
|
|
|
|
}
|
2026-08-20 17:10:56 -05:00
|
|
|
|
static __forceinline void CCryptoHashSHA3::SHAKE256(const uchar &in[], int ins, uchar &out[], int outl, const int o_s)
|
2026-08-11 18:00:24 -05:00
|
|
|
|
{
|
2026-08-20 17:10:56 -05:00
|
|
|
|
CCryptoHashSHA3::SHA3_HASH<SHA3_CHUNKT_BUFFER_SHA3_SHAKE_256, SHA3_DLIM_BUFFER_SHA3_SHAKE_256>(in, ins, out, outl, o_s);
|
2026-08-11 18:00:24 -05:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-08-11 17:33:10 -05:00
|
|
|
|
//---
|
|
|
|
|
|
}
|
|
|
|
|
|
//---
|
|
|
|
|
|
#endif // CRYPTOBYLEO_SRC_HASH_SHA3_MQH
|
|
|
|
|
|
//+------------------------------------------------------------------+
|