RSA 实现未正确解密
RSA-Implementation isn't decrypting correctly
我喜欢学习,今天我决定最终自己实现 RSA。
基本上,据我所知,我的代码应该有效,而且在一定程度上确实有效。
然而,即使(根据 Internet 学习资源)计算并正确使用了正确的密钥,我仍然得到奇怪的输出。我查了也没找到问题出在哪里,因为手工计算的结果是一样的...
是的,这是我的 cryptography.cpp
-文件:
#include "cryptography.h"
bool prime(const unsigned long long n) {
//max of sqrt(n)
unsigned long long m = 0.5 * n;
for(unsigned int i = 2; i <= m; i++) //check every possible divisor
if(n % i == 0) //wheter it goes in to n perfectly
return false; //n is not prime if such divisor is found
//if no divisor found
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;
}
//subtract smaller from bigger, keeping gcd
while(q != 0) {
unsigned long long r = p % q;
p = q;
q = r;
}
//gdc == 1
return p == 1;
}
/**
* Finds d for:
* 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 & q have to be primes
if(!(prime(p) && prime(q)) || p == q)
return false;
//n defined as p * q
n = p * q;
unsigned long long m = (p - 1) * (q - 1);
//find e where e and (p - 1)(q - 1) are coprime
e = 7;
while(!coprime(m, e))
e++;
//1 = (d * e) % (p - 1)(q - 1)
d = modularInverse(e, m);
//everything worked
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;
}
只是为了确定它在 main.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;
}
正如@President James K. Polk 正确地猜到问题是无声的整数溢出。对于坚持这一点的任何人:太高的加密数据整数很容易导致小素数问题。
我使用 this 来替换 encrypt
& decrypt
方法中的 pow(a, b) % c
调用 modularPow(a, b, c)
:
unsigned long long modularPow(const unsigned long long base, const unsigned long long exponent, const unsigned long long modulus) {
unsigned long long result = 1;
for(unsigned long long i = 0; i < exponent; i++) {
result *= base;
result %= modulus;
}
return result;
}
我喜欢学习,今天我决定最终自己实现 RSA。 基本上,据我所知,我的代码应该有效,而且在一定程度上确实有效。
然而,即使(根据 Internet 学习资源)计算并正确使用了正确的密钥,我仍然得到奇怪的输出。我查了也没找到问题出在哪里,因为手工计算的结果是一样的...
是的,这是我的 cryptography.cpp
-文件:
#include "cryptography.h"
bool prime(const unsigned long long n) {
//max of sqrt(n)
unsigned long long m = 0.5 * n;
for(unsigned int i = 2; i <= m; i++) //check every possible divisor
if(n % i == 0) //wheter it goes in to n perfectly
return false; //n is not prime if such divisor is found
//if no divisor found
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;
}
//subtract smaller from bigger, keeping gcd
while(q != 0) {
unsigned long long r = p % q;
p = q;
q = r;
}
//gdc == 1
return p == 1;
}
/**
* Finds d for:
* 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 & q have to be primes
if(!(prime(p) && prime(q)) || p == q)
return false;
//n defined as p * q
n = p * q;
unsigned long long m = (p - 1) * (q - 1);
//find e where e and (p - 1)(q - 1) are coprime
e = 7;
while(!coprime(m, e))
e++;
//1 = (d * e) % (p - 1)(q - 1)
d = modularInverse(e, m);
//everything worked
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;
}
只是为了确定它在 main.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;
}
正如@President James K. Polk 正确地猜到问题是无声的整数溢出。对于坚持这一点的任何人:太高的加密数据整数很容易导致小素数问题。
我使用 this 来替换 encrypt
& decrypt
方法中的 pow(a, b) % c
调用 modularPow(a, b, c)
:
unsigned long long modularPow(const unsigned long long base, const unsigned long long exponent, const unsigned long long modulus) {
unsigned long long result = 1;
for(unsigned long long i = 0; i < exponent; i++) {
result *= base;
result %= modulus;
}
return result;
}