当前位置:   article > 正文

C/C++使用GMP库实现Paillier加密和解密,中国剩余定理(CRT)加速解密过程对比。<三>_使用中国剩余定理优化paillier

使用中国剩余定理优化paillier

1、如何实现C语言使用GMP库实现Paillier加密,详看本篇文章,链接如下:

C/C++语言使用GMP大数运算库实现Paillier算法_Paidx.的博客-CSDN博客_c++ gmp

2、中国剩余定理在Paillier中的作用。

        想要使用中国剩余定理,则需要提前知道p,q的值,如果不知道p,q的值则不能够使用中国剩余定理进行加速解密的过程。大数的模幂运算在计算机中是耗时的,如果使用硬算的方法则会消耗大量时间,如果使用中国剩余定理进行优化则会提高解密效率。

        按照Paillier算法的要求进行加密,得到密文c,需要进行下面的数学原理进行划分:

 上述中的CRT(m_p,m_q) mod pq如何进行计算呢,请看下述讲解。

3、计算CRT(m_p,m_q) mod pq

 对于第二步中计算的m_q,m_p直接带入第三步最后一步的推到即可,即带入如下方程:

 4、可能会遇到的计算问题。

        (1)求乘法逆元

                调用GMP库中的gmp_invert()函数能够直接求出来。

                想要理解乘法逆元的概念,要先想想倒数的概念,3 * 3^{-1}=1。举个例子:

                求3 * 2^{-1} mod 5 的结果???

                此时显然是不能直接求得,需要先2^{-1}mod 5的乘法逆元,设乘法逆元为x,通过倒数的理解我们知道x 和2^{-1}在mod 5 的情况下同于于1。此时2^{-1}你直接看成 2 是一样的。计算x * 2 mod 5 =1,就可以知道x是多少了,显然x取3。这个是咱们手算,使用gmp_invert()方法咋求呢,该方法一共三个参数展示如下gmp_invert(result,2,5),第一个坑位放求得的逆元值,第二个坑是你求谁的逆元,第三个是mod谁。

        (2)第二步的L_p是一个函数。

                这个地方直接把数带进去计算就可以了,可以直接算乘法,应为是能够整除的。 

                但是h_p那个地方那个-1操作不能直接除法做,要求逆元,因为后面是mod一个数,可以直接求出一个逆元,不能看做是除法。就是如下展示的地方,不能看做除法,要用gmp_invert()来求逆元。

 5、使用常规方法(硬算)进行解密得到的时间:65ms

 6、使用中国剩余定理解密得到的时间:20ms

 7、常规解密的代码:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<gmpxx.h>
  5. #include<gmp.h>
  6. #include<iostream>
  7. #include<time.h>
  8. int main(){
  9. //设置随机数种子
  10. clock_t time=clock();
  11. gmp_randstate_t grt;
  12. gmp_randinit_default(grt);
  13. gmp_randseed_ui(grt, time);
  14. //p、q初始化
  15. mpz_t p,q,p1,q1;
  16. mpz_init(p);
  17. mpz_init(q);
  18. mpz_init(p1);
  19. mpz_init(q1);
  20. //p、q的的范围在0~2^128-1
  21. mpz_urandomb(p, grt, 128);
  22. mpz_urandomb(q, grt, 128);
  23. //生成p,q大素数
  24. mpz_nextprime(p, p);
  25. mpz_nextprime(q, q);
  26. //判断生成的是否是素数得到的结果为2则确定为大素数
  27. int su1,su2;//如果为1则在判断次数内大概率确定是大素数,为0则不是
  28. su1=mpz_probab_prime_p(p,10);
  29. su2=mpz_probab_prime_p(q,10);
  30. //printf("判断生成的是否是素数 :p=%d q=%d\n",su1,su2);
  31. //求p,q的乘积 n,以及n的平方n2
  32. mpz_t n,n2;
  33. mpz_init(n);
  34. mpz_init(n2);
  35. mpz_mul(n,p,q);
  36. mpz_mul(n2,n,n);
  37. //设置g,取值g=n+1
  38. mpz_t g,j;
  39. mpz_init(g);
  40. mpz_init_set_ui(j,1);
  41. //mpz_urandomb(g, grt, 128);
  42. mpz_add(g,n,j);
  43. //设置明文m
  44. mpz_t m;
  45. mpz_init_set_str(m,"123456",10);
  46. mpz_t r;//设置r,r为随机数
  47. mpz_urandomb(r, grt, 128);
  48. //设置密文c
  49. mpz_t c;
  50. mpz_init(c);
  51. //设置密文c
  52. mpz_powm(c,g,m,n2);
  53. mpz_powm(r,r,n,n2);
  54. mpz_mul(c,c,r);
  55. mpz_mod(c,c,n2);
  56. //解密过程
  57. //先求λ,是p、q的最小公倍数,y3代表λ
  58. mpz_t y1,y2,y3;
  59. mpz_init(y1);
  60. mpz_init(y2);
  61. mpz_init(y3);
  62. mpz_sub(p1,p,j);
  63. mpz_sub(q1,q,j);
  64. mpz_lcm(y3,p1,q1);//y3代表λ
  65. //输出明文m,g
  66. //十进制输出是%Zd,十六进制输出是%ZX,folat使用&Ff
  67. gmp_printf("明文m = %Zd\n\n", m);
  68. //gmp_printf("p = %Zd\n\n", p);
  69. //gmp_printf("q = %Zd\n\n", q);
  70. //gmp_printf("r = %Zd\n\n", r);
  71. //gmp_printf("g = %Zd\n\n", g);
  72. //gmp_printf("λ = %Zd\n\n", y3);
  73. //输出密文
  74. gmp_printf("密文c = %Zd\n\n",c);
  75. clock_t start, finish;
  76. start = clock();
  77. //y1代表c的λ次方摸n平方
  78. mpz_powm(y1,c,y3,n2);
  79. mpz_sub(y1,y1,j);
  80. mpz_div(y1,y1,n);
  81. //y2代表g的λ次方摸n平方
  82. mpz_powm(y2,g,y3,n2);
  83. mpz_sub(y2,y2,j);
  84. mpz_div(y2,y2,n);
  85. mpz_t x_y;
  86. mpz_init(x_y);
  87. mpz_invert(x_y,y2,n);//至关重要的一步,取逆
  88. mpz_mul(x_y,x_y,y1);
  89. mpz_mod(x_y,x_y,n);
  90. finish = clock();
  91. printf("time is :%fms\n",(double)(finish - start));
  92. //输出明文
  93. gmp_printf("解密得到明文m = %Zd\n\n",x_y);
  94. mpz_clear(p);
  95. mpz_clear(q);
  96. mpz_clear(n);
  97. mpz_clear(n2);
  98. mpz_clear(p1);
  99. mpz_clear(q1);
  100. mpz_clear(c);
  101. mpz_clear(g);
  102. mpz_clear(j);
  103. mpz_clear(r);
  104. mpz_clear(m);
  105. mpz_clear(y2);
  106. mpz_clear(y1);
  107. mpz_clear(y3);
  108. mpz_clear(x_y);
  109. return 0;
  110. }

