2026-08-10 16:05:10 -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
|
|
|
|
|
|
|
|
|
|
|
2026-08-10 16:09:46 -05:00
|
|
|
#ifndef CRYPTOBYLEO_SRC_SIMETRIC_AES_MAIN_MQH
|
|
|
|
|
#define CRYPTOBYLEO_SRC_SIMETRIC_AES_MAIN_MQH
|
|
|
|
|
|
2026-08-10 16:05:10 -05:00
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#include "Defines.mqh"
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
namespace TSN
|
|
|
|
|
{
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
class CAes
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
// se peude modifcar directamtne fuera..
|
|
|
|
|
uint8_t m_iv[AES_BLOCKLEN]; // vecotr de inicizlaicion
|
|
|
|
|
uint m_ks; // desde donde inica el buffer pasado para cifrar\descifrar
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
//_--
|
|
|
|
|
ENUM_AES_TYPE_CRYPTH m_method;
|
|
|
|
|
ENUM_AES_LAST_ERR m_last_err;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
int m_ivs;
|
|
|
|
|
bool m_save_last_ivs_in_cbc;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
int m_round_key_s; // size
|
|
|
|
|
uint8_t m_round_key[AES_MAX_KEY_FINAL_S]; // round key
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
uint m_ncol; // nuymeo de columnas en la clave (4 = clavelen\4) (Nk)
|
|
|
|
|
uint m_ncol_last; // m_ncol-1 (para fast %)
|
|
|
|
|
uint m_nr; // numero de rondas (nk+6)
|
|
|
|
|
int m_expected_len_key; // tamaño de clave que se espera
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
void AddRoundKey(uint round, uint8_t& state[]) const;
|
|
|
|
|
|
2026-08-12 08:29:06 -05:00
|
|
|
__forceinline uint8_t xtime(uint8_t x) const;
|
2026-08-10 16:05:10 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
CAes(void);
|
|
|
|
|
~CAes(void) {}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
void KeyExpansion(const uint8_t& key[]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
void Method(ENUM_AES_TYPE_CRYPTH tcrypht);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
bool Init(const uint8_t &key[]);
|
|
|
|
|
bool Init(const uint8_t& key[], const uint8_t& iv[]);
|
|
|
|
|
|
|
|
|
|
//--- Base / ECB
|
2026-08-12 08:29:06 -05:00
|
|
|
void CifradoInverso(uint8_t& state[]) const;
|
|
|
|
|
void Cifrar(uint8_t& state[]) const;
|
2026-08-10 16:05:10 -05:00
|
|
|
|
|
|
|
|
//--- Cbc con IV secuencial
|
|
|
|
|
void CbcCifrado(uint8_t &buf[], uint length);
|
|
|
|
|
void CbcDescifra(uint8_t& buf[], uint length);
|
|
|
|
|
__forceinline bool CbcSaveLastIv() const { return m_save_last_ivs_in_cbc; }
|
|
|
|
|
void CbcSaveLastIv(bool v) { m_save_last_ivs_in_cbc = v; }
|
|
|
|
|
|
|
|
|
|
//--- CTR
|
|
|
|
|
void CtrCryptX(uint8_t& buf[], uint length);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
static void CorrectPadding(uchar& in[]);
|
|
|
|
|
static bool QuitarPadding(uchar& in[]);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
CAes::CAes(void)
|
|
|
|
|
: m_save_last_ivs_in_cbc(true)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CAes::KeyExpansion(const uint8_t & key[])
|
|
|
|
|
{
|
|
|
|
|
unsigned int i, j, k;
|
|
|
|
|
uint8_t tempa[4]; // Used for the column/row operations
|
|
|
|
|
|
|
|
|
|
//--- Copiamos.
|
|
|
|
|
// Primera pasada copiamos por cada columa 4 valores..
|
|
|
|
|
// [] .... m_col
|
|
|
|
|
// []
|
|
|
|
|
// []
|
|
|
|
|
// []
|
|
|
|
|
for(i = 0; i < m_ncol; ++i)
|
|
|
|
|
{
|
|
|
|
|
m_round_key[(i * 4) + 0] = key[(i * 4) + 0];
|
|
|
|
|
m_round_key[(i * 4) + 1] = key[(i * 4) + 1];
|
|
|
|
|
m_round_key[(i * 4) + 2] = key[(i * 4) + 2];
|
|
|
|
|
m_round_key[(i * 4) + 3] = key[(i * 4) + 3];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// luego empzamos en la utliam fila hasta el numero de rondas * 4 +1
|
|
|
|
|
for(i = m_ncol; i < AES_COL_S * (m_nr + 1); ++i)
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
// Obtenemos palabra
|
|
|
|
|
k = (i - 1) * 4;
|
|
|
|
|
tempa[0] = m_round_key[k + 0];
|
|
|
|
|
tempa[1] = m_round_key[k + 1];
|
|
|
|
|
tempa[2] = m_round_key[k + 2];
|
|
|
|
|
tempa[3] = m_round_key[k + 3];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if((i & m_ncol_last) == 0) // % mncol
|
|
|
|
|
{
|
|
|
|
|
// This function shifts the 4 bytes in a word to the left once.
|
|
|
|
|
// [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
|
|
|
|
|
|
|
|
|
|
// Function RotWord()
|
|
|
|
|
{
|
|
|
|
|
const uint8_t u8tmp = tempa[0];
|
|
|
|
|
tempa[0] = tempa[1];
|
|
|
|
|
tempa[1] = tempa[2];
|
|
|
|
|
tempa[2] = tempa[3];
|
|
|
|
|
tempa[3] = u8tmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SubWord() is a function that takes a four-byte input word and
|
|
|
|
|
// applies the S-box to each of the four bytes to produce an output word.
|
|
|
|
|
|
|
|
|
|
// Function Subword()
|
|
|
|
|
{
|
|
|
|
|
tempa[0] = getSBoxValue(tempa[0]);
|
|
|
|
|
tempa[1] = getSBoxValue(tempa[1]);
|
|
|
|
|
tempa[2] = getSBoxValue(tempa[2]);
|
|
|
|
|
tempa[3] = getSBoxValue(tempa[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tempa[0] = tempa[0] ^ g_aes_rcon[i / m_ncol];
|
|
|
|
|
}
|
|
|
|
|
//#if defined(AES256) && (AES256 == 1)
|
|
|
|
|
if(m_method == AES_CRYPTH_256 && (i & m_ncol_last) == 4)
|
|
|
|
|
{
|
|
|
|
|
// Function Subword()
|
|
|
|
|
{
|
|
|
|
|
tempa[0] = getSBoxValue(tempa[0]);
|
|
|
|
|
tempa[1] = getSBoxValue(tempa[1]);
|
|
|
|
|
tempa[2] = getSBoxValue(tempa[2]);
|
|
|
|
|
tempa[3] = getSBoxValue(tempa[3]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//#endif
|
|
|
|
|
j = i * 4;
|
|
|
|
|
k = (i - m_ncol) * 4;
|
|
|
|
|
m_round_key[j + 0] = m_round_key[k + 0] ^ tempa[0];
|
|
|
|
|
m_round_key[j + 1] = m_round_key[k + 1] ^ tempa[1];
|
|
|
|
|
m_round_key[j + 2] = m_round_key[k + 2] ^ tempa[2];
|
|
|
|
|
m_round_key[j + 3] = m_round_key[k + 3] ^ tempa[3];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CAes::Method(ENUM_AES_TYPE_CRYPTH tcrypht)
|
|
|
|
|
{
|
|
|
|
|
m_method = tcrypht;
|
|
|
|
|
switch(tcrypht)
|
|
|
|
|
{
|
|
|
|
|
case AES_CRYPTH_128:
|
|
|
|
|
{
|
|
|
|
|
m_round_key_s = 176;
|
|
|
|
|
m_expected_len_key = 16;
|
|
|
|
|
m_ncol = 4;
|
|
|
|
|
m_ncol_last = 3;
|
|
|
|
|
m_nr = 10;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case AES_CRYPTH_256:
|
|
|
|
|
{
|
|
|
|
|
m_round_key_s = 240;
|
|
|
|
|
m_expected_len_key = 32;
|
|
|
|
|
m_ncol = 8;
|
|
|
|
|
m_ncol_last = 7;
|
|
|
|
|
m_nr = 14;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
// fllabkac a 128
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CAes::Init(const uint8_t &key[])
|
|
|
|
|
{
|
|
|
|
|
if(ArraySize(key) != m_expected_len_key)
|
|
|
|
|
{
|
|
|
|
|
m_last_err = AES_LAST_ERR_INVALID_KEY_LEN;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
KeyExpansion(key);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CAes::Init(const uint8_t &key[], const uint8_t &iv[])
|
|
|
|
|
{
|
|
|
|
|
if(ArraySize(key) != m_expected_len_key)
|
|
|
|
|
{
|
|
|
|
|
m_last_err = AES_LAST_ERR_INVALID_KEY_LEN;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
KeyExpansion(key);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const int t = ArraySize(iv);
|
|
|
|
|
if(t != AES_BLOCKLEN)
|
|
|
|
|
{
|
|
|
|
|
m_last_err = AES_LAST_ERR_INVALID_IV_SIZE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
for(int i = 0; i < AES_BLOCKLEN; i++)
|
|
|
|
|
{
|
|
|
|
|
m_iv[i] = iv[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
// con el buffer acutal aplicamos un xor con el key
|
|
|
|
|
void CAes::AddRoundKey(uint round, uint8_t& state[]) const
|
|
|
|
|
{
|
2026-08-12 08:29:06 -05:00
|
|
|
uint8_t i;
|
2026-08-10 16:05:10 -05:00
|
|
|
for(i = 0; i < 4; ++i)
|
|
|
|
|
{
|
2026-08-12 08:29:06 -05:00
|
|
|
// unrolled
|
|
|
|
|
AesStateAcces(i, 0) ^= m_round_key[(round * AES_COL_S * 4) + (i * AES_COL_S) + 0];
|
|
|
|
|
AesStateAcces(i, 1) ^= m_round_key[(round * AES_COL_S * 4) + (i * AES_COL_S) + 1];
|
|
|
|
|
AesStateAcces(i, 2) ^= m_round_key[(round * AES_COL_S * 4) + (i * AES_COL_S) + 2];
|
|
|
|
|
AesStateAcces(i, 3) ^= m_round_key[(round * AES_COL_S * 4) + (i * AES_COL_S) + 3];
|
2026-08-10 16:05:10 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
// Suma corregida por lo visto en mapa finito de 256
|
|
|
|
|
__forceinline uint8_t CAes::xtime(uint8_t x) const
|
|
|
|
|
{
|
|
|
|
|
return ((x << 1) ^ (((x >> 7) & 1) * 0x1b));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
// por cda elemento lo sutitlmis con la posicion en que cae en la talba sbox
|
2026-08-12 08:29:06 -05:00
|
|
|
/*
|
2026-08-10 16:05:10 -05:00
|
|
|
void CAes::SubBytes(uint8_t &state[]) const
|
|
|
|
|
{
|
|
|
|
|
uint8_t i, j;
|
|
|
|
|
for(i = 0; i < 4; ++i)
|
|
|
|
|
{
|
2026-08-12 08:29:06 -05:00
|
|
|
AesStateAcces(0, i) = getSBoxValue(AesStateAcces(0, i));
|
|
|
|
|
AesStateAcces(1, i) = getSBoxValue(AesStateAcces(1, i));
|
|
|
|
|
AesStateAcces(2, i) = getSBoxValue(AesStateAcces(2, i));
|
|
|
|
|
AesStateAcces(3, i) = getSBoxValue(AesStateAcces(3, i));
|
2026-08-10 16:05:10 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CAes::ShiftRows(uint8_t &state[]) const
|
|
|
|
|
{
|
|
|
|
|
uint8_t temp;
|
|
|
|
|
|
|
|
|
|
// Rotate first row 1 columns to left
|
|
|
|
|
temp = AesStateAcces(0, 1);
|
|
|
|
|
AesStateAcces(0, 1) = AesStateAcces(1, 1);
|
|
|
|
|
AesStateAcces(1, 1) = AesStateAcces(2, 1);
|
|
|
|
|
AesStateAcces(2, 1) = AesStateAcces(3, 1);
|
|
|
|
|
AesStateAcces(3, 1) = temp;
|
|
|
|
|
|
|
|
|
|
// Rotate second row 2 columns to left
|
|
|
|
|
temp = AesStateAcces(0, 2);
|
|
|
|
|
AesStateAcces(0, 2) = AesStateAcces(2, 2);
|
|
|
|
|
AesStateAcces(2, 2) = temp;
|
|
|
|
|
temp = AesStateAcces(1, 2);
|
|
|
|
|
AesStateAcces(1, 2) = AesStateAcces(3, 2);
|
|
|
|
|
AesStateAcces(3, 2) = temp;
|
|
|
|
|
|
|
|
|
|
// Rotate third row 3 columns to left
|
|
|
|
|
temp = AesStateAcces(0, 3);
|
|
|
|
|
AesStateAcces(0, 3) = AesStateAcces(3, 3);
|
|
|
|
|
AesStateAcces(3, 3) = AesStateAcces(2, 3);
|
|
|
|
|
AesStateAcces(2, 3) = AesStateAcces(1, 3);
|
|
|
|
|
AesStateAcces(1, 3) = temp;
|
2026-08-12 08:29:06 -05:00
|
|
|
}*/
|
|
|
|
|
/*
|
2026-08-10 16:05:10 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CAes::MixColumns(uint8_t &state[]) const
|
|
|
|
|
{
|
2026-08-12 08:29:06 -05:00
|
|
|
uint8_t temp = AesStateAcces(0, 1);
|
|
|
|
|
AesStateAcces(0, 1) = AesStateAcces(1, 1);
|
|
|
|
|
AesStateAcces(1, 1) = AesStateAcces(2, 1);
|
|
|
|
|
AesStateAcces(2, 1) = AesStateAcces(3, 1);
|
|
|
|
|
AesStateAcces(3, 1) = temp;
|
|
|
|
|
// Rotate second row 2 columns to left
|
|
|
|
|
temp = AesStateAcces(0, 2);
|
|
|
|
|
AesStateAcces(0, 2) = AesStateAcces(2, 2);
|
|
|
|
|
AesStateAcces(2, 2) = temp;
|
|
|
|
|
temp = AesStateAcces(1, 2);
|
|
|
|
|
AesStateAcces(1, 2) = AesStateAcces(3, 2);
|
|
|
|
|
AesStateAcces(3, 2) = temp;
|
|
|
|
|
// Rotate third row 3 columns to left
|
|
|
|
|
temp = AesStateAcces(0, 3);
|
|
|
|
|
AesStateAcces(0, 3) = AesStateAcces(3, 3);
|
|
|
|
|
AesStateAcces(3, 3) = AesStateAcces(2, 3);
|
|
|
|
|
AesStateAcces(2, 3) = AesStateAcces(1, 3);
|
|
|
|
|
AesStateAcces(1, 3) = temp;
|
2026-08-10 16:05:10 -05:00
|
|
|
}
|
2026-08-12 08:29:06 -05:00
|
|
|
*/
|
2026-08-10 16:05:10 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-08-12 08:29:06 -05:00
|
|
|
/*
|
2026-08-10 16:05:10 -05:00
|
|
|
void CAes::InvMixColumns(uint8_t &state[]) const
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
uint8_t a, b, c, d;
|
|
|
|
|
for(i = 0; i < 4; ++i)
|
|
|
|
|
{
|
|
|
|
|
a = AesStateAcces(i, 0);
|
|
|
|
|
b = AesStateAcces(i, 1);
|
|
|
|
|
c = AesStateAcces(i, 2);
|
|
|
|
|
d = AesStateAcces(i, 3);
|
|
|
|
|
AesStateAcces(i, 0) = AesMultiply(a, 0x0e) ^ AesMultiply(b, 0x0b) ^ AesMultiply(c, 0x0d) ^ AesMultiply(d, 0x09);
|
|
|
|
|
AesStateAcces(i, 1) = AesMultiply(a, 0x09) ^ AesMultiply(b, 0x0e) ^ AesMultiply(c, 0x0b) ^ AesMultiply(d, 0x0d);
|
|
|
|
|
AesStateAcces(i, 2) = AesMultiply(a, 0x0d) ^ AesMultiply(b, 0x09) ^ AesMultiply(c, 0x0e) ^ AesMultiply(d, 0x0b);
|
|
|
|
|
AesStateAcces(i, 3) = AesMultiply(a, 0x0b) ^ AesMultiply(b, 0x0d) ^ AesMultiply(c, 0x09) ^ AesMultiply(d, 0x0e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CAes::InvSubBytes(uint8_t &state[]) const
|
|
|
|
|
{
|
2026-08-12 08:29:06 -05:00
|
|
|
uint8_t i;
|
2026-08-10 16:05:10 -05:00
|
|
|
for(i = 0; i < 4; ++i)
|
|
|
|
|
{
|
2026-08-12 08:29:06 -05:00
|
|
|
AesStateAcces(0, i) = getSBoxInvert(AesStateAcces(0, i));
|
|
|
|
|
AesStateAcces(1, i) = getSBoxInvert(AesStateAcces(1, i));
|
|
|
|
|
AesStateAcces(2, i) = getSBoxInvert(AesStateAcces(2, i));
|
|
|
|
|
AesStateAcces(3, i) = getSBoxInvert(AesStateAcces(3, i));
|
2026-08-10 16:05:10 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CAes::InvShiftRows(uint8_t &state[]) const
|
|
|
|
|
{
|
|
|
|
|
// Rotate first row 1 columns to right
|
2026-08-12 08:29:06 -05:00
|
|
|
uint8_t temp = AesStateAcces(3, 1);
|
2026-08-10 16:05:10 -05:00
|
|
|
AesStateAcces(3, 1) = AesStateAcces(2, 1);
|
|
|
|
|
AesStateAcces(2, 1) = AesStateAcces(1, 1);
|
|
|
|
|
AesStateAcces(1, 1) = AesStateAcces(0, 1);
|
|
|
|
|
AesStateAcces(0, 1) = temp;
|
|
|
|
|
// Rotate second row 2 columns to right
|
|
|
|
|
temp = AesStateAcces(0, 2);
|
|
|
|
|
AesStateAcces(0, 2) = AesStateAcces(2, 2);
|
|
|
|
|
AesStateAcces(2, 2) = temp;
|
|
|
|
|
temp = AesStateAcces(1, 2);
|
|
|
|
|
AesStateAcces(1, 2) = AesStateAcces(3, 2);
|
|
|
|
|
AesStateAcces(3, 2) = temp;
|
|
|
|
|
// Rotate third row 3 columns to right
|
|
|
|
|
temp = AesStateAcces(0, 3);
|
|
|
|
|
AesStateAcces(0, 3) = AesStateAcces(1, 3);
|
|
|
|
|
AesStateAcces(1, 3) = AesStateAcces(2, 3);
|
|
|
|
|
AesStateAcces(2, 3) = AesStateAcces(3, 3);
|
|
|
|
|
AesStateAcces(3, 3) = temp;
|
|
|
|
|
}
|
2026-08-12 08:29:06 -05:00
|
|
|
*/
|
2026-08-10 16:05:10 -05:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Cifrado\Descifrado de un block de 16 exactos |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-08-12 08:29:06 -05:00
|
|
|
void CAes::Cifrar(uint8_t& state[]) const
|
2026-08-10 16:05:10 -05:00
|
|
|
{
|
|
|
|
|
uint8_t round = 0;
|
|
|
|
|
|
|
|
|
|
// Add the First round key to the buf before starting the rounds.
|
2026-08-12 08:29:06 -05:00
|
|
|
AddRoundKey(0, state);
|
2026-08-10 16:05:10 -05:00
|
|
|
|
|
|
|
|
// There will be m_nr rounds.
|
|
|
|
|
// The first m_nr-1 rounds are identical.
|
|
|
|
|
// These m_nr rounds are executed in the loop below.
|
|
|
|
|
// Last one without MixColumns()
|
|
|
|
|
for(round = 1; ; ++round)
|
|
|
|
|
{
|
2026-08-12 08:29:06 -05:00
|
|
|
//--- Subbytes
|
|
|
|
|
// SubBytes(state);
|
|
|
|
|
uint8_t i;
|
|
|
|
|
for(i = 0; i < 4; ++i)
|
|
|
|
|
{
|
|
|
|
|
// unrrolled
|
|
|
|
|
AesStateAcces(0, i) = getSBoxValue(AesStateAcces(0, i));
|
|
|
|
|
AesStateAcces(1, i) = getSBoxValue(AesStateAcces(1, i));
|
|
|
|
|
AesStateAcces(2, i) = getSBoxValue(AesStateAcces(2, i));
|
|
|
|
|
AesStateAcces(3, i) = getSBoxValue(AesStateAcces(3, i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Shift rows
|
|
|
|
|
// Inline
|
|
|
|
|
//ShiftRows(state);
|
|
|
|
|
// temp;
|
|
|
|
|
// Rotate first row 1 columns to left
|
|
|
|
|
uint8_t temp = AesStateAcces(0, 1);
|
|
|
|
|
AesStateAcces(0, 1) = AesStateAcces(1, 1);
|
|
|
|
|
AesStateAcces(1, 1) = AesStateAcces(2, 1);
|
|
|
|
|
AesStateAcces(2, 1) = AesStateAcces(3, 1);
|
|
|
|
|
AesStateAcces(3, 1) = temp;
|
|
|
|
|
// Rotate second row 2 columns to left
|
|
|
|
|
temp = AesStateAcces(0, 2);
|
|
|
|
|
AesStateAcces(0, 2) = AesStateAcces(2, 2);
|
|
|
|
|
AesStateAcces(2, 2) = temp;
|
|
|
|
|
temp = AesStateAcces(1, 2);
|
|
|
|
|
AesStateAcces(1, 2) = AesStateAcces(3, 2);
|
|
|
|
|
AesStateAcces(3, 2) = temp;
|
|
|
|
|
// Rotate third row 3 columns to left
|
|
|
|
|
temp = AesStateAcces(0, 3);
|
|
|
|
|
AesStateAcces(0, 3) = AesStateAcces(3, 3);
|
|
|
|
|
AesStateAcces(3, 3) = AesStateAcces(2, 3);
|
|
|
|
|
AesStateAcces(2, 3) = AesStateAcces(1, 3);
|
|
|
|
|
AesStateAcces(1, 3) = temp;
|
|
|
|
|
|
|
|
|
|
//---
|
2026-08-10 16:05:10 -05:00
|
|
|
if(round == m_nr)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-08-12 08:29:06 -05:00
|
|
|
|
|
|
|
|
//--- Mix columns
|
|
|
|
|
//MixColumns(state); Inline
|
|
|
|
|
uint8_t Tmp, Tm, t;
|
|
|
|
|
//---
|
|
|
|
|
for(i = 0; i < 4; ++i)
|
|
|
|
|
{
|
|
|
|
|
t = AesStateAcces(i, 0);
|
|
|
|
|
Tm = t ^ AesStateAcces(i, 1);
|
|
|
|
|
Tmp = Tm ^ AesStateAcces(i, 2) ^ AesStateAcces(i, 3);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
Tm = xtime(Tm);
|
|
|
|
|
AesStateAcces(i, 0) ^= Tm ^ Tmp ;
|
|
|
|
|
Tm = AesStateAcces(i, 1) ^ AesStateAcces(i, 2) ;
|
|
|
|
|
Tm = xtime(Tm);
|
|
|
|
|
AesStateAcces(i, 1) ^= Tm ^ Tmp ;
|
|
|
|
|
Tm = AesStateAcces(i, 2) ^ AesStateAcces(i, 3) ;
|
|
|
|
|
Tm = xtime(Tm);
|
|
|
|
|
AesStateAcces(i, 2) ^= Tm ^ Tmp ;
|
|
|
|
|
Tm = AesStateAcces(i, 3) ^ t ;
|
|
|
|
|
Tm = xtime(Tm);
|
|
|
|
|
AesStateAcces(i, 3) ^= Tm ^ Tmp ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
AddRoundKey(round, state);
|
2026-08-10 16:05:10 -05:00
|
|
|
}
|
2026-08-12 08:29:06 -05:00
|
|
|
|
|
|
|
|
//---
|
2026-08-10 16:05:10 -05:00
|
|
|
// Add round key to last round
|
2026-08-12 08:29:06 -05:00
|
|
|
AddRoundKey(m_nr, state);
|
2026-08-10 16:05:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-08-12 08:29:06 -05:00
|
|
|
void CAes::CifradoInverso(uint8_t& state[]) const
|
2026-08-10 16:05:10 -05:00
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
// Add the First round key to the buf before starting the rounds.
|
2026-08-12 08:29:06 -05:00
|
|
|
AddRoundKey(m_nr, state);
|
2026-08-10 16:05:10 -05:00
|
|
|
|
|
|
|
|
// There will be m_nr rounds.
|
|
|
|
|
// The first m_nr-1 rounds are identical.
|
|
|
|
|
// These m_nr rounds are executed in the loop below.
|
|
|
|
|
// Last one without InvMixColumn()
|
2026-08-12 08:29:06 -05:00
|
|
|
for(uint8_t round = uchar(m_nr - 1); ; --round)
|
2026-08-10 16:05:10 -05:00
|
|
|
{
|
2026-08-12 08:29:06 -05:00
|
|
|
//---
|
|
|
|
|
// InvShiftRows
|
|
|
|
|
// Rotate first row 1 columns to right
|
|
|
|
|
uint8_t temp = AesStateAcces(3, 1);
|
|
|
|
|
AesStateAcces(3, 1) = AesStateAcces(2, 1);
|
|
|
|
|
AesStateAcces(2, 1) = AesStateAcces(1, 1);
|
|
|
|
|
AesStateAcces(1, 1) = AesStateAcces(0, 1);
|
|
|
|
|
AesStateAcces(0, 1) = temp;
|
|
|
|
|
// Rotate second row 2 columns to right
|
|
|
|
|
temp = AesStateAcces(0, 2);
|
|
|
|
|
AesStateAcces(0, 2) = AesStateAcces(2, 2);
|
|
|
|
|
AesStateAcces(2, 2) = temp;
|
|
|
|
|
temp = AesStateAcces(1, 2);
|
|
|
|
|
AesStateAcces(1, 2) = AesStateAcces(3, 2);
|
|
|
|
|
AesStateAcces(3, 2) = temp;
|
|
|
|
|
// Rotate third row 3 columns to right
|
|
|
|
|
temp = AesStateAcces(0, 3);
|
|
|
|
|
AesStateAcces(0, 3) = AesStateAcces(1, 3);
|
|
|
|
|
AesStateAcces(1, 3) = AesStateAcces(2, 3);
|
|
|
|
|
AesStateAcces(2, 3) = AesStateAcces(3, 3);
|
|
|
|
|
AesStateAcces(3, 3) = temp;
|
|
|
|
|
|
|
|
|
|
//--- SubBytes
|
|
|
|
|
// InvSubBytes(state);
|
|
|
|
|
for(uint8_t i = 0; i < 4; ++i)
|
|
|
|
|
{
|
|
|
|
|
AesStateAcces(0, i) = getSBoxInvert(AesStateAcces(0, i));
|
|
|
|
|
AesStateAcces(1, i) = getSBoxInvert(AesStateAcces(1, i));
|
|
|
|
|
AesStateAcces(2, i) = getSBoxInvert(AesStateAcces(2, i));
|
|
|
|
|
AesStateAcces(3, i) = getSBoxInvert(AesStateAcces(3, i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
AddRoundKey(round, state);
|
2026-08-10 16:05:10 -05:00
|
|
|
if(round == 0)
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-08-12 08:29:06 -05:00
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// InvMixColumns(state);
|
|
|
|
|
uint8_t a, b, c, d;
|
|
|
|
|
for(int i = 0; i < 4; ++i)
|
|
|
|
|
{
|
|
|
|
|
a = AesStateAcces(i, 0);
|
|
|
|
|
b = AesStateAcces(i, 1);
|
|
|
|
|
c = AesStateAcces(i, 2);
|
|
|
|
|
d = AesStateAcces(i, 3);
|
|
|
|
|
AesStateAcces(i, 0) = AesMultiply(a, 0x0e) ^ AesMultiply(b, 0x0b) ^ AesMultiply(c, 0x0d) ^ AesMultiply(d, 0x09);
|
|
|
|
|
AesStateAcces(i, 1) = AesMultiply(a, 0x09) ^ AesMultiply(b, 0x0e) ^ AesMultiply(c, 0x0b) ^ AesMultiply(d, 0x0d);
|
|
|
|
|
AesStateAcces(i, 2) = AesMultiply(a, 0x0d) ^ AesMultiply(b, 0x09) ^ AesMultiply(c, 0x0e) ^ AesMultiply(d, 0x0b);
|
|
|
|
|
AesStateAcces(i, 3) = AesMultiply(a, 0x0b) ^ AesMultiply(b, 0x0d) ^ AesMultiply(c, 0x09) ^ AesMultiply(d, 0x0e);
|
|
|
|
|
}
|
2026-08-10 16:05:10 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Cifrado\Descifrado CBC |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
// buf = entrada se cifra
|
|
|
|
|
// lenght multiplde blockslen (si no esta ajusta padding con len % BLOCK len eso te da lo que falta lo sumas y rellenas)
|
|
|
|
|
void CAes::CbcCifrado(uint8_t &buf[], uint length)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
m_ivs = -1;
|
|
|
|
|
for(m_ks = 0; m_ks < length; m_ks += AES_BLOCKLEN)
|
|
|
|
|
{
|
|
|
|
|
//--- Xor
|
|
|
|
|
// The block in AES is always 128bit no matter the key size
|
|
|
|
|
if(m_ivs == -1)
|
|
|
|
|
{
|
|
|
|
|
for(uint k = 0; k < AES_BLOCKLEN; ++k)
|
|
|
|
|
buf[m_ks + k] ^= m_iv[k];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for(uint k = 0; k < AES_BLOCKLEN; ++k)
|
|
|
|
|
buf[m_ks + k] ^= buf[m_ivs + k];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// cifra desde m_ks
|
|
|
|
|
Cifrar(buf);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
m_ivs = (int)m_ks; // Ahora punta ahi..
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
/* store Iv in ctx for next call */
|
|
|
|
|
if(m_save_last_ivs_in_cbc)
|
|
|
|
|
{
|
|
|
|
|
ArrayCopy(m_iv, buf, 0, m_ivs, AES_BLOCKLEN); // memcpy(ctx->Iv, Iv, AES_BLOCKLEN);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CAes::CbcDescifra(uchar &buf[], uint length)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
m_ivs = -1;
|
|
|
|
|
uint8_t storeNextIv[AES_BLOCKLEN];
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
for(m_ks = 0; m_ks < length; m_ks += AES_BLOCKLEN)
|
|
|
|
|
{
|
|
|
|
|
//--- Copiamos en el temporañ
|
|
|
|
|
//memcpy(storeNextIv, buf, AES_BLOCKLEN);
|
|
|
|
|
for(int i = 0; i < AES_BLOCKLEN; i++)
|
|
|
|
|
storeNextIv[i] = buf[m_ks + i];
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
CifradoInverso(buf);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
//XorWithIv(buf, ctx->Iv);
|
|
|
|
|
//--- Xor
|
|
|
|
|
// The block in AES is always 128bit no matter the key size
|
|
|
|
|
if(m_ivs == -1)
|
|
|
|
|
{
|
|
|
|
|
for(uint k = 0; k < AES_BLOCKLEN; ++k)
|
|
|
|
|
buf[m_ks + k] ^= m_iv[k];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for(uint k = 0; k < AES_BLOCKLEN; ++k)
|
|
|
|
|
buf[m_ks + k] ^= buf[m_ivs + k];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN);,
|
|
|
|
|
for(int i = 0; i < AES_BLOCKLEN; i++)
|
|
|
|
|
{
|
|
|
|
|
m_iv[i] = storeNextIv[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// buf += AES_BLOCKLEN; ya se hace en el foir
|
|
|
|
|
}
|
|
|
|
|
// Nota que nosotros no hacesmos suma de putneros para iterar
|
|
|
|
|
// Si no que tenemso un integer que es como nuestro puntero de lecutra
|
|
|
|
|
// ENtonces nosotros modificamos eso..
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void CAes::CtrCryptX(uint8_t& buf[], uint length)
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
uint8_t buffer[AES_BLOCKLEN];
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
uint i;
|
|
|
|
|
int bi;
|
|
|
|
|
m_ks = 0; // start en 0
|
|
|
|
|
|
|
|
|
|
// La idea aqui es ir cifrando iv y aplicar xor con el buffer
|
|
|
|
|
//---
|
|
|
|
|
for(i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi)
|
|
|
|
|
{
|
|
|
|
|
if(bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */
|
|
|
|
|
{
|
|
|
|
|
// memcpy(buffer, m_iv, AES_BLOCKLEN);
|
|
|
|
|
for(int k = 0; k < AES_BLOCKLEN; k++)
|
|
|
|
|
{
|
|
|
|
|
buffer[k] = m_iv[k];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
Cifrar(buffer);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
// Sumar en 1 (base 256)
|
|
|
|
|
/* Increment Iv and handle overflow */
|
|
|
|
|
for(bi = (AES_BLOCKLEN - 1); bi >= 0; --bi)
|
|
|
|
|
{
|
|
|
|
|
/* inc will overflow */
|
|
|
|
|
if(m_iv[bi] == 255)
|
|
|
|
|
{
|
|
|
|
|
m_iv[bi] = 0;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
m_iv[bi] += 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
bi = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-- xor
|
|
|
|
|
buf[i] = (buf[i] ^ buffer[bi]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
static void CAes::CorrectPadding(uchar &in[])
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
const int t = ArraySize(in);
|
|
|
|
|
uchar ext = uchar(t % AES_BLOCKLEN);
|
|
|
|
|
if(ext == 0)
|
|
|
|
|
ext = 16;
|
|
|
|
|
|
|
|
|
|
//----
|
|
|
|
|
const int fs = t + ext;
|
|
|
|
|
ArrayResize(in, fs);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
for(int i = t; i < fs; i++)
|
|
|
|
|
{
|
|
|
|
|
in[i] = ext;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
static bool CAes::QuitarPadding(uchar &in[])
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
const int t = ArraySize(in);
|
|
|
|
|
if(t < 1)
|
|
|
|
|
return true; // raro no hay nada.. asi que no hayt errores
|
|
|
|
|
const uchar last = in[t - 1];
|
|
|
|
|
|
|
|
|
|
//--- Check de range
|
|
|
|
|
if(last < 1 || last > AES_BLOCKLEN)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
const int fs = int(t - last);
|
|
|
|
|
for(int i = fs; i < t; i++)
|
|
|
|
|
{
|
|
|
|
|
if(in[i] != last)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
ArrayResize(in, fs);
|
|
|
|
|
|
|
|
|
|
//---
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-08-10 16:09:46 -05:00
|
|
|
#endif // CRYPTOBYLEO_SRC_SIMETRIC_AES_MAIN_MQH
|