forked from nique_372/CryptoByLeo
162 lines
5.1 KiB
MQL5
162 lines
5.1 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Gen.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_RSA_KEYS_GEN_MQH
|
|
#define CRYPTOBYLEO_SRC_RSA_KEYS_GEN_MQH
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
#include "H.mqh"
|
|
#include "..\\..\\Imports\\Main.mqh"
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
namespace TSN
|
|
{
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
class CRsa
|
|
{
|
|
public:
|
|
CRsa(void) {}
|
|
~CRsa(void) {}
|
|
|
|
//---
|
|
template <typename TRandomGen>
|
|
static bool GenerateKeyData(int public_exponent, int key_size_bits,
|
|
int rounds_test_primo, int t_attemps, CRsaPublicKey& pub, CRsaPrivateKey& priv);
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TRandomGen>
|
|
static bool CRsa::GenerateKeyData(int public_exponent, int key_size_bits,
|
|
int rounds_test_primo, int t_attemps, CRsaPublicKey& pub, CRsaPrivateKey& priv)
|
|
{
|
|
//
|
|
//---
|
|
/* En esta funcion creamos
|
|
- p (primo grande)
|
|
- q (primero grande)
|
|
- n (producto de p y q)
|
|
- d (se deriva de lo publico)
|
|
*/
|
|
|
|
//---
|
|
/*
|
|
1. Fijar e = 65537 (dado, no se "elige" en tiempo de generación)
|
|
2. Generar candidato p:
|
|
a. Sacar un número aleatorio impar de 1024 bits
|
|
b. Testear primalidad (Miller-Rabin / Fermat)
|
|
c. Si no es primo → volver a (a)
|
|
d. Si es primo → verificar gcd(e, p-1) == 1
|
|
e. Si NO es coprimo con e → descartar p entero, volver a (a)
|
|
3. Repetir todo el paso 2 para generar q (con la condición extra p ≠ q)
|
|
4. n = p × q
|
|
5. φ(n) = (p-1)(q-1)
|
|
6. d = e⁻¹ mod φ(n) (Euclides extendido) | e * d = 1 mod φ(n) (ed es como ax en formula)
|
|
*/
|
|
|
|
//----
|
|
const int keyss_limbs = BIGNUMERBYLEO_BITS_TO_LIMBS(key_size_bits);
|
|
BigUInteger p(TSN::BigUInteger::EMPTY_INT_ARR, keyss_limbs);
|
|
BigUInteger q(TSN::BigUInteger::EMPTY_INT_ARR, keyss_limbs);
|
|
|
|
//--- P
|
|
while(true)
|
|
{
|
|
if(--t_attemps < 0)
|
|
return false;
|
|
|
|
|
|
// La idea aqui es primeramente generar un nuermo alaeatorio
|
|
// generamos
|
|
p.FillRandom<TRandomGen>();
|
|
// BCryptGenRandom(0, p.m_v, sizeof(ulong) * keyss_limbs, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
|
|
p.m_v[0] |= 1; // foramozas a que sea impar
|
|
// Ahora formzaos que el alto este activado
|
|
// La idea es que neceistos garnaizasr qeu este numero sea de key_size_bits
|
|
// Por que peude que en la generacion los altos esten apgados asi qeu teoramte no seria un numero de esos bit
|
|
// asi que lo forzamos activand el mas alto
|
|
p.m_v[keyss_limbs - 1] |= (1ULL << 63);
|
|
|
|
//--- ahora le pasamos
|
|
if(!p.IsProbablePrime(rounds_test_primo))
|
|
continue;
|
|
|
|
// restamos 1
|
|
p -= 1;
|
|
|
|
// Buscamos que sean coprimos (con el public exponent)
|
|
if(p.Gdc(public_exponent) == 1)
|
|
break;
|
|
}
|
|
|
|
//---
|
|
p += 1;
|
|
|
|
//--- q
|
|
while(true)
|
|
{
|
|
if(--t_attemps < 0)
|
|
return false;
|
|
q.FillRandom<TRandomGen>();
|
|
q.m_v[0] |= 1; // foramozas a que sea impar
|
|
q.m_v[keyss_limbs - 1] |= (1ULL << 63);
|
|
//---
|
|
if(p == q)
|
|
continue; // deben de ser diferentes
|
|
//--- ahora le pasamos
|
|
if(!q.IsProbablePrime(rounds_test_primo))
|
|
continue;
|
|
q -= 1; // restamos 1
|
|
// Buscamos que sean coprimos (con el public exponent)
|
|
if(q.Gdc(public_exponent) == 1)
|
|
break;
|
|
}
|
|
|
|
//---
|
|
BigUInteger phi_n = (p - 1) * q; // q ya es q-1
|
|
// Ahora d = e⁻¹ mod φ(n)
|
|
// public_exponent * x = 1 (mod phi(n))
|
|
// primero converitmos a e a un big integer.. usando contructo exacto
|
|
const BigUInteger bige(TSN::BigUInteger::EMPTY_NUMBER_EXACT, public_exponent);
|
|
// ahora si calculamos..
|
|
BigUInteger d = bige.GdcExtendedRetX(phi_n);
|
|
|
|
//--- Calculo de crt
|
|
// (dq)
|
|
BigUInteger dq = d % q;
|
|
// (dp)
|
|
BigUInteger dp = d % (p - 1);
|
|
// qinv
|
|
BigUInteger qinv = q.GdcExtendedRetX(p);
|
|
|
|
//--- N final
|
|
q += 1;
|
|
BigUInteger n = p * q;
|
|
BigUInteger ncopy = n;
|
|
|
|
//---
|
|
pub = CRsaPublicKey(n, public_exponent);
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
}
|
|
#endif // CRYPTOBYLEO_SRC_RSA_KEYS_GEN_MQH
|
|
//+------------------------------------------------------------------+
|