CryptoByLeo/Src/Simetric/AES/Main.mqh
2026-08-12 08:29:06 -05:00

765 lignes
22 Kio
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_SIMETRIC_AES_MAIN_MQH
#define CRYPTOBYLEO_SRC_SIMETRIC_AES_MAIN_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#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;
__forceinline uint8_t xtime(uint8_t x) const;
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
void CifradoInverso(uint8_t& state[]) const;
void Cifrar(uint8_t& state[]) const;
//--- 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
{
uint8_t i;
for(i = 0; i < 4; ++i)
{
// 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];
}
}
//+------------------------------------------------------------------+
// 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
/*
void CAes::SubBytes(uint8_t &state[]) const
{
uint8_t i, j;
for(i = 0; i < 4; ++i)
{
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));
}
}
//+------------------------------------------------------------------+
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;
}*/
/*
//+------------------------------------------------------------------+
void CAes::MixColumns(uint8_t &state[]) const
{
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;
}
*/
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
/*
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
{
uint8_t i;
for(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));
}
}
//+------------------------------------------------------------------+
void CAes::InvShiftRows(uint8_t &state[]) const
{
// 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;
}
*/
//+------------------------------------------------------------------+
//| Cifrado\Descifrado de un block de 16 exactos |
//+------------------------------------------------------------------+
void CAes::Cifrar(uint8_t& state[]) const
{
uint8_t round = 0;
// Add the First round key to the buf before starting the rounds.
AddRoundKey(0, state);
// 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)
{
//--- 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;
//---
if(round == m_nr)
{
break;
}
//--- 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);
}
//---
// Add round key to last round
AddRoundKey(m_nr, state);
}
//+------------------------------------------------------------------+
void CAes::CifradoInverso(uint8_t& state[]) const
{
//---
// Add the First round key to the buf before starting the rounds.
AddRoundKey(m_nr, state);
// 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()
for(uint8_t round = uchar(m_nr - 1); ; --round)
{
//---
// 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);
if(round == 0)
{
break;
}
//---
// 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);
}
}
}
//+------------------------------------------------------------------+
//| 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;
}
}
//+------------------------------------------------------------------+
#endif // CRYPTOBYLEO_SRC_SIMETRIC_AES_MAIN_MQH