CryptoByLeo/Src/MAC/HMac/Main.mqh
2026-08-13 18:48:30 -05:00

294 lines
9.7 KiB
MQL5

//+------------------------------------------------------------------+
//| Main.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_MAC_HMAC_MAIN_MQH
#define CRYPTOBYLEO_SRC_MAC_HMAC_MAIN_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "Def.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
/*
HMAC(K,m)=H((K′⊕opad)∥H((K′⊕ipad)∥m))
---
Notas:
- Si pasasis un ENUM invalido, dara invalid pointer de fncion...
Nota tampoco que no hay veriicaiones ni last err ni nad... tu eres respobiel de hacer
las cosas bien
*/
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
namespace TSN
{
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CHMac
{
public:
// clave
uchar m_key[];
int m_key_s;
int m_key_r;
// (Se peude cambiar la clave interna)
private:
// funcion hasher
CCryptoHashMeta::TsnCryptoByLeoHashFuncFixed m_func_haser;
int m_out_hash_size; // tamaño en bytes del hash de salida
//---
int m_block_size_internal; // tamaño del bloque que procesa HMAC (depede del haser)
//--- interno del algoritmo
// tamaño = msi (tamaño del dato) + (tamaño del bloque)
uchar m_ipad[];
int m_ipad_r;
// tamaño = block_size + out h size
int m_opad_r;
uchar m_opad[];
// kout (k'prima)
uchar m_kout[];
public:
//--- La salida es publicxa tambien para logeo
uchar m_out[]; // HMAC actual
// tamaño es igual a outhsize
public:
CHMac(const uchar& key[], const uchar& data[], CCryptoHashMeta::ENUM_TSN_CRYPTO_HASH f);
CHMac(void);
~CHMac(void) {}
//--- Funcion base
// Nota esto solo resetea el estado interno... es como un set (Acutlizar)
// NO STREAMING..
void Update(const uchar &data[]);
// No hay funcion para setear key dado qeu es publica
//--- Cuando se actulize KEY
void OnKeyUpdate();
//--- Comparacion
// comparacion RAW (no compara con fomrato espeicifo si no bytes TAL CUAl raw como se meciona)
// Si quieres ocmprar ocn hex conveirtelo
bool CompareRaw(const string& hmac);
bool CompareRaw(const uchar& hmac[]);
//--- Getter \ Setter generales
// Funciones hasher
CCryptoHashMeta::TsnCryptoByLeoHashFuncFixed HashFunc() { return m_func_haser; }
void HashFunc(CCryptoHashMeta::ENUM_TSN_CRYPTO_HASH f);
//--- getter
__forceinline int BlockSize() const { return m_block_size_internal; }
__forceinline int OutHashSize() const { return m_out_hash_size; }
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CHMac::CHMac(void)
: m_ipad_r(512), m_block_size_internal(0), m_out_hash_size(0),
m_func_haser(NULL), m_key_s(0), m_key_r(128), m_opad_r(512)
{
ArrayResize(m_opad, m_opad_r, m_opad_r);
ArrayResize(m_ipad, m_ipad_r, m_ipad_r);
ArrayResize(m_key, m_key_r, m_key_r);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CHMac::CHMac(const uchar &key[], const uchar &data[], CCryptoHashMeta::ENUM_TSN_CRYPTO_HASH f)
: m_ipad_r(ArraySize(data)), m_block_size_internal(0), m_out_hash_size(0),
m_func_haser(NULL), m_key_s(ArraySize(key)), m_opad_r(0)
{
//--- Llamamaos a la funcion f
HashFunc(f);
//--- Ipad
m_ipad_r += m_block_size_internal;
ArrayResize(m_ipad, m_ipad_r, m_ipad_r); // inicialemte tamaño del blouqe
//--- key
m_key_r = m_key_s << 1;
ArrayResize(m_key, m_key_r, m_key_r);
for(int i = 0; i < m_key_s; i++)
m_key[i] = key[i]; // copiamos los datos
//---
OnKeyUpdate();
//--- Actulizamos el estado interno
Update(data);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHMac::HashFunc(CCryptoHashMeta::ENUM_TSN_CRYPTO_HASH f)
{
//--- Check validez
if(f >= CRYPTOBYLEO_HASHFUNC_TOTAL_FIXED || f < 0)
return; // invalid range
//---
m_out_hash_size = TSN::CCryptoHashMeta::g_crytpo_hash_meta[f].outl;
m_block_size_internal = TSN::CCryptoHashMeta::g_crytpo_hash_meta[f].blocksize;
m_func_haser = TSN::CCryptoHashMeta::g_crypto_fhash_fixed[f];
//--- opad
const int n = m_block_size_internal + m_out_hash_size;
if(n > m_opad_r)
{
m_opad_r += n << 1;
ArrayResize(m_opad, m_opad_r, m_opad_r); // tamaño de blocksize + outhsize
}
//--- Kout
ArrayResize(m_kout, m_block_size_internal, m_block_size_internal); // tamaño del bloque como tal
//--- Out
ArrayResize(m_out, m_out_hash_size); // tamaño final
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHMac::OnKeyUpdate(void)
{
//--- Parte del algoritmo hmac
if(m_key_s > m_block_size_internal) // mayor
{
// entoncesd comprimirmos
m_func_haser(m_key, m_key_s, m_kout);
// itermoas desdel el inico del fin
for(int i = m_out_hash_size; i < m_block_size_internal; i++)
m_kout[i] = 0; // 0
}
else
{
// Ahora aqui
for(int i = 0; i < m_key_s; i++)
m_kout[i] = m_key[i];
// sobrante
for(int i = m_key_s; i < m_block_size_internal; i++)
m_kout[i] = 0; // 0
}
//--- Ipad y Opad
for(int i = 0; i < m_block_size_internal; i++)
{
m_opad[i] = m_kout[i] ^ 0x5c;
m_ipad[i] = m_kout[i] ^ 0x36;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHMac::Update(const uchar &data[])
{
//---
const int msi = ArraySize(data);
int n = msi + m_block_size_internal;
if(n > m_ipad_r)
{
m_ipad_r += n << 1;
ArrayResize(m_ipad, m_ipad_r, m_ipad_r);
}
//---reutilizaps ipad
// ahora copiamos los datos de data a ipad+blocksize
// ArrayCopy(ipad, data, TSNTABLES_HMAC_BLOCKSIZE, 0, msi);
for(int i = 0; i < msi; i++)
m_ipad[m_block_size_internal + i] = data[i];
/*
uchar iner_out[TSNTABLES_SHA256_OUT];
if(CryptEncode(CRYPT_HASH_SHA256, ipad, empty, iner_out) != TSNTABLES_SHA256_OUT)
return false;
*/ // Encryptamos lo qeu tenemos
m_func_haser(m_ipad, n, m_out); // ahora esta en m_out el resultado
// reutkliar mout (envez de iner out)
// ArrayCopy(opad, iner_out, TSNTABLES_HMAC_BLOCKSIZE, 0, TSNTABLES_SHA256_OUT);
for(int i = 0; i < m_out_hash_size; i++)
m_opad[m_block_size_internal + i] = m_out[i];
//--- utlima fase
// return CryptEncode(CRYPT_HASH_SHA256, opad, empty, res) == TSNTABLES_SHA256_OUT;
n = m_out_hash_size + m_block_size_internal;
m_func_haser(m_opad, n, m_out); // finalizamos
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CHMac::CompareRaw(const uchar &hmac[])
{
const int t = ArraySize(hmac);
if(t != m_out_hash_size)
return false;
//---
uchar v = 0;
for(int i = 0; i < t; i++)
{
// si son iguales = 0 (la idea es que sean todos iguales y asi todo 0 or y 0 fnal)
// si no son iguales (pero 1 \0) = 1 aqui ya con el primero que no se giual |1
// asi que no encajaria
v |= hmac[i] ^ m_out[i];
}
// Basandome en los comapore safe de otros lengaujes, usan esto para evita "ataque" de timing
// sincamtne no se como fucinoar eso infiero que perfilaran cuanto tarda el programa y en base a eso podria
// hacer stats.. de ir probadno varias clavez de varios len para ver primero que len usa y adiviar el algortimo
// algo ais.. la verdad es que son supociones ...
// Asi que para evitart eso si hacemos el tiempo de compracion constante ya eso para N entradas
// da el mismo resultado.
return v == 0; // 0
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CHMac::CompareRaw(const string &hmac)
{
const int t = StringLen(hmac);
if(t != m_out_hash_size)
return false;
//---
uchar v = 0;
for(int i = 0; i < t; i++)
{
v |= (uchar)hmac[i] ^ m_out[i];
}
return v == 0; // 0
}
//--- namespace
}
#endif // CRYPTOBYLEO_SRC_MAC_HMAC_MAIN_MQH