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
|
| | |
|
| | | private:
|
| | | //_--
|
| | | ENUM_AES_TYPE_CRYPTH m_method;
|
| | | ENUM_AES_LAST_ERR m_last_err;
|
| | |
|
2026-08-26 09:08:11 -05:00 | | | //--
|
| | | uint m_ks; // desde donde inica el buffer pasado para cifrar\descifrar
|
| | |
|
2026-08-10 16:05:10 -05:00 | | | //---
|
| | | int m_ivs;
|
| | |
|
| | | //---
|
2026-08-26 09:08:11 -05:00 | | | int m_round_key_s; // size
|
2026-08-10 16:05:10 -05:00 | | | uint8_t m_round_key[AES_MAX_KEY_FINAL_S]; // round key
|
| | |
|
| | | //---
|
2026-08-26 09:08:11 -05:00 | | | uint m_ncol; // nuymeo de columnas en la clave (4 = clavelen\4) (Nk)
|
| | | uint m_ncol_div; // /m_ncol (division por mncol) pasdo a shift
|
| | | uint m_ncol_last; // m_ncol-1 (para fast %)
|
| | | uint m_nr; // numero de rondas (nk+6)
|
2026-08-10 16:05:10 -05:00 | | | int m_expected_len_key; // tamaño de clave que se espera
|
| | |
|
| | |
|
| | | //---
|
| | | void AddRoundKey(uint round, uint8_t& state[]) const;
|
| | |
|
2026-08-26 08:21:19 -05:00 | | | __forceinline uint8_t xtime(uint8_t x) const;
|
2026-08-10 16:05:10 -05:00 | | |
|
| | |
|
| | | public:
|
2026-09-02 10:54:31 -05:00 | | | CAes(ENUM_AES_TYPE_CRYPTH method);
|
| | | CAes(void) {}
|
2026-08-10 16:05:10 -05:00 | | | ~CAes(void) {}
|
| | |
|
2026-08-26 09:08:11 -05:00 | | | //--- Metodo base
|
2026-08-10 16:05:10 -05:00 | | | void Method(ENUM_AES_TYPE_CRYPTH tcrypht);
|
2026-09-02 10:01:34 -05:00 | | | __forceinline ENUM_AES_TYPE_CRYPTH Method() const { return m_method; }
|
2026-08-10 16:05:10 -05:00 | | |
|
2026-08-26 08:21:19 -05:00 | | | //--- Expansion de key
|
2026-09-02 10:01:34 -05:00 | | | void KeyExpansion(const uint8_t& key[], int key_off = 0);
|
2026-08-26 08:21:19 -05:00 | | |
|
| | | //--- Iniclizacoins (Seteo de key e iv)
|
2026-09-02 10:01:34 -05:00 | | | bool Init(const uint8_t &key[], int key_off = 0);
|
| | | bool Init(const uint8_t& key[], const uint8_t& iv[], int key_off = 0);
|
2026-08-10 16:05:10 -05:00 | | |
|
| | | //--- 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
|
2026-09-01 17:56:09 -05:00 | | | void CbcCifrado(uint8_t &buf[], uint length, uint buf_off = 0);
|
| | | void CbcDescifra(uint8_t& buf[], uint length, uint buf_off = 0);
|
2026-08-10 16:05:10 -05:00 | | |
|
| | | //--- CTR
|
| | | void CtrCryptX(uint8_t& buf[], uint length);
|
| | |
|
2026-09-02 10:01:34 -05:00 | | | //--- Last err
|
| | | __forceinline ENUM_AES_LAST_ERR LastErr() const { return m_last_err; }
|
| | |
|
2026-08-10 16:05:10 -05:00 | | | //---
|
2026-09-01 17:56:09 -05:00 | | | static int PKCS7_CorrectPadding(uchar& in[], int t, int i = 0);
|
| | | static int PKCS7_QuitarPadding(uchar& in[], int t, int i = 0);
|
2026-08-10 16:05:10 -05:00 | | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-09-02 10:54:31 -05:00 | | | CAes::CAes(ENUM_AES_TYPE_CRYPTH method)
|
2026-08-10 16:05:10 -05:00 | | | {
|
2026-09-02 10:54:31 -05:00 | | | Method(method);
|
2026-08-10 16:05:10 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-09-02 10:01:34 -05:00 | | | void CAes::KeyExpansion(const uint8_t & key[], int key_off = 0)
|
2026-08-10 16:05:10 -05:00 | | | {
|
| | | 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
|
| | | // []
|
| | | // []
|
| | | // []
|
2026-09-02 10:01:34 -05:00 | | | // la idea es iterar por cada columna [0 ... m_ncol-1]
|
| | | // y trabajamos a nivel de filas con i=0 trabajsmores con toda la coluimna 0 (lo que implcia uss filas)
|
2026-08-10 16:05:10 -05:00 | | | for(i = 0; i < m_ncol; ++i)
|
| | | {
|
2026-09-02 10:01:34 -05:00 | | | m_round_key[(i << 2) + 0] = key[key_off + ((i << 2) + 0)];
|
| | | m_round_key[(i << 2) + 1] = key[key_off + ((i << 2) + 1)];
|
| | | m_round_key[(i << 2) + 2] = key[key_off + ((i << 2) + 2)];
|
| | | m_round_key[(i << 2) + 3] = key[key_off + ((i << 2) + 3)];
|
2026-08-10 16:05:10 -05:00 | | | }
|
| | |
|
| | |
|
| | | //---
|
2026-09-02 10:01:34 -05:00 | | | // luego empzamos en la utliam fila hasta el numero de rondas << 2 +1
|
2026-08-10 16:05:10 -05:00 | | | for(i = m_ncol; i < AES_COL_S * (m_nr + 1); ++i)
|
| | | {
|
| | | {
|
| | | // Obtenemos palabra
|
2026-09-02 10:01:34 -05:00 | | | k = (i - 1) << 2;
|
2026-08-10 16:05:10 -05:00 | | | 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]);
|
| | | }
|
| | |
|
2026-08-26 08:21:19 -05:00 | | | tempa[0] = tempa[0] ^ g_aes_rcon[i >> m_ncol_div];
|
2026-08-10 16:05:10 -05:00 | | | }
|
| | | //#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
|
2026-09-02 10:01:34 -05:00 | | | j = i << 2;
|
| | | k = (i - m_ncol) << 2;
|
2026-08-10 16:05:10 -05:00 | | | 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;
|
2026-08-26 08:21:19 -05:00 | | | m_nr = 10;
|
| | |
|
| | | //---
|
2026-08-10 16:05:10 -05:00 | | | m_ncol = 4;
|
| | | m_ncol_last = 3;
|
2026-08-26 08:21:19 -05:00 | | | m_ncol_div = 2; // x>>2 = x/4
|
2026-08-10 16:05:10 -05:00 | | | break;
|
| | | }
|
| | | case AES_CRYPTH_256:
|
| | | {
|
| | | m_round_key_s = 240;
|
| | | m_expected_len_key = 32;
|
2026-08-26 08:21:19 -05:00 | | | m_nr = 14;
|
| | |
|
| | | //---
|
2026-08-10 16:05:10 -05:00 | | | m_ncol = 8;
|
| | | m_ncol_last = 7;
|
2026-08-26 08:21:19 -05:00 | | | m_ncol_div = 3; // x>>3= x/8
|
2026-08-10 16:05:10 -05:00 | | | break;
|
| | | }
|
| | | default:
|
| | | {
|
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-09-02 10:01:34 -05:00 | | | bool CAes::Init(const uint8_t &key[], int key_off = 0)
|
2026-08-10 16:05:10 -05:00 | | | {
|
2026-09-02 10:01:34 -05:00 | | | if(ArraySize(key) < m_expected_len_key)
|
2026-08-10 16:05:10 -05:00 | | | {
|
| | | m_last_err = AES_LAST_ERR_INVALID_KEY_LEN;
|
| | | return false;
|
| | | }
|
2026-09-02 10:01:34 -05:00 | | | KeyExpansion(key, key_off);
|
2026-08-10 16:05:10 -05:00 | | | return true;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-09-02 10:01:34 -05:00 | | | bool CAes::Init(const uint8_t &key[], const uint8_t &iv[], int key_off = 0)
|
2026-08-10 16:05:10 -05:00 | | | {
|
2026-09-02 10:01:34 -05:00 | | | //---
|
| | | if(ArraySize(key) < m_expected_len_key)
|
2026-08-10 16:05:10 -05:00 | | | {
|
| | | m_last_err = AES_LAST_ERR_INVALID_KEY_LEN;
|
| | | return false;
|
| | | }
|
2026-09-02 10:01:34 -05:00 | | | if(ArraySize(iv) < AES_BLOCKLEN)
|
2026-08-10 16:05:10 -05:00 | | | {
|
| | | m_last_err = AES_LAST_ERR_INVALID_IV_SIZE;
|
| | | return false;
|
| | | }
|
| | |
|
| | | //---
|
2026-09-02 10:01:34 -05:00 | | | KeyExpansion(key, key_off);
|
2026-08-26 08:21:19 -05:00 | | | ArrayCopy(m_iv, iv, 0, 0, AES_BLOCKLEN);
|
2026-08-10 16:05:10 -05:00 | | | return true;
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | // con el buffer acutal aplicamos un xor con el key
|
| | | void CAes::AddRoundKey(uint round, uint8_t& state[]) const
|
| | | {
|
2026-09-02 10:01:34 -05:00 | | | for(uint8_t i = 0; i < 4; ++i)
|
2026-08-10 16:05:10 -05:00 | | | {
|
2026-08-12 08:29:06 -05:00 | | | // unrolled
|
2026-09-02 10:01:34 -05:00 | | | AesStateAcces(i, 0) ^= m_round_key[(round * (AES_COL_S << 2)) + (i * AES_COL_S) + 0];
|
| | | AesStateAcces(i, 1) ^= m_round_key[(round * (AES_COL_S << 2)) + (i * AES_COL_S) + 1];
|
| | | AesStateAcces(i, 2) ^= m_round_key[(round * (AES_COL_S << 2)) + (i * AES_COL_S) + 2];
|
| | | AesStateAcces(i, 3) ^= m_round_key[(round * (AES_COL_S << 2)) + (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)
|
2026-09-01 17:56:09 -05:00 | | | void CAes::CbcCifrado(uint8_t &buf[], uint length, uint buf_off = 0)
|
2026-08-10 16:05:10 -05:00 | | | {
|
| | | //---
|
| | | m_ivs = -1;
|
2026-09-01 17:56:09 -05:00 | | | m_ks = buf_off;
|
| | | length += buf_off;
|
| | |
|
| | | //---
|
| | | for(; m_ks < length; m_ks += AES_BLOCKLEN)
|
2026-08-10 16:05:10 -05:00 | | | {
|
| | | //--- 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 */
|
2026-08-26 09:08:11 -05:00 | | | // if(m_save_last_ivs_in_cbc)
|
| | | // {
|
| | | ArrayCopy(m_iv, buf, 0, m_ivs, AES_BLOCKLEN); // memcpy(ctx->Iv, Iv, AES_BLOCKLEN);
|
| | | // }
|
2026-08-10 16:05:10 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-09-01 17:56:09 -05:00 | | | void CAes::CbcDescifra(uchar &buf[], uint length, uint buf_off = 0)
|
2026-08-10 16:05:10 -05:00 | | | {
|
| | | //---
|
| | | m_ivs = -1;
|
| | | uint8_t storeNextIv[AES_BLOCKLEN];
|
2026-09-01 17:56:09 -05:00 | | | m_ks = buf_off;
|
| | | length += buf_off;
|
2026-08-10 16:05:10 -05:00 | | |
|
| | | //---
|
2026-09-01 17:56:09 -05:00 | | | for(; m_ks < length; m_ks += AES_BLOCKLEN)
|
2026-08-10 16:05:10 -05:00 | | | {
|
| | | //--- Copiamos en el temporañ
|
| | | //memcpy(storeNextIv, buf, AES_BLOCKLEN);
|
2026-08-26 09:08:11 -05:00 | | | // for(int i = 0; i < AES_BLOCKLEN; i++)
|
| | | // storeNextIv[i] = buf[m_ks + i];
|
| | | ArrayCopy(storeNextIv, buf, 0, m_ks, AES_BLOCKLEN);
|
2026-08-10 16:05:10 -05:00 | | |
|
| | | //---
|
| | | 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);,
|
2026-08-26 09:08:11 -05:00 | | | ArrayCopy(m_iv, storeNextIv, 0, 0, AES_BLOCKLEN);
|
| | | // for(int i = 0; i < AES_BLOCKLEN; i++)
|
| | | // {
|
| | | // m_iv[i] = storeNextIv[i];
|
| | | // }
|
2026-08-10 16:05:10 -05:00 | | |
|
| | | // 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]);
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-08-26 09:08:11 -05:00 | | | //| PKCS#7 Padding |
|
2026-08-10 16:05:10 -05:00 | | | //+------------------------------------------------------------------+
|
2026-09-01 17:56:09 -05:00 | | | // de un array in
|
| | | // t=tamaño del bloque a verificar (len)
|
| | | // i=posicion de inicio del bloque en el array in
|
| | | // tipo [offset:len] se analiza solo un trozo del array que el user diga
|
| | | // no todo el array y se agraga padding luego del len
|
| | |
|
| | | static int CAes::PKCS7_CorrectPadding(uchar &in[], int t, int i = 0)
|
2026-08-10 16:05:10 -05:00 | | | {
|
| | | //---
|
2026-08-26 09:08:11 -05:00 | | | uchar ext = AES_BLOCKLEN - uchar(t % AES_BLOCKLEN);
|
2026-08-10 16:05:10 -05:00 | | | if(ext == 0)
|
| | | ext = 16;
|
| | |
|
| | | //----
|
2026-09-01 17:56:09 -05:00 | | | const int fs = i + t + ext;
|
2026-08-26 09:08:11 -05:00 | | | if(fs > ArraySize(in))
|
| | | ArrayResize(in, fs);
|
2026-08-10 16:05:10 -05:00 | | |
|
| | | //---
|
2026-09-01 17:56:09 -05:00 | | | i += t; // escritura empeiza donde termina (justo ahi pnemos el padding)
|
| | | for(; i < fs; i++)
|
2026-08-10 16:05:10 -05:00 | | | {
|
| | | in[i] = ext;
|
| | | }
|
2026-08-26 09:08:11 -05:00 | | |
|
| | | //---
|
2026-09-01 17:56:09 -05:00 | | | return fs; // nuevo tamaño FINAL [offset+t+ext]
|
2026-08-10 16:05:10 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-09-01 17:56:09 -05:00 | | | static int CAes::PKCS7_QuitarPadding(uchar &in[], int t, int i = 0)
|
2026-08-10 16:05:10 -05:00 | | | {
|
| | | //---
|
| | | if(t < 1)
|
2026-08-26 09:08:11 -05:00 | | | return 0; // raro no hay nada.. asi que no hayt errores
|
2026-09-01 17:56:09 -05:00 | | |
|
| | | //---
|
| | | i += t;
|
| | | const uchar last = in[i - 1];
|
2026-08-10 16:05:10 -05:00 | | |
|
| | | //--- Check de range
|
| | | if(last < 1 || last > AES_BLOCKLEN)
|
2026-08-26 09:08:11 -05:00 | | | return -1;
|
2026-08-10 16:05:10 -05:00 | | |
|
| | | //---
|
2026-09-01 17:56:09 -05:00 | | | // tamaño final recortado
|
| | | const int fs = int(i - last);
|
| | |
|
| | | //---
|
2026-08-26 09:08:11 -05:00 | | | uchar v = 0;
|
2026-09-01 17:56:09 -05:00 | | | i = fs; // lo ponemos justo donde empiza el padding
|
| | | for(; i < t; i++) // chekeamos en tiempo constante
|
2026-08-10 16:05:10 -05:00 | | | {
|
2026-08-26 09:08:11 -05:00 | | | v |= in[i] ^ last;
|
2026-08-10 16:05:10 -05:00 | | | }
|
| | |
|
| | | //---
|
2026-08-26 09:08:11 -05:00 | | | if(v != 0)
|
2026-09-01 17:56:09 -05:00 | | | return -1; // fallo
|
2026-08-10 16:05:10 -05:00 | | |
|
| | | //---
|
2026-08-26 09:08:11 -05:00 | | | return fs; // tamaño final solo lo retornamos el usre decide que hace..
|
2026-08-10 16:05:10 -05:00 | | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-08-10 16:09:46 -05:00 | | | #endif // CRYPTOBYLEO_SRC_SIMETRIC_AES_MAIN_MQH
|