2026-08-12 08:29:06 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| 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:
|
2026-08-12 13:31:16 -05:00
|
|
|
uint32_t m_state[CHACHA20_STATE_S];
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
CChaCha20(void);
|
2026-08-12 08:29:06 -05:00
|
|
|
~CChaCha20(void) {}
|
2026-08-12 13:31:16 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// 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; }
|
2026-08-12 08:29:06 -05:00
|
|
|
};
|
2026-08-12 13:31:16 -05:00
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
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];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
2026-08-12 08:29:06 -05:00
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-08-12 13:31:16 -05:00
|
|
|
#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
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
//+------------------------------------------------------------------+
|