尝试使用 C++ 上的 RSA 和 GMP 从文件中解密会产生不可预测的结果
Trying to decipher from a file using RSA on C++ with GMP yields unpredictable results
我正在尝试使用 GMP 库实现 RSA 算法。当我试图破译从文件中读取的加密值时,最终结果是一个比原始密文大几倍的值。
这是我的代码中有问题的部分:
void cipher_file(mpz_t E, mpz_t N, string Filename){
// getting the file contents
// and converting the letters to their ASCII values
mpz_set_ui(CipheredLetter, TextASCII[j][k]);
mpz_powm(CipheredLetter,CipheredLetter,E,N);
// converting the resulting number to a string so that it can
// be written on a file
string AuxString(mpz_get_str(NULL,10,CipheredLetter));
CipheredLine.push_back(AuxString);
}
void decipher_file(mpz_t D, mpz_t N, string Filename){
// getting the file contents
while(getline(CipheredFile,ReadLine)){
stringstream Aux(ReadLine);
do{
Aux >> AuxString;
if(AuxString== "x") // end of line delimeter
break;
mpz_set_str(DecipheredLetter,AuxString.c_str(),10);
mpz_powm(DecipheredLetter,DecipheredLetter,D,N);
}while(Aux);
}
}
加密函数逐个字母地工作,因此像 abc
这样的输入将作为 <ciphered a> <ciphered b> <ciphered b>
存储在加密文件中,即 a
、[=16 的结果密码=] 和 c
以空格分隔。
E
和 N
是 public 密钥的两个部分,其中 N 是模,E 是 (p-1)(q-1) 的互质,D
和 N
是私钥的两部分。密钥生成按预期工作(生成素数 P 和 Q 我正在使用 Fermat 的素数测试,为了获得 D 我正在使用扩展欧几里得算法,GMP 的基本函数确认我的结果是正确的)。
问题发生在 decipher_file
函数中,在 mpz_powm
行。该行的结果应该是原始文件中字母的 ASCII 码,然而,结果不是某个巨大且看似随机的数字。
这是一个发生的例子(请注意,这些只是 64 位整数,但是这意味着能够更进一步,我只是用 64 位整数进行测试):
E = 1792236355377141527966304989230907
N = 4648032597737790824232209858880409
D = 2807452368750797442560595530474579
ASCII Code of Read Letter: 54
Ciphered Value: 835328461955738677042072153797186
Read from Ciphered File: 835328461955738677042072153797186
"Deciphered" Value: 211928638691469780709516904424482
我发现 this 使用 GMP 实现的简单(有点旧)RSA 实现与我的意图几乎相同,并且以与我几乎相同的方式实现,但是,他的作品好吧,出于我无法理解的原因。
感谢您阅读这么多。感谢任何帮助。
您的 N
没有两个不同的质因数:
4648032597737790824232209858880409 = 68176481265446597^2
这意味着您选择了p = q
。除了明显的安全问题(n
可以通过取平方根轻松分解)之外,这还会在计算 N
(reference) 的 Carmichael totient 函数时引起问题。具体来说,lambda(pq) = (p-1)*(q-1)
仅适用于 p != q
。对于 p = q
,您必须改用 lambda(p^2) = p(p-1)
。
我正在尝试使用 GMP 库实现 RSA 算法。当我试图破译从文件中读取的加密值时,最终结果是一个比原始密文大几倍的值。 这是我的代码中有问题的部分:
void cipher_file(mpz_t E, mpz_t N, string Filename){
// getting the file contents
// and converting the letters to their ASCII values
mpz_set_ui(CipheredLetter, TextASCII[j][k]);
mpz_powm(CipheredLetter,CipheredLetter,E,N);
// converting the resulting number to a string so that it can
// be written on a file
string AuxString(mpz_get_str(NULL,10,CipheredLetter));
CipheredLine.push_back(AuxString);
}
void decipher_file(mpz_t D, mpz_t N, string Filename){
// getting the file contents
while(getline(CipheredFile,ReadLine)){
stringstream Aux(ReadLine);
do{
Aux >> AuxString;
if(AuxString== "x") // end of line delimeter
break;
mpz_set_str(DecipheredLetter,AuxString.c_str(),10);
mpz_powm(DecipheredLetter,DecipheredLetter,D,N);
}while(Aux);
}
}
加密函数逐个字母地工作,因此像 abc
这样的输入将作为 <ciphered a> <ciphered b> <ciphered b>
存储在加密文件中,即 a
、[=16 的结果密码=] 和 c
以空格分隔。
E
和 N
是 public 密钥的两个部分,其中 N 是模,E 是 (p-1)(q-1) 的互质,D
和 N
是私钥的两部分。密钥生成按预期工作(生成素数 P 和 Q 我正在使用 Fermat 的素数测试,为了获得 D 我正在使用扩展欧几里得算法,GMP 的基本函数确认我的结果是正确的)。
问题发生在 decipher_file
函数中,在 mpz_powm
行。该行的结果应该是原始文件中字母的 ASCII 码,然而,结果不是某个巨大且看似随机的数字。
这是一个发生的例子(请注意,这些只是 64 位整数,但是这意味着能够更进一步,我只是用 64 位整数进行测试):
E = 1792236355377141527966304989230907
N = 4648032597737790824232209858880409
D = 2807452368750797442560595530474579
ASCII Code of Read Letter: 54
Ciphered Value: 835328461955738677042072153797186
Read from Ciphered File: 835328461955738677042072153797186
"Deciphered" Value: 211928638691469780709516904424482
我发现 this 使用 GMP 实现的简单(有点旧)RSA 实现与我的意图几乎相同,并且以与我几乎相同的方式实现,但是,他的作品好吧,出于我无法理解的原因。
感谢您阅读这么多。感谢任何帮助。
您的 N
没有两个不同的质因数:
4648032597737790824232209858880409 = 68176481265446597^2
这意味着您选择了p = q
。除了明显的安全问题(n
可以通过取平方根轻松分解)之外,这还会在计算 N
(reference) 的 Carmichael totient 函数时引起问题。具体来说,lambda(pq) = (p-1)*(q-1)
仅适用于 p != q
。对于 p = q
,您必须改用 lambda(p^2) = p(p-1)
。