//+------------------------------------------------------------------+ //| 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