pow函数和long int引起的问题

时间:2013-09-29 01:14:28

标签: c gcc encryption int pow

我正在尝试实施RSA加密方案。它是这样的:

encrypted data = ((message)^e) % ndecrypted data = ((encrypted data)^d) % n

我试图在c中实现这一点。这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(){

    long int num = 3255859; 
    long int encrypt =(int)pow((double) num,3) % 33;
    printf("%ld\n",encrypt);

    return 0;

}

我使用gcc -Werror -g -o encrypt encrypt.c -lm

编译了这个

这是我得到的输出= -2,这显然是错误的。当我尝试使用较小的数字代码时,我得到了正确的结果。例如:

当我设置num = 2时,我得到了正确的结果8

我知道我要么输入错误,要么我在某个地方跑出界限。我确实需要使用此代码来加密像上面代码中那样的大数字。

请指出我哪里出错了。

由于

编辑:

好的,根据@Micael Oliver的建议,这里是修改后的代码:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(){

    unsigned long long  num = 3255859; 

    long long encrypt =(long long)pow((double) num,3) % 33;

    printf("%llu\n",encrypt);

    long long decrypt =(long long)pow((double) encrypt,7) % 33;

    printf("%llu\n",decrypt);

    return 0;

}

这是此代码的输出:

Notra:Desktop Sukhvir$ gcc -Werror -g -o encrypt encrypt.c -lm
Notra:Desktop Sukhvir$ ./encrypt
18446744073709551608
18446744073709551614

这显然是错误的,因为第二个出口应该是3255859

3 个答案:

答案 0 :(得分:2)

您的代码中有一些未签名和已签名的数字 - 您应该尽可能避免这种情况。此外,您尝试在已签名的长片上使用%llu - 在这种情况下您应该使用%lld

但是这里有一个更微妙的问题。在这一行:

long long encrypt =(long long)pow((double) num,3) % 33;

pow会返回double,但不能保证您所需的所有精确度。当你转向long long时,你最终会失去一些数字。不幸的是,C不能为计算指数提供一个很好的选择,所以你需要自己实现一些东西或使用一个库(其他一些答案已经提出了一些)。

如果你想自己实现一个,可以在Wikipedia上找到一篇关于通过平方快速求幂的好文章:Exponentiation by squaring

它们提供了一些伪代码,这些伪代码在C语言中应该很明显。

但最后,一般来说,您的代码会受到long long大小或您选择的任何类型的限制。最终对于大数字,您应该使用其他库,或找到更好的算法。在这种情况下,您正在计算功率然后采用模数 - 这正是模块化指数算法无需处理这些库即可实现的功能。你可以在这里找到一篇维基百科文章:Modular Exponentiation

答案 1 :(得分:0)

一个建议是使用另一种数据类型,例如long long:

3255859^3 ==  34514116960466804779
ULLONG_MAX == 18446744073709551615  // this is the minimum guaranteed

因此,unsigned long long可能无效。通常,更改数据类型有限制。 您可以考虑的另一种更强大的方法是使用GMP - 免费。 gmp manual -

- 你也可以在这个网站上下载gmp。

代码段:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gmp.h>

int main()
{
    mpz_t rop, base, exp, mod;
    mpz_init2(rop,128); 
    mpz_init2(base,128); 
    mpz_init2(exp,128); 
    mpz_init2(mod,128);
    mpz_set_ui(base, 3255859);
    mpz_set_ui(exp, 3);
    mpz_set_ui(mod, 33);
    mpz_powm_sec (rop, base, exp, mod);
    gmp_printf ("result %Zd\n", rop);    
    return 0;
}

答案 2 :(得分:0)

只要你的数字大小只是你工作类型的一半,你就可以这样做:

(((num * num) % 33) * num) % 33

通常,对于任何可用于加密目的的内容,您需要更大的值和计算框架才能使用1024+位数。为此,您可以使用现有代码(我建议libtommath使用libtomcrypt,绝对 GMP)或自己编写。