La implementación de RSA no está descifrando correctamente.
Me gusta aprender y hoy decidí finalmente implementar RSA por mi cuenta.
Básicamente, por lo que puedo ver, mi código debería funcionar y de hecho lo hace hasta cierto punto.
Sin embargo, incluso si (según las fuentes de aprendizaje de Internet) se calculan correctamente las claves correctas y se utilizan correctamente, obtengo resultados extraños. Comprobé pero no pude encontrar dónde está el problema, porque el cálculo a mano produce los mismos resultados…
Entonces, aquí está mi archivo cryptography.cpp
:
#include "cryptography.h"
bool prime(const unsigned long long n) {
//máximo de sqrt(n)
unsigned long long m = 0.5 * n;
for(unsigned int i = 2; i <= m; i++) //comprobar cada posible divisor
if(n % i == 0) //si es que se divide perfectamente
return false; //n no es primo si se encuentra dicho divisor
//si no se encuentra ningún divisor
return true;
}
bool coprime(unsigned long long p, unsigned long long q) {
//p >= q
if(q > p) {
long long t = p;
p = q;
q = t;
}
//restar del más grande el más pequeño, manteniendo el GCD
while(q != 0) {
unsigned long long r = p % q;
p = q;
q = r;
}
//gcd == 1
return p == 1;
}
/**
* Encuentra d para:
* 1 = (d * e) % m
*/
unsigned long long modularInverse(const unsigned long long e, const unsigned long long m) {
unsigned long long d = 1;
while(d * e % m != 1)
d++;
return d;
}
unsigned long long pow(const unsigned long long base, const unsigned long long exponent) {
unsigned long long result = 1;
for(long long i = 0; i < exponent; i++)
result *= base;
return result;
}
bool RSA::generateKeys(const unsigned long long p, const unsigned long long q, unsigned long long& n, unsigned long long& d, unsigned long long& e) {
//p y q tienen que ser primos
if(!(prime(p) && prime(q)) || p == q)
return false;
//n definido como p * q
n = p * q;
unsigned long long m = (p - 1) * (q - 1);
//encontrar e donde e y (p - 1)(q - 1) son coprimos
e = 7;
while(!coprime(m, e))
e++;
//1 = (d * e) % (p - 1)(q - 1)
d = modularInverse(e, m);
//todo funcionó
return true;
}
unsigned long long RSA::encrypt(const unsigned long long message, const unsigned long long e, const unsigned long long n) {
return pow(message, e) % n;
}
unsigned long long RSA::decrypt(const unsigned long long encryptedMessage, const unsigned long long d, const unsigned long long n) {
return pow(encryptedMessage, d) % n;
}
Para estar seguro, aquí está cómo se usa en main.cpp
:
“`cpp
#include <iostream>
#include "cryptography.h"
int main(int argc, char const *argv[]) {
unsigned long long n, d, e;
if(!RSA::generateKeys(7, 13, n, d, e))
return -1;
std::cout << "n: " << n << std::endl;
std::cout << "d: " << d << std::endl;
std::cout << "e: " << e << std::endl;
std::cout << std::endl;
unsigned long long message;
std::cin >> message;
std::cout << "Message: " << message << std::endl;
unsigned long long encryptedMessage = RSA::encrypt(message, e, n);
std::cout << "Encrypted Message: " << encryptedMessage << std::endl;
unsigned long long decryptedMessage = RSA::decrypt(encryptedMessage, d, n);
std::cout << "Decrypted Message: " << decryptedMessage << std::endl;
}
“`
davy.ai
El código parece ser una implementación básica del algoritmo del criptosistema RSA en C++. El archivo
cryptography.cpp
contiene funciones para generar claves públicas y privadas RSA y cifrar y descifrar mensajes usando estas claves. La funcióngenerateKeys()
genera las claves requeridas dados dos números primosp
yq
, y las devuelve por referencia enn
,d
ye
. Las funcionesencrypt()
ydecrypt()
toman un mensaje, una clave y un módulo, y cifran y descifran respectivamente el mensaje usando la exponenciación modular.La función
prime()
es una implementación básica de una prueba de número primo, sin embargo, solo verifica números primos hasta la raíz cuadrada máxima den
, lo que puede no ser suficiente para números grandes. La funcióncoprime()
calcula el máximo común divisor entre dos números y devuelvetrue
si su GCD es 1, es decir, si son coprimos. La funciónmodularInverse()
devuelve un valord
tal que(d * e) % m == 1
. La funciónpow()
es una implementación básica de la exponenciación modular, que tiene una complejidad temporal de O (log n).No está claro del código proporcionado qué salidas está recibiendo el usuario que se consideran raras o qué entradas está proporcionando el usuario al programa. Se puede requerir una depuración adicional para identificar el problema.