forked from nique_372/CryptoByLeo
369 lines
13 KiB
MQL5
369 lines
13 KiB
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_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
|
|
//+------------------------------------------------------------------+
|