CryptoByLeo/Src/Hash/SHA512.mqh
2026-08-13 18:48:30 -05:00

458 lines
15 KiB
MQL5

//+------------------------------------------------------------------+
//| SHA512.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_SHA512_MQH
#define CRYPTOBYLEO_SRC_HASH_SHA512_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "Base.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#define CRYPTOBYLEO_SHA512_SIZET_FHASH (64)
#define CRYPTOBYLEO_SHA384_SIZET_FHASH (48)
//---
#define CRYPTOBYLEO_SHA512_SIZET_U64HASH (8)
// versiones simplificadoas de la original
// en ch
// 11
// base = (x AND y) XOR (NOT x AND z)
// el not es baicmante x XOR 1
// dado qeu si x = 0 0 XOR 1 = 1 y 1 XOR 1 = 0 (ahi esta flip volteado... )
// asi qeu quedaria (x AND y) XOR ((x XOR 1) AND z) AND tiene mayor precendecia, asi que podemos distirbyuir
// (x AND y) XOR ((x AND z) XOR (1 and Z))) (1 ANd x siempre da x comoresultado)
// (x AND y) XOR ((x AND z) Xor z)
// Desnetolalmos x AND y xor x AND z xor z , hay comunes facotiruzamos
// (x AND ((Y XOR Z)) XOR Z queda asi x and tiene mas priodiad que xor
// nuevo = z XOR (x AND (y XOR z)) reducico en 3 operaciones..
#define CRYPTOBYLEO_SHA2H_CH(x,y,z) ((z)^((x)&((y)^(z))))
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
/*
const uint32_t g_cryptbyleo_sha256_hinicial[CRYPTOBYLEO_SHA256_SIZET_U32HASH] =
{
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
};
*/
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
const ulong g_cryptbyleo_sha2h_k[80] =
{
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
};
//+------------------------------------------------------------------+
#define TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, b) ((v>>b) | (v <<(64 - b)))
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
namespace TSN
{
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static void CCryptoHash::SHA2_HIGH(ulong &h[], const uchar &inp[], int ins)
{
//--- Pase inical tema de padding
int longitud_with_m = ins + 1 + 16;
const ulong bits_len_mes = (ulong)ins << 3ULL;
// %64 = &63
int relleno_con_zeros = (128 - (longitud_with_m & 127)) & 127;
// longitud_with_m aqui lo podemos reintrepsta rcomo 1 extra y 8 de longitd fional BE
uchar in[];
ArrayResize(in, (longitud_with_m + relleno_con_zeros));
// ArrayInitialize(in,0);
// Copiamos los datos
for(int i = 0; i < ins; i++)
{
in[i] = inp[i];
}
// Primero
in[ins++] = 0x80;
// Ahora los ceros
const int final_s = ins + relleno_con_zeros; // final
for(; ins < final_s; ins++)
{
in[ins] = 0; // zeros
}
// Ahora si los ultimos
const int longitud_final = final_s + 16; //
ins = longitud_final - 1; // + 7 por que (+ 8 -1 8 para el final y -1 empza en el utlimo el)
for(int k = 0; ins >= final_s; ins--, k += 8)
{
// BE
// La idea es ir esribiendo lo que podmas aqui traemos los 8 bajos.
in[ins] = uint8_t(bits_len_mes >> k); // zeros
}
//---------
// Base
uint64_t palabras[80];
// Algoritmo en si
for(int ip = 0; ip < longitud_final;)
{
//---
/*
// pasamos a palabras de 32 (primante 16)
for(int i = 0; i < 16; i++)
{
}
*/
//---- Unrolled (Tomamos 128 bytes a 16 words)
#define SHA512_LOAD64(i) \
palabras[i] = uint64_t(in[ip++]) << 56 | \
uint64_t(in[ip++]) << 48 | \
uint64_t(in[ip++]) << 40 | \
uint64_t(in[ip++]) << 32 | \
uint64_t(in[ip++]) << 24 | \
uint64_t(in[ip++]) << 16 | \
uint64_t(in[ip++]) << 8 | \
uint64_t(in[ip++]);
//---
SHA512_LOAD64(0)
SHA512_LOAD64(1)
SHA512_LOAD64(2)
SHA512_LOAD64(3)
SHA512_LOAD64(4)
SHA512_LOAD64(5)
SHA512_LOAD64(6)
SHA512_LOAD64(7)
SHA512_LOAD64(8)
SHA512_LOAD64(9)
SHA512_LOAD64(10)
SHA512_LOAD64(11)
SHA512_LOAD64(12)
SHA512_LOAD64(13)
SHA512_LOAD64(14)
SHA512_LOAD64(15)
//---
// Ahora las expandimos 16 a 80 palarbras (para nuestro bloque final)
for(int i = 16; i < 80; i += 4)
{
uint64_t v, s0, s1;
//--- ronda 1
v = palabras[i - 15];
s0 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 1) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 8) ^ (v >> 7);
v = palabras[i - 2];
s1 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 19) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 61) ^ (v >> 6);
palabras[i] = palabras[i - 16] + s0 + palabras[i - 7] + s1;
//--- ronda 2
v = palabras[i - 14];
s0 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 1) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 8) ^ (v >> 7);
v = palabras[i - 1];
s1 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 19) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 61) ^ (v >> 6);
palabras[i + 1] = palabras[i - 15] + s0 + palabras[i - 6] + s1;
//--- ronda 3
v = palabras[i - 13];
s0 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 1) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 8) ^ (v >> 7);
v = palabras[i];
s1 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 19) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 61) ^ (v >> 6);
palabras[i + 2] = palabras[i - 14] + s0 + palabras[i - 5] + s1;
//--- ronda 4
v = palabras[i - 12];
s0 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 1) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 8) ^ (v >> 7);
v = palabras[i + 1];
s1 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 19) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(v, 61) ^ (v >> 6);
palabras[i + 3] = palabras[i - 13] + s0 + palabras[i - 4] + s1;
}
//---
// Ahora comprimirmos...
uint64_t a = h[0], b = h[1], c = h[2], d = h[3];
uint64_t e = h[4], f = h[5], g = h[6], hh = h[7];
//---
// unrolled 8
for(int i = 0; i < 80; i += 8)
{
uint64_t t1, t2, s1, s0, ch, maj;
// ronda 0
s1 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 14) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 18) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 41);
ch = CRYPTOBYLEO_SHA2H_CH(e, f, g);
t1 = hh + s1 + ch + g_cryptbyleo_sha2h_k[i] + palabras[i];
s0 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 28) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 34) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 39);
maj = (a & b) ^ (a & c) ^ (b & c);
t2 = s0 + maj;
hh = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
// ronda 1
s1 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 14) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 18) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 41);
ch = CRYPTOBYLEO_SHA2H_CH(e, f, g);
t1 = hh + s1 + ch + g_cryptbyleo_sha2h_k[i + 1] + palabras[i + 1];
s0 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 28) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 34) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 39);
maj = (a & b) ^ (a & c) ^ (b & c);
t2 = s0 + maj;
hh = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
// ronda 2
s1 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 14) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 18) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 41);
ch = CRYPTOBYLEO_SHA2H_CH(e, f, g);
t1 = hh + s1 + ch + g_cryptbyleo_sha2h_k[i + 2] + palabras[i + 2];
s0 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 28) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 34) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 39);
maj = (a & b) ^ (a & c) ^ (b & c);
t2 = s0 + maj;
hh = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
// ronda 3
s1 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 14) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 18) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 41);
ch = CRYPTOBYLEO_SHA2H_CH(e, f, g);
t1 = hh + s1 + ch + g_cryptbyleo_sha2h_k[i + 3] + palabras[i + 3];
s0 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 28) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 34) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 39);
maj = (a & b) ^ (a & c) ^ (b & c);
t2 = s0 + maj;
hh = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
// ronda 4
s1 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 14) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 18) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 41);
ch = CRYPTOBYLEO_SHA2H_CH(e, f, g);
t1 = hh + s1 + ch + g_cryptbyleo_sha2h_k[i + 4] + palabras[i + 4];
s0 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 28) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 34) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 39);
maj = (a & b) ^ (a & c) ^ (b & c);
t2 = s0 + maj;
hh = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
// ronda 5
s1 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 14) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 18) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 41);
ch = CRYPTOBYLEO_SHA2H_CH(e, f, g);
t1 = hh + s1 + ch + g_cryptbyleo_sha2h_k[i + 5] + palabras[i + 5];
s0 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 28) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 34) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 39);
maj = (a & b) ^ (a & c) ^ (b & c);
t2 = s0 + maj;
hh = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
// ronda 6
s1 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 14) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 18) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 41);
ch = CRYPTOBYLEO_SHA2H_CH(e, f, g);
t1 = hh + s1 + ch + g_cryptbyleo_sha2h_k[i + 6] + palabras[i + 6];
s0 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 28) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 34) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 39);
maj = (a & b) ^ (a & c) ^ (b & c);
t2 = s0 + maj;
hh = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
// ronda 7
s1 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 14) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 18) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(e, 41);
ch = CRYPTOBYLEO_SHA2H_CH(e, f, g);
t1 = hh + s1 + ch + g_cryptbyleo_sha2h_k[i + 7] + palabras[i + 7];
s0 = TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 28) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 34) ^ TSN_CRYPTBYLEO_SHA2H_ROT_DER(a, 39);
maj = (a & b) ^ (a & c) ^ (b & c);
t2 = s0 + maj;
hh = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
//---
h[0] += a;
h[1] += b;
h[2] += c;
h[3] += d;
h[4] += e;
h[5] += f;
h[6] += g;
h[7] += hh;
//--- Sigueinte bloque
//ip += 64;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
//---
#define CRYPTOHASHBYLEO_HASH_ASSING64(INDEX) \
out[INDEX] = uint8_t(t >> 56); \
out[INDEX+1] = uint8_t(t >> 48); \
out[INDEX+2] = uint8_t(t >> 40); \
out[INDEX+3] = uint8_t(t >> 32); \
out[INDEX+4] = uint8_t(t >> 24); \
out[INDEX+5] = uint8_t(t >> 16); \
out[INDEX+6] = uint8_t(t >> 8); \
out[INDEX+7] = uint8_t(t);
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static void CCryptoHash::SHA512(const uchar &inp[], int ins, uchar& out[])
{
//--- iv iniical
uint64_t h[8] =
{
0x6a09e667f3bcc908,
0xbb67ae8584caa73b,
0x3c6ef372fe94f82b,
0xa54ff53a5f1d36f1,
0x510e527fade682d1,
0x9b05688c2b3e6c1f,
0x1f83d9abfb41bd6b,
0x5be0cd19137e2179
};
//---
SHA2_HIGH(h, inp, ins);
//---
uint64_t t = h[0];
CRYPTOHASHBYLEO_HASH_ASSING64(0)
t = h[1];
CRYPTOHASHBYLEO_HASH_ASSING64(8)
t = h[2];
CRYPTOHASHBYLEO_HASH_ASSING64(16)
t = h[3];
CRYPTOHASHBYLEO_HASH_ASSING64(24)
t = h[4];
CRYPTOHASHBYLEO_HASH_ASSING64(32)
t = h[5];
CRYPTOHASHBYLEO_HASH_ASSING64(40)
t = h[6];
CRYPTOHASHBYLEO_HASH_ASSING64(48)
t = h[7];
CRYPTOHASHBYLEO_HASH_ASSING64(56)
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
static void CCryptoHash::SHA384(const uchar &inp[], int ins, uchar &out[])
{
//--- iv iniical
uint64_t h[8] =
{
0xcbbb9d5dc1059ed8,
0x629a292a367cd507,
0x9159015a3070dd17,
0x152fecd8f70e5939,
0x67332667ffc00b31,
0x8eb44a8768581511,
0xdb0c2e0d64f98fa7,
0x47b5481dbefa4fa4
};
//---
SHA2_HIGH(h, inp, ins);
//---
uint64_t t = h[0];
CRYPTOHASHBYLEO_HASH_ASSING64(0)
t = h[1];
CRYPTOHASHBYLEO_HASH_ASSING64(8)
t = h[2];
CRYPTOHASHBYLEO_HASH_ASSING64(16)
t = h[3];
CRYPTOHASHBYLEO_HASH_ASSING64(24)
t = h[4];
CRYPTOHASHBYLEO_HASH_ASSING64(32)
t = h[5];
CRYPTOHASHBYLEO_HASH_ASSING64(40)
}
//--- Namepsace TSN
}
#endif // CRYPTOBYLEO_SRC_HASH_SHA512_MQH