CryptoByLeo/Src/Hash/Blake2b.mqh

228 lignes
7,4 Kio
MQL5
Brut Lien permanent Vue normale Historique

2026-08-11 10:06:33 -05:00
//+------------------------------------------------------------------+
//| Blake2b.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_BLACK2B_MQH
#define CRYPTOBYLEO_SRC_HASH_BLACK2B_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "Base.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#define BLAKE2B_G(v,a,bb,c,d,x,y) \
v[a] = v[a] + v[bb] + x; \
{ulong _t = v[d]^v[a]; v[d] = (_t >> 32) | (_t << 32);} \
v[c] = v[c] + v[d]; \
{ulong _t = v[bb]^v[c]; v[bb] = (_t >> 24) | (_t << 40);} \
v[a] = v[a] + v[bb] + y; \
{ulong _t = v[d]^v[a]; v[d] = (_t >> 16) | (_t << 48);} \
v[c] = v[c] + v[d]; \
{ulong _t = v[bb]^v[c]; v[bb] = (_t >> 63) | (_t << 1);}
#define BLAKE2B_BLOCKBYTES (128)
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
namespace TSN
{
static void CCryptoHash::BLAKE2B(const uchar &in[], int ins, uchar &out[], int outl = 64)
{
//-- base
// modificable (state final) esto luego lo pasrmeos a out
ulong h[8] =
{
0x6a09e667f3bcc908, 0xbb67ae8584caa73b,
0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
0x510e527fade682d1, 0x9b05688c2b3e6c1f,
0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
};
// tabla 2 (como un uni)
static const uchar SIGMA[192] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3,
11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4,
7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8,
9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13,
2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9,
12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11,
13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10,
6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5,
10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3
};
//----
h[0] ^= (ulong)0x01010000 | (ulong)outl; // key_len=0, fanout=1, depth=1
//----
ulong t0 = 0, t1 = 0;
//--- numero de bloques a procesar
int blocks = (ins + 127) >> 7; // / 128;
if(blocks == 0)
blocks = 1;
//---
ulong v[16]; // vector de trabaajo v
//---
union u64_u8_block
{
ulong palabras[16]; // palabras (m)
uchar block[BLAKE2B_BLOCKBYTES]; // chunk que se procesa
} w;
2026-08-11 10:06:33 -05:00
//---
for(int b = 0; b < blocks; b++)
{
//---
const int off = b << 7; // * BLAKE2B_BLOCKBYTES;
const bool is_l = (b == blocks - 1);
int chunk = ins - off;
if(chunk > BLAKE2B_BLOCKBYTES)
chunk = BLAKE2B_BLOCKBYTES;
else
if(chunk < 0)
chunk = 0;
2026-08-11 10:06:33 -05:00
//---
for(int i = chunk; i < BLAKE2B_BLOCKBYTES; i++)
w.block[i] = 0;
2026-08-11 10:06:33 -05:00
//---
for(int i = 0; i < chunk; i++)
w.block[i] = in[off + i];
2026-08-11 10:06:33 -05:00
//--- Contadores..
const ulong inc = is_l ? (ulong)chunk : 128ULL;
t0 += inc;
t1 += (t0 < inc);
//---
// Comprirmimos. a 16 parnas en LE
2026-08-13 17:24:10 -05:00
// Ya no es necasrio solo reinterepretamos
/* for(int i = 0; i < 16; i++)
{
const int p = i << 3;
palabras[i] = (ulong)block[p] | ((ulong)block[p + 1] << 8) |
((ulong)block[p + 2] << 16) | ((ulong)block[p + 3] << 24) |
((ulong)block[p + 4] << 32) | ((ulong)block[p + 5] << 40) |
((ulong)block[p + 6] << 48) | ((ulong)block[p + 7] << 56);
}
*/
2026-08-11 10:06:33 -05:00
//---
/* for(int i = 0; i < 8; i++)
{
v[i] = h[i];
v[i + 8] = iv[i];
}*/
// Desenrollado
// Parte 1
v[0] = h[0];
v[1] = h[1];
v[2] = h[2];
v[3] = h[3];
v[4] = h[4];
v[5] = h[5];
v[6] = h[6];
v[7] = h[7];
2026-08-13 17:24:10 -05:00
//--- iv base
/*
const ulong iv[8] =
{
0x6a09e667f3bcc908,
0xbb67ae8584caa73b,
0x3c6ef372fe94f82b,
0xa54ff53a5f1d36f1,
0x510e527fade682d1,
0x9b05688c2b3e6c1f,
0x1f83d9abfb41bd6b,
0x5be0cd19137e2179
};
*/
2026-08-11 10:06:33 -05:00
// Parte 2
2026-08-13 17:24:10 -05:00
v[8] = 0x6a09e667f3bcc908; // iv[0];
v[9] = 0xbb67ae8584caa73b; // iv[1];
v[10] = 0x3c6ef372fe94f82b; // iv[2];
v[11] = 0xa54ff53a5f1d36f1; // iv[3];
v[12] = 0x510e527fade682d1 ^ t0;
v[13] = 0x9b05688c2b3e6c1f ^ t1;
2026-08-11 10:06:33 -05:00
/*
if(is_l)
v[14] = ~v[14];
*/
2026-08-13 17:24:10 -05:00
v[14] = 0x1f83d9abfb41bd6b ^ (is_l ? ~0ULL : 0ULL);
v[15] = 0x5be0cd19137e2179; // iv[7];
2026-08-11 10:06:33 -05:00
//---
//--- Compresion Rondas finales (funcion F)
for(int r = 0; r < 12; r++)
{
//--- Ronda
const int base = r << 4;
BLAKE2B_G(v, 0, 4, 8, 12, w.palabras[SIGMA[base + 0]], w.palabras[SIGMA[base + 1]]);
BLAKE2B_G(v, 1, 5, 9, 13, w.palabras[SIGMA[base + 2]], w.palabras[SIGMA[base + 3]]);
BLAKE2B_G(v, 2, 6, 10, 14, w.palabras[SIGMA[base + 4]], w.palabras[SIGMA[base + 5]]);
BLAKE2B_G(v, 3, 7, 11, 15, w.palabras[SIGMA[base + 6]], w.palabras[SIGMA[base + 7]]);
BLAKE2B_G(v, 0, 5, 10, 15, w.palabras[SIGMA[base + 8]], w.palabras[SIGMA[base + 9]]);
BLAKE2B_G(v, 1, 6, 11, 12, w.palabras[SIGMA[base + 10]], w.palabras[SIGMA[base + 11]]);
BLAKE2B_G(v, 2, 7, 8, 13, w.palabras[SIGMA[base + 12]], w.palabras[SIGMA[base + 13]]);
BLAKE2B_G(v, 3, 4, 9, 14, w.palabras[SIGMA[base + 14]], w.palabras[SIGMA[base + 15]]);
2026-08-11 10:06:33 -05:00
}
//--- Add
h[0] ^= v[0] ^ v[8];
h[1] ^= v[1] ^ v[9];
h[2] ^= v[2] ^ v[10];
h[3] ^= v[3] ^ v[11];
h[4] ^= v[4] ^ v[12];
h[5] ^= v[5] ^ v[13];
h[6] ^= v[6] ^ v[14];
h[7] ^= v[7] ^ v[15];
}
//---
const int tw = outl >> 3; // cuántas palabras de 64 bits caben completas
const int rw = outl & 7; // bytes sueltos de la última palabra parcial
//----
int pos = 0;
for(int i = 0; i < tw; i++)
{
const ulong val = h[i];
out[pos++] = (uchar)(val);
out[pos++] = (uchar)(val >> 8);
out[pos++] = (uchar)(val >> 16);
out[pos++] = (uchar)(val >> 24);
out[pos++] = (uchar)(val >> 32);
out[pos++] = (uchar)(val >> 40);
out[pos++] = (uchar)(val >> 48);
out[pos++] = (uchar)(val >> 56);
}
//----
if(rw > 0)
{
const ulong val = h[tw];
for(int j = 0; j < rw; j++)
out[pos++] = (uchar)(val >> (j << 3));
}
}
}
//+------------------------------------------------------------------+
#endif // CRYPTOBYLEO_SRC_HASH_BLACK2B_MQH