2026-08-19 13:03:20 -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_PADDING_OAEP_MAIN_MQH
|
| | | #define CRYPTOBYLEO_SRC_PADDING_OAEP_MAIN_MQH
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | // mgf1
|
| | | #include "..\\..\\MGF1\\Main.mqh"
|
| | |
|
2026-08-19 16:55:01 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #define CRYPTOBYLEO_OAEP_SEED_I (1)
|
| | |
|
2026-08-19 13:03:20 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | namespace TSN
|
| | | {
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | class COAEP
|
| | | {
|
| | | public:
|
| | | COAEP(void) {}
|
| | | ~COAEP(void) {}
|
| | |
|
| | |
|
2026-08-19 21:20:19 -05:00 | | | //---
|
| | | // msg=mensaje
|
2026-08-30 10:39:49 -05:00 | | | // kmod=tamaño del modulo del RSA en bytes (Ejm 2048 = 256)
|
2026-08-20 17:22:07 -05:00 | | | // random=array random tamaño hlen (consulta el tamaño del hash meta y generalo)
|
2026-08-19 21:20:19 -05:00 | | | // f=funcion
|
| | | // out=buffer de fuera
|
| | | // retorna:
|
| | | // tamaño del array de out, -1 en caso de err
|
2026-08-30 10:39:49 -05:00 | | | static int Encode(const uchar& msg[], int kmod, const uchar& random[],
|
2026-08-20 17:22:07 -05:00 | | | TSN::CCryptoHashMeta::ENUM_TSN_CRYPTO_HASH f, uchar& out[]);
|
| | |
|
2026-08-19 13:03:20 -05:00 | | |
|
2026-08-19 21:20:19 -05:00 | | | //---
|
2026-08-19 21:27:59 -05:00 | | | // NOTA imporante el array buffw uqeda con caracetres >t
|
| | | // eso si quieres lo puedes runcar ArrayResize(buffw, t)
|
| | | // o trabajo con el tamaño t que te da...
|
2026-08-19 21:20:19 -05:00 | | | static int Decode(const uchar& msg[], int k, CCryptoHashMeta::ENUM_TSN_CRYPTO_HASH f, uchar& buffw[]);
|
| | | };
|
2026-08-19 17:43:41 -05:00 | | |
|
2026-08-19 16:55:01 -05:00 | | |
|
2026-08-20 17:22:07 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-08-30 10:39:49 -05:00 | | | static int COAEP::Encode(const uchar& msg[], int kmod, const uchar& random[],
|
2026-08-20 17:22:07 -05:00 | | | TSN::CCryptoHashMeta::ENUM_TSN_CRYPTO_HASH f, uchar& out[])
|
| | | {
|
| | | //---
|
| | | const int hlen = TSN::CCryptoHashMeta::g_crytpo_hash_meta[f].outl; // tamañao de salida
|
| | | const int ml = ArraySize(msg);
|
2026-08-30 10:39:49 -05:00 | | | if(ml > kmod - (hlen << 1) - 2)
|
2026-08-20 17:22:07 -05:00 | | | return -1;
|
| | |
|
| | | //--- deriviacion del taamño final
|
| | | // nota que el tamaño de out hasta este moneto es de = hlen + 1 + (ps) + ml = (DB)
|
2026-08-30 10:39:49 -05:00 | | | // = hlen + 1 + (kmod - ml - (hlen*2) - 2) + ml
|
| | | // = hlen + 1 + kmod - ml - (hlen*2) - 2 + ml --- quitaremos el ml se cancelan
|
| | | // = hlen + 1 + kmod - (hlen*2) - 2 -- + 1
|
| | | // = hlen + kmod - (hlen*2) - 1
|
| | | // = kmod - (hlen + hlen) - 1 + hlen
|
| | | // = kmod - hlen - hlen - 1 + hlen ---- se sale 1
|
| | | // = kmod - hlen - 1
|
| | | // asiq ue eda eso.. .como estimacion final el out hasta qui tendra un tmaño de kmod
|
2026-08-20 17:22:07 -05:00 | | | // y ese es el mismo numro de bytes aleatorio que generaremos
|
2026-08-30 10:39:49 -05:00 | | | const int l = (kmod - hlen - 1); // tamaño out (seed y bloque)
|
2026-08-20 17:22:07 -05:00 | | |
|
| | | //--- diagarmas de ayuda de laypout
|
| | | /*
|
| | | 1. data block
|
| | | - lhash= label hash (en nuestro caso ya vien precauldo a "" la funcion, no soprota label)
|
| | | - ps= paddding de zeros
|
| | | - 01= byte 01
|
| | | - M=mensage peagado
|
| | | +----------+------+--+-------+
|
| | | DB = | lHash | PS |01| M |
|
| | | +----------+------+--+-------+
|
| | |
|
| | | 2. encoeded message
|
| | | 00=Byte 0
|
| | | maskedSeed= Mascara de la semilla
|
| | | maskedDB= Mascara de los datos
|
| | |
|
| | | Tofdo esto concatenado eso seria lo final
|
| | |
|
| | | +--+----------+----------------------------+
|
| | | EM = |00|maskedSeed| maskedDB |
|
| | | +--+----------+----------------------------+
|
| | | */
|
| | |
|
| | | //-- calculo del tamaño final
|
| | | // = 1 + hlen + l
|
| | | // 1= byte0
|
| | | // hlen=masked seed (el seed tiene tamaño de hlen como tal)
|
| | | // l=masked data (la mascara del dato tambien tiene l como tal de size)
|
| | | //--- asi que podemos apicar de una
|
| | | const int sb = hlen + l + 1; // tamaño final + 1 0x1
|
| | | if(sb + l > ArraySize(out)) // sumamso otro l dado que usamos los altos para un temp
|
| | | ArrayResize(out, sb + l);
|
| | |
|
| | | //--- label="" asi qeu copiamso el vacio
|
| | | out[0] = 0x0; // pos 0 = byte1
|
| | |
|
| | | //--- seed
|
| | | //TRandomClass::Random(out, hlen, 1); // aqui ponemos
|
2026-08-29 21:53:22 -05:00 | | | //ArrayCopy(out, random, 1, 0, hlen);
|
2026-08-20 17:22:07 -05:00 | | | for(int k = 0; k < hlen; k++)
|
2026-08-29 21:53:22 -05:00 | | | out[k + 1] = random[k];
|
2026-08-20 17:22:07 -05:00 | | |
|
| | | //--- ahora luego va el hlen calculos pos
|
| | | const int i_db_pos = (CRYPTOBYLEO_OAEP_SEED_I + hlen); // ahora pasamos directo
|
| | | int i = i_db_pos;
|
| | |
|
| | | // esto se peude dado qeu cada hash outl es multiplo de 16 siempre
|
2026-08-23 20:09:15 -05:00 | | | ArrayCopy(out, TSN::CCryptoHashMeta::g_crytpo_hash_empty_out[f].bytes, i, 0, hlen);
|
| | | i += hlen;
|
| | | //for(int k = 0; k < hlen;)
|
| | | // out[i++] = TSN::CCryptoHashMeta::g_crytpo_hash_empty_out[f].bytes[k++];
|
| | |
|
2026-08-20 17:22:07 -05:00 | | |
|
| | | // Print(i);
|
| | | //---
|
2026-08-30 10:39:49 -05:00 | | | // kmod=mod
|
2026-08-20 17:22:07 -05:00 | | | // ml=msg len
|
| | | // hlen=out hash len
|
2026-08-30 10:39:49 -05:00 | | | // const int ps = kmod - ml - (hlen << 1) - 2; // ps
|
2026-08-20 17:22:07 -05:00 | | | // le agregamos in place ps bytes 0
|
2026-08-30 10:39:49 -05:00 | | | #define MGF1_PS (kmod - ml - (hlen << 1) - 2)
|
2026-08-20 17:22:07 -05:00 | | | const int fin = i + MGF1_PS;
|
| | |
|
| | | for(; i < fin; i++)
|
| | | out[i] = 0;
|
| | |
|
| | | // ahora le agregamos un byte
|
| | | out[i++] = 1;
|
| | |
|
| | | // ahora agregamos el mensaje
|
2026-08-29 21:53:22 -05:00 | | | ArrayCopy(out, msg, i, 0, ml);
|
| | | //for(int k = 0; k < ml; k++)
|
| | | // out[i + k] = msg[k];
|
2026-08-20 17:22:07 -05:00 | | | i += ml;
|
| | |
|
| | | //---
|
| | | // aplciamos
|
| | | // el seed se encuntra en [1 ... hlen bytes]
|
| | | // resultado en: [sb ... l bytes]
|
| | | MGF1(out, 1, hlen, out, sb, l, f);
|
| | | // Print(StringFormat("%02X%02X%02X%02X%02X%02X", mask[0], mask[1], mask[2], mask[3], mask[4], mask[5]));
|
| | | // salida de un tamaño de l
|
| | | // ahora mask en si tamabien ahora se convierte en completo a la maskara final
|
| | | //Print("x");
|
| | |
|
| | | //--- xor adb
|
| | | // DB = [i_db_pos ... l bytes]
|
| | | // dbmas = [sb ... l bytes]
|
| | | // k = empzia en DB start y termina en sb (todo l completo)
|
| | | for(int k = 0; k < l; k++)
|
| | | out[i_db_pos + k] ^= out[sb + k];
|
| | | // ahora donde esta DB tenemos masked Db osea ya se le aplico el mask
|
| | |
|
| | | //--- ahora seed
|
| | | // Masked out = [i_db_pos ... l bytes]
|
| | | // resultado en = [sb ... l bytes]
|
| | | MGF1(out, i_db_pos, l, out, sb, hlen, f);
|
| | | // Print(StringFormat("%02X%02X%02X%02X%02X%02X", mask[0], mask[1], mask[2], mask[3], mask[4], mask[5]));
|
| | |
|
| | | // aplicamos xor, para obetner masked_seed
|
| | | // masked_seed = (seed ^ seed_mask)
|
| | | // (NOTA que seed_mask = mask)
|
| | | // seed esta en la ppsoicion CRYPTOBYLEO_OAEP_SEED_I
|
| | | // unrooled 16
|
| | | for(int k = 0; k < hlen;)
|
| | | out[CRYPTOBYLEO_OAEP_SEED_I + k] ^= out[sb + (k++)];
|
| | |
|
| | | // Ahora si terminmos
|
| | | // La idea con todo esto es tratar de crear los mejores buffers temporales
|
| | | // hacerlo todo implace
|
| | | // Ahora mismo solo cree un buffer temporal mask
|
| | | // dado qeu es el unico qeu neceisto pro qeu seed a de estar o en el buff (si es asi otro buff termporla mpara el out)
|
| | | // O como hice yo array sepraod y luego al out le aplico esa seed
|
| | | //---
|
| | | // Nota extra: incluiimos label aunque sea vacio para cumplirt con el protcolo
|
| | | return sb;
|
| | | }
|
| | |
|
| | |
|
2026-08-19 16:55:01 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-08-19 21:20:19 -05:00 | | | static int COAEP::Decode(const uchar &msg[], int k, CCryptoHashMeta::ENUM_TSN_CRYPTO_HASH f, uchar& buffw[])
|
2026-08-19 16:55:01 -05:00 | | | {
|
| | | //---
|
| | | const int hlen = TSN::CCryptoHashMeta::g_crytpo_hash_meta[f].outl; // tamañao de salida
|
| | |
|
| | | //---
|
| | | const int eml = ArraySize(msg);
|
2026-08-19 21:20:19 -05:00 | | | int i_db_pos = CRYPTOBYLEO_OAEP_SEED_I + hlen;
|
2026-08-19 16:55:01 -05:00 | | | // const int db_le = eml - i_db_pos; // tamaño total del db (sumando mas 1)
|
| | | const int l = k - hlen - 1; // tamaño de db [hash|padding|1|msg]
|
| | |
|
| | | //---
|
2026-08-19 21:20:19 -05:00 | | | const int buffw_l = (l << 1);
|
| | | ArrayResize(buffw, buffw_l); // de paso reservamos para el msg final que es menor isempre que k
|
| | |
|
| | | //---
|
| | | /*
|
| | | Usaremos buffw de esta forma
|
| | | [aqui los byutes donde pondremos el texto real...] [tranbajo mascaras]
|
| | | = tiene un tamaaño de l
|
| | | = trabajo de macascaras tambein l
|
| | | */
|
2026-08-19 16:55:01 -05:00 | | |
|
| | | //---
|
| | | // mgf1(masked_db, h_len, hash_func)
|
| | | // revierte: MGF1(out, i_db_pos, l, mask, 0, hlen, f);
|
2026-08-19 21:20:19 -05:00 | | | MGF1(msg, i_db_pos, l, buffw, l, hlen, f);
|
2026-08-19 16:55:01 -05:00 | | | // con esto ay tenemos la mascara uqe usamos con la seed
|
| | | // ahora limpiamos
|
| | | for(int i = 0; i < hlen; i++)
|
2026-08-19 21:20:19 -05:00 | | | {
|
| | | buffw[i + l] ^= msg[CRYPTOBYLEO_OAEP_SEED_I + i];
|
| | | }
|
2026-08-19 16:55:01 -05:00 | | |
|
2026-08-19 21:20:19 -05:00 | | | // listo ahora mismo ya tenemos en la posicion [l .. hlen-1]
|
| | | // la seed original esta en todo ese rango
|
2026-08-19 16:55:01 -05:00 | | |
|
| | | //--- Ahora con ese seed que tenemos revertamos el enmascarado de el DB
|
| | | // NOTA: sobreescirnimso seed ya no lo necesitamreos
|
| | | // revierte: MGF1(mask, 0, hlen, mask, 0, l, f)
|
2026-08-19 21:20:19 -05:00 | | | MGF1(buffw, l, hlen, buffw, l, l, f);
|
2026-08-19 16:55:01 -05:00 | | | // ahora si en bufffw tenemso la mascaraka que se uso luegoi con DB
|
2026-08-19 21:20:19 -05:00 | | | // l= tamiben seusa como indice de incio recodemos eso
|
| | | // 1.uso = le deicmos que lea buffw desde la posicon l
|
| | | // 2.uso = le deicmos que ponga el reusltaod en l y l ele,entos..
|
2026-08-19 16:55:01 -05:00 | | |
|
| | | //--- Ahora en la posicion de DB aplciamso un xor (a = b ^ a -> a ^= b)
|
2026-08-19 21:20:19 -05:00 | | | /*
|
| | | Ahora la idea aqui es temrinadr de aplicar DB
|
| | | lo que haremos sera [.... altos] en los altos esta todo L
|
| | | la idea sera incialemten convertir el label.. pero como no lo usaremos
|
| | | entonces estara fuera de eso
|
| | | */
|
| | |
|
2026-08-19 16:55:01 -05:00 | | | // ahora aplicamos un xor
|
| | | // mask_seed_mgf1 ^ Db_masked
|
| | | int pos = -1;
|
2026-08-19 21:20:19 -05:00 | | | int i = l; // ioniciosmos en el high
|
| | | // ahora db pos esta en el inico del hash
|
2026-08-19 16:55:01 -05:00 | | | // pase 1 (hash) unrolled 16
|
2026-08-19 21:20:19 -05:00 | | | /*for(; i < hlen; i++)
|
2026-08-19 16:55:01 -05:00 | | | {
|
2026-08-19 21:20:19 -05:00 | | |
|
2026-08-19 16:55:01 -05:00 | | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | |
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | |
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | |
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | | buffw[i] ^= msg[i_db_pos + (i++)];
|
| | | buffw[i] ^= msg[i_db_pos + (i)];
|
| | |
|
2026-08-19 21:20:19 -05:00 | | | }*/ // bucle esto solo si estaraismo querienod obtner el label
|
| | | i += hlen; // nos saltamos el hash entero del label
|
| | |
|
| | | // pase 2 , ahora mismo en el primer byte de PS padding
|
| | | // la idea es buscar el primer 1 que nos indicadra el incio del mensaje (luego de el)
|
| | | for(; i < buffw_l; i++)
|
2026-08-19 16:55:01 -05:00 | | | {
|
2026-08-19 21:20:19 -05:00 | | | if((buffw[i] ^ msg[i_db_pos + (i - l)]) == 0x1)
|
2026-08-23 20:09:15 -05:00 | | | {
|
| | | pos = i++;
|
2026-08-19 16:55:01 -05:00 | | | break;
|
2026-08-23 20:09:15 -05:00 | | | }
|
2026-08-19 16:55:01 -05:00 | | | }
|
| | | // ahora justo aqui esta el 1
|
2026-08-19 21:20:19 -05:00 | | | if(pos == -1)
|
| | | {
|
| | | return -1; // invalido no lo encontramos
|
| | | }
|
| | |
|
2026-08-19 16:55:01 -05:00 | | | // i apunta a luego del 1
|
| | | // ahora lo que queda es resto del mensaje sobreescribimos buffer
|
| | | // hasta ahora hemos leido ps+hlen+2 bytes
|
| | |
|
| | | //---- notas sobre un razonamiento qeu tuve
|
| | | // Mi idea era ver si podiamos quizas retuilziar el bufferw
|
| | | // para directament escribir el out ahi, parece uqe no:
|
| | | // ahora es seguro dado que:
|
| | | // ps = k - ml - hlen - hlen - 2
|
| | | // suma hlen en ambos lados
|
| | | // ps + hlen = k - ml - hlen - 2
|
| | | // suma dos en ambos lados
|
| | | // ps + hlen + 2 = k - ml - hlen
|
| | | // Ahora sabemos que lo que hemos leido es igual a k-ml-hlen
|
| | | // Tambien tenemos garantizado
|
| | | // ml <= k - (hlen << 1) - 2
|
| | | // por lo que ml siempre sera menor a k
|
| | | // otro dato qeu tenemos es que:
|
| | | // ml >= 2hlen + 2
|
| | | // Esto solo si ml no se acerca al limite de su valor
|
| | | // dado qeu si no:
|
| | | // k - ml < ml puede psar eso lo cual
|
| | | // k < 2ml lo cuial no tiene sneintdo si k si es mayor a ml
|
| | | // por ejemplo con k=1024 y ml=958 al maximo posible
|
| | | // (958 viene de hlen = 32 entonces 1024-64-2 = 958)
|
| | | // en ese caso 1024-958=66 lo cual invalida
|
| | | // ml <= k - ml + 2
|
| | | // 958 <= 1024- 958+2
|
| | | // cosa que prueba que eso de ml sol ose da cuano ml esta mas lejos del "maximo"
|
| | | // tope como en nuestro codigo ml puede tomar el maximo eso quiere decir
|
| | | // que si ml >= 2hlen + 2 en un caso promedio quizas
|
| | | // ps + hlen + 2 = k - ml - hlen
|
| | | // como k > ml entonces daria poco residuo que se lo cmoemra hlen quedando todo eso
|
| | | // en algo de como minimo hlen+2 osea que el valor minimo que tenemos es de hlen+2
|
| | | // ps peude llega a ser 0 pero no menor que este entonces
|
| | | // pro lo visto si en el caso "promedio" ps quizas no llegue a ser tran grande
|
| | | // mas bien donde ml sea grande un numero de bytes "ps + hlen + 2 "
|
| | | // no nos alcanzaria... para meteer el mensage complejo
|
| | | // Como un caso "borde" nos fallo .. entonces queda descartado
|
| | | // no creo qeu tenga caso seguir viendo mas casos donde si cumple etc
|
| | | // por qeu creo que meteiramos mucho overhad si vamos clasificando y aplicando
|
| | | // asi qeu no...
|
| | | // volvere a poner buffw como local ya no como out..
|
| | |
|
2026-08-19 21:20:19 -05:00 | | | //-- Ahora si escribimos el out (ahor amismo en pos+1)
|
2026-08-19 16:55:01 -05:00 | | | const int li = i;
|
2026-08-19 21:20:19 -05:00 | | | const int ml = (buffw_l - i);
|
| | | // Ahora la idea sera posiciones msg justo en 1
|
| | | for(; i < buffw_l; i++)
|
| | | buffw[i - li] = buffw[i] ^ msg[i_db_pos + (i - l)];
|
2026-08-19 16:55:01 -05:00 | | |
|
2026-08-19 17:43:41 -05:00 | | |
|
2026-08-19 16:55:01 -05:00 | | | //--- retorna el tamaño del mensaje
|
| | | return ml;
|
2026-08-19 13:03:20 -05:00 | | | }
|
2026-08-19 16:55:01 -05:00 | | |
|
| | | //---
|
| | | #undef MGF1_PS
|
2026-08-19 13:03:20 -05:00 | | | }
|
| | | #endif // CRYPTOBYLEO_SRC_PADDING_OAEP_MAIN_MQH
|
| | | //+------------------------------------------------------------------+
|