//+------------------------------------------------------------------+ //| 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; //--- 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; //--- for(int i = chunk; i < BLAKE2B_BLOCKBYTES; i++) w.block[i] = 0; //--- for(int i = 0; i < chunk; i++) w.block[i] = in[off + i]; //--- Contadores.. const ulong inc = is_l ? (ulong)chunk : 128ULL; t0 += inc; t1 += (t0 < inc); //--- // Comprirmimos. a 16 parnas en LE // 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); } */ //--- /* 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]; //--- iv base /* const ulong iv[8] = { 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 }; */ // Parte 2 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; /* if(is_l) v[14] = ~v[14]; */ v[14] = 0x1f83d9abfb41bd6b ^ (is_l ? ~0ULL : 0ULL); v[15] = 0x5be0cd19137e2179; // iv[7]; //--- //--- 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]]); } //--- 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