//+------------------------------------------------------------------+ //| 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_SIMETRIC_CHACHA20_MAIN_MQH #define CRYPTOBYLEO_SRC_SIMETRIC_CHACHA20_MAIN_MQH //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "Def.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ namespace TSN { //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CChaCha20 { public: uint32_t m_state[CHACHA20_STATE_S]; public: CChaCha20(void); ~CChaCha20(void) {} //--- // key = clave de 32 bytes // iv = nonce aleatorio por cada bloque a cifrar (tamaƱo de 12 bytes) // inicia el estado del cifrador // Nota que no se veriica nada, se asume que el usuario pasa todo correcto void Init(const uchar& key[], const uchar& iv[], uint32_t counter = 0); //--- void XProcces(uchar &in[], int ins); //--- Extra void ResetCounter(uint32_t counter = 0) { m_state[CHACHA20_STATE_IDX_CNT] = counter; } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ CChaCha20::CChaCha20() { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CChaCha20::Init(const uchar &key[], const uchar &iv[], uint32_t counter = 0) { //--- constnes iniciales m_state[0] = 0x61707865; m_state[1] = 0x3320646e; m_state[2] = 0x79622d32; m_state[3] = 0x6b206574; //--- los siuientes 8 vamos cargo 4 bytes de la calve en un uint for(int i = 0; i < 8; i++) { const int s = i << 2; // Empiza ahi m_state[4 + i] = (uint32_t)key[s] | (uint32_t)key[s + 1] << 8 | (uint32_t)key[s + 2] << 16 | (uint32_t)key[s + 3] << 24; } //--- contador m_state[CHACHA20_STATE_IDX_CNT] = counter; //---- iv //for(int i = 0; i < 3; i++) // unrrolled m_state[13] = (uint32_t)iv[0] | (uint32_t)iv[1] << 8 | (uint32_t)iv[2] << 16 | (uint32_t)iv[3] << 24; m_state[14] = (uint32_t)iv[4] | (uint32_t)iv[5] << 8 | (uint32_t)iv[6] << 16 | (uint32_t)iv[7] << 24; m_state[15] = (uint32_t)iv[8] | (uint32_t)iv[9] << 8 | (uint32_t)iv[10] << 16 | (uint32_t)iv[11] << 24; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CChaCha20::XProcces(uchar &in[], int ins) { //---- union U32_8 { uint32_t u32[CHACHA20_KEYSTREAM_SIZE_U32]; uchar u8[CHACHA20_KEYSTREAM_SIZEB]; } keystream; //--- const int s = ins - CHACHA20_KEYSTREAM_SIZEB; int pos = 0; while(pos < s) { //--- Algoritmo base para un ks // Contruiimos el bloque de 16 (keysteam) // aqwui instaicniasmpo temporales. uint32_t x0 = m_state[0], x1 = m_state[1], x2 = m_state[2], x3 = m_state[3]; uint32_t x4 = m_state[4], x5 = m_state[5], x6 = m_state[6], x7 = m_state[7]; uint32_t x8 = m_state[8], x9 = m_state[9], x10 = m_state[10], x11 = m_state[11]; uint32_t x12 = m_state[12], x13 = m_state[13], x14 = m_state[14], x15 = m_state[15]; // bueno ahora aplicamos las rnodnas con la funcion Qr // 10 unrroled rondas para un total de 10 rondas CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND // Ahora aplicamos al finall // unrroled (16) suma + escritura keystream.u32[0] = x0 + m_state[0]; keystream.u32[1] = x1 + m_state[1]; keystream.u32[2] = x2 + m_state[2]; keystream.u32[3] = x3 + m_state[3]; keystream.u32[4] = x4 + m_state[4]; keystream.u32[5] = x5 + m_state[5]; keystream.u32[6] = x6 + m_state[6]; keystream.u32[7] = x7 + m_state[7]; keystream.u32[8] = x8 + m_state[8]; keystream.u32[9] = x9 + m_state[9]; keystream.u32[10] = x10 + m_state[10]; keystream.u32[11] = x11 + m_state[11]; keystream.u32[12] = x12 + m_state[12]; keystream.u32[13] = x13 + m_state[13]; keystream.u32[14] = x14 + m_state[14]; keystream.u32[15] = x15 + m_state[15]; // Aumentamos el confaodr m_state[CHACHA20_STATE_IDX_CNT]++; //--- Next ahora aplicamos... escritura ffinal for(int i = 0; i < CHACHA20_KEYSTREAM_SIZEB; i++) { in[pos + i] ^= keystream.u8[i]; } //--- pos += CHACHA20_KEYSTREAM_SIZEB; } //--- bytes finales if(pos < ins) { //--- Algoritmo base para un ks // Contruiimos el bloque de 16 (keysteam) // aqwui instaicniasmpo temporales. uint32_t x0 = m_state[0], x1 = m_state[1], x2 = m_state[2], x3 = m_state[3]; uint32_t x4 = m_state[4], x5 = m_state[5], x6 = m_state[6], x7 = m_state[7]; uint32_t x8 = m_state[8], x9 = m_state[9], x10 = m_state[10], x11 = m_state[11]; uint32_t x12 = m_state[12], x13 = m_state[13], x14 = m_state[14], x15 = m_state[15]; // bueno ahora aplicamos las rnodnas con la funcion Qr // 10 unrroled rondas para un total de 10 rondas CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND CHACHA20_DOUBLE_ROUND // Ahora aplicamos al finall // unrroled (16) suma + escritura keystream.u32[0] = x0 + m_state[0]; keystream.u32[1] = x1 + m_state[1]; keystream.u32[2] = x2 + m_state[2]; keystream.u32[3] = x3 + m_state[3]; keystream.u32[4] = x4 + m_state[4]; keystream.u32[5] = x5 + m_state[5]; keystream.u32[6] = x6 + m_state[6]; keystream.u32[7] = x7 + m_state[7]; keystream.u32[8] = x8 + m_state[8]; keystream.u32[9] = x9 + m_state[9]; keystream.u32[10] = x10 + m_state[10]; keystream.u32[11] = x11 + m_state[11]; keystream.u32[12] = x12 + m_state[12]; keystream.u32[13] = x13 + m_state[13]; keystream.u32[14] = x14 + m_state[14]; keystream.u32[15] = x15 + m_state[15]; // Aumentamos el confaodr m_state[CHACHA20_STATE_IDX_CNT]++; //--- const int f = ins - pos; for(int i = 0; i < f; i++) { in[pos + i] ^= keystream.u8[i]; } } } //--- } //+------------------------------------------------------------------+ #endif // CRYPTOBYLEO_SRC_SIMETRIC_CHACHA20_MAIN_MQH /* Por lo que esrtuve enindeod creo que es mas ismple que AEs primero incializ un estado con una key 4 consatnes y un once (aleatorios) Luego vas procsenados chunks de 64 bytes. - Tomar el estado actuliza lo instiaca luego vas aplicando sumas, xor, rotaciones a ese "x" temporalce (Copia de state) por 20 rondas... terminana esas rondas aplicas denueo al estaod (se lo sumas) todos esos temporales bien emepzlaos, y aumentas el condaor (12) - Ahora luego tomas ese aray key stream y aplica un xor en el buffer de salida del cifrado y luego lo copias al buffer de salia (aqui pasas uint32 a uchar) //---- Bueno el algoritmo no es tan complejo a decir verdad... mas faicl que AES Este como tal es el algoritmo puro sin poly.. que se le agrega */ //+------------------------------------------------------------------+