CryptoByLeo/Src/Padding/OAEP/Main.mqh

369 lines
13 KiB
MQL5
Raw Permalink Normal View History

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
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
// pse ale
#include "..\\..\\PseAle\\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) {}
//---
// msg=mensaje
2026-08-20 17:22:07 -05:00
// 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
2026-08-20 19:39:46 -05:00
static int Encode(const uchar& msg[], int kexp, 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: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...
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-20 19:39:46 -05:00
static int COAEP::Encode(const uchar& msg[], int kexp, 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);
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
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);
//---
// 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
2026-08-23 20:09:15 -05:00
//ArrayCopy(out,msg,i,0,ml);
2026-08-20 17:22:07 -05:00
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;
}
2026-08-19 16:55:01 -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);
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]
//---
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);
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++)
{
buffw[i + l] ^= msg[CRYPTOBYLEO_OAEP_SEED_I + i];
}
2026-08-19 16:55:01 -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)
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
// 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)
/*
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;
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
/*for(; i < hlen; i++)
2026-08-19 16:55:01 -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)];
}*/ // 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
{
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
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..
//-- Ahora si escribimos el out (ahor amismo en pos+1)
2026-08-19 16:55:01 -05:00
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)];
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
//+------------------------------------------------------------------+