我正在尝试实施RSA加密方案,但是虽然我的加密值似乎是正确的,但解密后的值并非如此。基于我得到的p,q等的值,似乎计算部分(IE,硬部分)很好,并且消息似乎正在加密(以防万一我将加密部分包括为虽然)。请注意,我应该在没有任何库的情况下执行此操作(我已经使用GMP编写了它),这就是为什么我使用不切实际的小数字。
int main()
{
...
vector<uint64_t> encrypted = doEncrypt(e, n);
doDecrypt(d, n, encrypted);
}
vector<uint64_t> doEncrypt(unsigned int e, unsigned int n)
{
string message;
vector<uint64_t> encrypted;
cout << "Public key is <" << e << ", " << n << ">.\nPlease enter a message to encrypt: ";
getline(cin, message);
for (unsigned int i = 0; i < message.length(); i++)
encrypted.push_back(encrypt(message[i], e, n));
return encrypted;
}
uint64_t encrypt(char message, unsigned e, unsigned int n)
{
int toencrypt = (int)message;
cout << toencrypt << ' ';
uint64_t result = pow64(toencrypt, e);
return result%n;
}
void doDecrypt(unsigned int d, unsigned int n, vector<uint64_t> encrypted)
{
cout << "Encrypted message is: ";
for (unsigned int i = 0; i < encrypted.size(); i++)
cout << encrypted[i] << ' ';
cout << "\nDecrypted message is: ";
char out;
for (unsigned int i = 0; i < encrypted.size(); i++){
decrypt(out, encrypted[i], d, n);
cout << out << ' ';//This is only for diagnostics, I will
//take out the printing of the decrypted
//number and space later
}
cout << endl;
}
void decrypt(char& decrypted, uint64_t message, unsigned int d, unsigned int n)
{
uint64_t decrypt = (pow64(message, d)%n);
cout << decrypt;
decrypted = (char)decrypt;
}
uint64_t pow64(uint64_t base, unsigned int ex)
{
uint64_t back = 1;
for (unsigned int i = 0; i < ex; i++)
back = back * base;
return back;
}
示例输出:
p = 23
q = 23
n = 529
phi_n = 484
e = 9
d = 269
公钥是&lt; 9,529&gt;
请输入要加密的消息:狗
100 111 103加密信息是:515 33 295
解密的消息是:523
417±364l
答案 0 :(得分:1)
你的问题是p == q,所以n是一个完美的正方形而不是两个素数的乘积,这意味着你对phi(n)的计算是错误的。 phi(p ^ 2)== p *(p-1)其中p是素数。因此,如果您将代码更改为使用phi(n)== 506和d == 225,它应该可以正常工作。
或者选择了不同的 p和q。
使用小素数测试代码时要担心的另一个陷阱 - 如果您的明文值是p或q的倍数,加密/解密将失败。当对p和q使用实数值(256位或更多)时,这种情况极不可能发生,但是这种小值可能偶然发生。达到此问题的概率与对手随机猜测您的私人因素的概率相同。
可能发生的第三个陷阱是您选择的公共指数e
必须与phi(n)没有任何共同的因素,否则将不存在有效的d
解码指数。同样,这不是“真正的”RSA密钥的问题,因为(p-1)/ 2和(q-1)/ 2应该是素数,所以只要e
是奇数,就有可能不是拥有有效的解密密钥的程度非常小。
修改强>
你的代码有问题,你的pow64例程很容易溢出(515 ^ 269超过2000位)。尝试使用:
uint64_t pow64(uint32_t base, uint32_t ex, uint32_t n)
{
uint64_t back = 1;
for (unsigned int i = 0; i < ex; i++)
back = (back * base) % n;
return back;
}
请注意,我将输入值限制为uint32_t,因此中间乘法永远不会溢出64位。这也是非常无效的 - 你最好平均基数并一次一个地指数:
uint64_t pow64(uint32_t base, uint32_t ex, uint32_t n)
{
uint64_t back = 1;
for (uint64_t i = 1; i <= ex; i <<= 1) {
if (i & ex)
back = (back * base) % n;
base = ((uint64_t)base * base) % n; }
return back;
}