//+------------------------------------------------------------------+ //| 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 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ // pse ale #include "..\\..\\PseAle\\Main.mqh" // mgf1 #include "..\\..\\MGF1\\Main.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #define CRYPTOBYLEO_OAEP_SEED_I (1) //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ namespace TSN { //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class COAEP { public: COAEP(void) {} ~COAEP(void) {} //--- // msg=mensaje // kexp=exponenete RSA // random=array random tamaño hlen (consulta el tamaño del hash meta y generalo) // f=funcion // out=buffer de fuera // retorna: // tamaño del array de out, -1 en caso de err static int Encode(const uchar& msg[], int kexp, const uchar& random[], TSN::CCryptoHashMeta::ENUM_TSN_CRYPTO_HASH f, uchar& out[]); //--- // 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... static int Decode(const uchar& msg[], int k, CCryptoHashMeta::ENUM_TSN_CRYPTO_HASH f, uchar& buffw[]); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ static int COAEP::Encode(const uchar& msg[], int kexp, const uchar& random[], 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); if(ml > kexp - (hlen << 1) - 2) return -1; //--- deriviacion del taamño final // nota que el tamaño de out hasta este moneto es de = hlen + 1 + (ps) + ml = (DB) // = hlen + 1 + (kexp - ml - (hlen*2) - 2) + ml // = hlen + 1 + kexp - ml - (hlen*2) - 2 + ml --- quitaremos el ml se cancelan // = hlen + 1 + kexp - (hlen*2) - 2 -- + 1 // = hlen + kexp - (hlen*2) - 1 // = kexp - (hlen + hlen) - 1 + hlen // = kexp - hlen - hlen - 1 + hlen ---- se sale 1 // = kexp - hlen - 1 // asiq ue eda eso.. .como estimacion final el out hasta qui tendra un tmaño de kexp // y ese es el mismo numro de bytes aleatorio que generaremos const int l = (kexp - hlen - 1); // tamaño out (seed y bloque) //--- 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 for(int k = 0; k < hlen; k++) out[k + 1] = random[k]; //--- 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 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++]; // Print(i); //--- // kexp=expoentne // ml=msg len // hlen=out hash len // const int ps = kexp - ml - (hlen << 1) - 2; // ps // le agregamos in place ps bytes 0 #define MGF1_PS (kexp - ml - (hlen << 1) - 2) 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 //ArrayCopy(out,msg,i,0,ml); for(int k = 0; k < ml; k++) out[i + k] = msg[k]; 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; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ static int COAEP::Decode(const uchar &msg[], int k, CCryptoHashMeta::ENUM_TSN_CRYPTO_HASH f, uchar& buffw[]) { //--- const int hlen = TSN::CCryptoHashMeta::g_crytpo_hash_meta[f].outl; // tamañao de salida //--- const int eml = ArraySize(msg); int i_db_pos = CRYPTOBYLEO_OAEP_SEED_I + hlen; // 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] //--- 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 */ //--- // mgf1(masked_db, h_len, hash_func) // revierte: MGF1(out, i_db_pos, l, mask, 0, hlen, f); MGF1(msg, i_db_pos, l, buffw, l, hlen, f); // con esto ay tenemos la mascara uqe usamos con la seed // ahora limpiamos for(int i = 0; i < hlen; i++) { buffw[i + l] ^= msg[CRYPTOBYLEO_OAEP_SEED_I + i]; } // listo ahora mismo ya tenemos en la posicion [l .. hlen-1] // la seed original esta en todo ese rango //--- 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) MGF1(buffw, l, hlen, buffw, l, l, f); // ahora si en bufffw tenemso la mascaraka que se uso luegoi con DB // 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.. //--- Ahora en la posicion de DB aplciamso un xor (a = b ^ a -> a ^= b) /* 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 */ // ahora aplicamos un xor // mask_seed_mgf1 ^ Db_masked int pos = -1; int i = l; // ioniciosmos en el high // ahora db pos esta en el inico del hash // pase 1 (hash) unrolled 16 /*for(; i < hlen; 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++)]; buffw[i] ^= msg[i_db_pos + (i)]; }*/ // 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++) { if((buffw[i] ^ msg[i_db_pos + (i - l)]) == 0x1) { pos = i++; break; } } // ahora justo aqui esta el 1 if(pos == -1) { return -1; // invalido no lo encontramos } // 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.. //-- Ahora si escribimos el out (ahor amismo en pos+1) const int li = i; 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)]; //--- retorna el tamaño del mensaje return ml; } //--- #undef MGF1_PS } #endif // CRYPTOBYLEO_SRC_PADDING_OAEP_MAIN_MQH //+------------------------------------------------------------------+