RSA解密失败

时间:2013-11-24 01:18:27

标签: c++ rsa

我正在尝试实施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

1 个答案:

答案 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;
}