8、使用中国剩余定理解密的代码:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<gmpxx.h>
  5. #include<gmp.h>
  6. #include<iostream>
  7. #include<time.h>
  8. //g++ test_1.c -o test1 -lgmp -lm
  9. //./test1
  10. int main(){
  11. //设置随机数种子
  12. clock_t time=clock();
  13. gmp_randstate_t grt;
  14. gmp_randinit_default(grt);
  15. gmp_randseed_ui(grt, time);
  16. //p、q初始化
  17. mpz_t p,q,p1,q1;
  18. mpz_init(p);
  19. mpz_init(q);
  20. mpz_init(p1);
  21. mpz_init(q1);
  22. //p、q的的范围在0~2^128-1
  23. mpz_urandomb(p, grt, 128);
  24. mpz_urandomb(q, grt, 128);
  25. //生成p,q大素数
  26. mpz_nextprime(p, p);
  27. mpz_nextprime(q, q);
  28. //求p,q的乘积 n,以及n的平方n2
  29. mpz_t n,n2;
  30. mpz_init(n);
  31. mpz_init(n2);
  32. mpz_mul(n,p,q);
  33. mpz_mul(n2,n,n);
  34. //设置g,取值g=n+1
  35. mpz_t g,j;
  36. mpz_init(g);
  37. mpz_init_set_ui(j,1);
  38. mpz_add(g,n,j);
  39. //设置明文m
  40. mpz_t m;
  41. mpz_init_set_str(m,"123456",10);
  42. mpz_t r;//设置r,r为随机数
  43. mpz_urandomb(r, grt, 128);
  44. //设置密文c,c1,需要对这两个密文做同态加法
  45. mpz_t c;
  46. mpz_init(c);
  47. //设置密文c
  48. mpz_powm(c,g,m,n2);
  49. mpz_powm(r,r,n,n2);
  50. mpz_mul(c,c,r);
  51. mpz_mod(c,c,n2);
  52. //输出密文
  53. gmp_printf("明文m = %Zd\n\n", m);
  54. gmp_printf("密文c = %Zd\n\n",c);
  55. //中国剩余定理做paillier
  56. mpz_sub(p1,p,j);
  57. mpz_sub(q1,q,j);
  58. mpz_t m_p,m_q,p_2,q_2,mp_y1,mp_y2,mq_y1,mq_y2,p_ni,q_ni,q_p;
  59. mpz_init(m_p);
  60. mpz_init(q_p);
  61. mpz_init(p_ni);
  62. mpz_init(q_ni);
  63. mpz_init(m_q);
  64. mpz_init(p_2);
  65. mpz_init(q_2);
  66. mpz_init(mp_y1);
  67. mpz_init(mp_y2);
  68. mpz_init(mq_y1);
  69. mpz_init(mq_y2);
  70. mpz_mul(p_2,p,p);
  71. mpz_mul(q_2,q,q);
  72. mpz_invert(p_ni,p,p);
  73. mpz_invert(q_ni,q,q);
  74. //count time
  75. clock_t start, finish;
  76. start = clock();
  77. //m_p
  78. mpz_powm(mp_y1,c,p1,p_2);
  79. mpz_sub(mp_y1,mp_y1,j);
  80. mpz_div(mp_y1,mp_y1,p);
  81. mpz_powm(mp_y2,g,p1,p_2);
  82. mpz_sub(mp_y2,mp_y2,j);
  83. mpz_div(mp_y2,mp_y2,p);
  84. mpz_invert(mp_y2,mp_y2,p);
  85. mpz_mod(mp_y2,mp_y2,p);
  86. mpz_mul(mp_y1,mp_y1,mp_y2);
  87. mpz_mod(m_p,mp_y1,p);
  88. //m_q
  89. mpz_powm(mq_y1,c,q1,q_2);
  90. mpz_sub(mq_y1,mq_y1,j);
  91. mpz_div(mq_y1,mq_y1,q);
  92. mpz_powm(mq_y2,g,q1,q_2);
  93. mpz_sub(mq_y2,mq_y2,j);
  94. mpz_div(mq_y2,mq_y2,q);
  95. mpz_invert(mq_y2,mq_y2,q);
  96. mpz_mod(mq_y2,mq_y2,q);
  97. mpz_mul(mq_y1,mq_y1,mq_y2);
  98. mpz_mod(m_q,mq_y1,q);
  99. //CRT
  100. mpz_t p_q,result;
  101. mpz_init(p_q);
  102. mpz_init(result);
  103. mpz_sub(p_q,m_q,m_p);
  104. mpz_mul(p_q,p_q,p_ni);
  105. mpz_mod(p_q,p_q,q);
  106. mpz_mul(p_q,p_q,p);
  107. mpz_add(result,m_p,p_q);
  108. finish = clock();
  109. printf("time is :%fms\n",(double)(finish - start));
  110. gmp_printf("解密得到明文m = %Zd\n\n",result);
  111. return 0;
  112. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/328704
推荐阅读
相关标签
  

闽ICP备14008679号