随便谷歌了一个图片做首图

原图地址: http://www.siwapu.com/etagid41968b0/

密码学基础系列:

  • (一) 基于整数的欧几里得算法和扩展欧几里得算法
  • (二) 中国剩余定理
  • (三) 扩展域 GF(2n)GF(2^n)GF(2n) 上的多项式运算
  • (四) 扩展域 GF(2n)GF(2^n)GF(2n) 上的欧几里得算法和扩展欧几里得算法

文章目录

  • 1. 问题
  • 2. 求解
  • 3. 代码
  • 4. 测试代码和示例
  • 5. 中国剩余定理的应用
  • 6. 完整代码
  • 7. 其它

看书自学的一个比较大的问题就是,一旦对书中的问题有疑问,尤其是一些小的细节,很难找到人答疑。

学习中国剩余定理时(CRT: Chinese Reminder Theorem),一直有点迷糊,没有完全明白中国剩余定理到底如何用。
陆续看了一些资料,

  • 《深入浅出密码学》中没有对中国剩余定理的证明,只在 7.5.2 节中提到使用中国剩余定理快速加密
  • 《密码编码学与网络安全》各版本(包括六/七/八版)中,对中国剩余定理的描述相当复杂(也可能是我太蠢了)
  • 《数论概论》第三版第 11 章中,只说了中国剩余定理的表述,没有提供完整计算方式
  • 《密码学原理与实践》第三版中,第 5.2.2 节对中国剩余定理有详细的证明和描述,是我见过最易懂的说明。

这里摘录一下《密码学原理与实践》中关于中国剩余定理的描述(第5.2.2节):

(中国剩余定理) 假定m1,m2,...,mrm_1, m_2, ..., m_rm1​,m2​,...,mr​为两两互素的正整数,又假定a1,a2,...,ara_1, a_2, ..., a_ra1​,a2​,...,ar​为整数。那么同余方程组:
x≡ai(modmi)(1≤i≤r)x\equiv a_i(mod\ m_i)(1\le i \le r)x≡ai​(mod mi​)(1≤i≤r) 有模 M=m1×m2×...×mrM=m_1 \times m_2 \times ... \times m_rM=m1​×m2​×...×mr​的唯一解,此解由下式给出:
x=∑i=1raiMiyimodMx = \sum_{i=1}^{r}{a_iM_iy_i}\ mod\ M x=i=1∑r​ai​Mi​yi​ mod M

其中, Mi=M/miM_i = M\ /\ m_iMi​=M / mi​,且yi=Mi−1modmi,1≤i≤ry_i=M_i^{-1}\ mod\ m_i, 1 \le i \le ryi​=Mi−1​ mod mi​,1≤i≤r

从定理出发,明确了定义之后,就容易计算了。

这里以《孙子算经》中的原文为例:

今有物不知其数,三三数之余二,五五数之余三,七七数之余二,问物几何?

1. 问题

这个问题翻译过来就是:

已知 3 个同余方程组:

  • 2≡xmod3,3≡xmod5,2≡xmod72\equiv x\ mod\ 3,\quad 3\equiv x\ mod\ 5,\quad 2\equiv x\ mod\ 72≡x mod 3,3≡x mod 5,2≡x mod 7,

求xxx。

从条件得知:

  1. (m1,m2,m3)⇒(3,5,7)(m_1, m_2, m_3)\Rightarrow(3, 5, 7)(m1​,m2​,m3​)⇒(3,5,7),即m1=3,m2=5,m3=7m_1=3,\ m_2=5,\ m_3=7m1​=3, m2​=5, m3​=7
  2. (a1,a2,a3)⇒(2,3,2)(a_1, a_2, a_3)\Rightarrow(2, 3, 2)(a1​,a2​,a3​)⇒(2,3,2),即a1=2,a2=3,a3=2a_1=2,\ a_2=3,\ a_3=2a1​=2, a2​=3, a3​=2

2. 求解

第一步,计算同余方程组的模M=m1×m2×...×mrM=m1 \times m2 \times ... \times m_rM=m1×m2×...×mr​

  • M=m1×m2×m3=3×5×7=105M=m_1 \times m_2 \times m_3 = 3 \times 5 \times 7 = 105M=m1​×m2​×m3​=3×5×7=105

第二步,求MiM_iMi​及其基于mim_imi​的逆元Mi−1M_i^{-1}Mi−1​和yiy_iyi​

这里的逆元Mi−1M_i^{-1}Mi−1​使用《密码学基础算法(一)基于整数的欧几里得算法和扩展欧几里得算法》一文中求逆的函数int int_inv(int a, int b)来求取。

  • M1=M/m1=105/3=35M_1=M\ /\ m_1 = 105 / 3 = 35M1​=M / m1​=105/3=35, M1−1=int_inv(M1,m1)=int_inv(35,3)=2M_1^{-1}=int\_inv(M_1,m_1)=int\_inv(35,3)=2M1−1​=int_inv(M1​,m1​)=int_inv(35,3)=2, y1=M1−1modm1=2mod3=2y_1=M_1^{-1}\ mod\ m_1=2\ mod\ 3=2y1​=M1−1​ mod m1​=2 mod 3=2
  • M2=M/m2=105/5=21M_2=M\ /\ m_2 = 105 / 5 = 21M2​=M / m2​=105/5=21, M2−1=int_inv(M2,m2)=int_inv(21,5)=1M_2^{-1}=int\_inv(M_2,m_2)=int\_inv(21,5)=1M2−1​=int_inv(M2​,m2​)=int_inv(21,5)=1, y2=M2−1modm2=1mod5=1y_2=M_2^{-1}\ mod\ m_2=1\ mod\ 5=1y2​=M2−1​ mod m2​=1 mod 5=1
  • M3=M/m3=105/7=15M_3=M\ /\ m_3 = 105 / 7 = 15M3​=M / m3​=105/7=15, M3−1=int_inv(M3,m3)=int_inv(15,7)=1M_3^{-1}=int\_inv(M_3,m_3)=int\_inv(15,7)=1M3−1​=int_inv(M3​,m3​)=int_inv(15,7)=1, y3=M3−1modm3=1mod7=1y_3=M_3^{-1}\ mod\ m_3=1\ mod\ 7=1y3​=M3−1​ mod m3​=1 mod 7=1

第三步,根据第二步计算的M/Mi/yiM/M_i/y_iM/Mi​/yi​,使用中国剩余定理的公式求xxx

x=∑i=1raiMiyimodM=(a1M1y1+a2M2y2+a3M3y3)mod105=(2×35×2+3×21×1+2×15×1)mod105=(140+63+30)mod105=233mod105=23x = \sum_{i=1}^{r}{a_iM_iy_i}\ mod\ M = (a_1M_1y_1 + a_2M_2y_2 + a_3M_3y_3)\ mod\ 105\\= (2 \times 35 \times 2 + 3 \times 21 \times 1 + 2 \times 15 \times 1)\ mod\ 105 \\= (140 + 63 + 30)\ mod\ 105\\=233\ mod\ 105 \\= 23 x=i=1∑r​ai​Mi​yi​ mod M=(a1​M1​y1​+a2​M2​y2​+a3​M3​y3​) mod 105=(2×35×2+3×21×1+2×15×1) mod 105=(140+63+30) mod 105=233 mod 105=23

所以最后得到要求的数为 23。

3. 代码

我们可以根据前面的计算过程将其翻译成代码

/*** @description: 中国剩余定理(CRT: Chinese Reminder Theorem)求同余方程解* @param {int} 指针 m, 指向整型数组, 包含每一组除数* @param {int} 指针 r, 指向整型数组, 包含每一组余数* @param {int} 整数 n, 指定传入指针 m 和 r 指向数组的大小* @return {*} 中国剩余定理的同余方程解*/
int crt(int *m, int *r, int n)
{int i;int M, Mi, yi;int sum;// 计算同于方程组的模 MM = 1;for (i=0; i<n; i++){M *= m[i];}sum = 0;for (i=0; i<n; i++){// 计算每一个 MiMi = M / m[i];// 计算每一个 yiyi = int_inv(Mi, m[i]) % m[i];// 累积求和sum += r[i] * Mi * yi;}return sum % M;
}

其中调用的函数int_inv来自《密码学基础算法(一)基于整数的欧几里得算法和扩展欧几里得算法》,专门用于求整数的乘法逆元,如下:

/*** @description: 基于扩展欧几里得算法计算整数 a 关于 整数 b 的乘法逆元(展开 int_gcd_ex 后的优化版本)* @param {int} a 整数 a* @param {int} b 整数 b* @return {*} 返回整数 a 关于整数 b 的最小正整数乘法逆元, 乘法逆元不存在(gcd(a, b) != 1)则返回 0;*/
int int_inv(int a, int b)
{int x, x0, x1;int q, r, t;/* 消除警告: "warning: ‘x’ may be used uninitialized in this function" */x = 0;/* 初始化最初两项系数 */x0 = 1;x1 = 0;/* 临时保存 b */t = b;q = a / b;r = a % b;while (r != 0){/* 计算当前项 x */x = x0 - q * x1;/* 依次保存前两项到 x0, x1 */x0 = x1; x1 = x;a = b;b = r; /* 前一次的余数 */q = a / b;r = a % b;}/* gcd(a, b) != 1, 没有乘法逆元 */if (b != 1){return 0;}/* 调整小于 0 的情况 */if (x < 0){x += t;}return x;
}

4. 测试代码和示例

  • 测试代码
int main(int argc, char *argv[])
{int m1[3] = { 3,  5,  7}, r1[3] = { 2,  3,  2}; // 示例1: 孙子算经int m2[3] = { 7, 11, 13}, r2[3] = { 5,  3, 10}; // 示例2: 《密码学原理与实践》第三版, p133, 例 5.3int m3[3] = {25, 26, 27}, r3[3] = {12,  9, 23}; // 示例3: 《密码学原理与实践》第三版, p178, 题 5.6int m4[2] = {37, 49},     r4[2] = {11, 42};     // 示例4: 《密码编码学与网络安全》第七版, p37, 示例int res;res = crt(m1, r1, 3);printf("同余方程组: 除数{ 7, 11, 13}, 余数{ 5,  3, 10}的解为 %d\n", res);res = crt(m2, r2, 3);printf("同余方程组: 除数{ 3,  5,  7}, 余数{ 2,  3,  2}的解为 %d\n", res);res = crt(m3, r3, 3);printf("同余方程组: 除数{25, 26, 27}, 余数{12,  9, 23}的解为 %d\n", res);res = crt(m4, r4, 2);printf("同余方程组: 除数{37, 49},     余数{11, 42}    的解为 %d\n", res);return 0;
}
  • 编译和运行
$ gcc crt.c -o crt
$ ./crt
同余方程组: 除数{ 7, 11, 13}, 余数{ 5,  3, 10}的解为 23
同余方程组: 除数{ 3,  5,  7}, 余数{ 2,  3,  2}的解为 894
同余方程组: 除数{25, 26, 27}, 余数{12,  9, 23}的解为 14387
同余方程组: 除数{37, 49},     余数{11, 42}    的解为 973

5. 中国剩余定理的应用

根据《密码编码学与网络安全》中的说明,运用中国剩余定理,使得模 M 的大数运算可以转化为相对较小的数的运算。当 M 为 150 位或 150 位以上时,这种方法特别有效。

例如:

973 对 37 和 49 取模分别为: 973mod37=11,973mod49=42973\ mod\ 37\ =\ 11,\ 973\ mod\ 49\ =\ 42973 mod 37 = 11, 973 mod 49 = 42,因此把 973 表示为(11, 42)的形式。

假如要计算 678 + 973 = 1651, 用处理 973 的办法同样处理 678: 678mod37=12,678mod49=41678\ mod\ 37=\ 12,\ 678\ mod\ 49=\ 41678 mod 37= 12, 678 mod 49= 41,因此把 678 表示为(12, 41)

然后将上面得到的两个二元组的元素相加并化简:
1651=973+678=((11+12)mod37,(42+41)mod49)=(23,34)1651=973+678=((11+12)\ mod\ 37, (42+41)\ mod\ 49)=(23, 34)1651=973+678=((11+12) mod 37,(42+41) mod 49)=(23,34)

从上面的例子可以看到,大数 1651 (其实很小) 对 37 和 49 取模转换成了小数 973 和 678 对 37 和 49 取模。

虽然看起来计算量差不多,但是对很大的数,前面提到的 150 位或更多这种,转换成两个数乘积的形式,新的数短一半,再进行操作是很有优势的。

6. 完整代码

#include <stdio.h>/*** @description: 基于扩展欧几里得算法计算整数 a 关于 整数 b 的乘法逆元(展开 int_gcd_ex 后的优化版本)* @param {int} a 整数 a* @param {int} b 整数 b* @return {*} 返回整数 a 关于整数 b 的最小正整数乘法逆元, 乘法逆元不存在(gcd(a, b) != 1)则返回 0;*/
int int_inv(int a, int b)
{int x, x0, x1;int q, r, t;/* 消除警告: "warning: ‘x’ may be used uninitialized in this function" */x = 0;/* 初始化最初两项系数 */x0 = 1;x1 = 0;/* 临时保存 b */t = b;q = a / b;r = a % b;while (r != 0){/* 计算当前项 x */x = x0 - q * x1;/* 依次保存前两项到 x0, x1 */x0 = x1; x1 = x;a = b;b = r; /* 前一次的余数 */q = a / b;r = a % b;}/* gcd(a, b) != 1, 没有乘法逆元 */if (b != 1){return 0;}/* 调整小于 0 的情况 */if (x < 0){x += t;}return x;
}/*** @description: 中国剩余定理(CRT: Chinese Reminder Theorem)求同余方程解* @param {int} 指针 m, 指向整型数组, 包含每一组除数* @param {int} 指针 r, 指向整型数组, 包含每一组余数* @param {int} 整数 n, 指定传入指针 m 和 r 指向数组的大小* @return {*} 中国剩余定理的同余方程解*/
int crt(int *m, int *r, int n)
{int i;int M, Mi, yi;int sum;// 计算同于方程组的模 MM = 1;for (i=0; i<n; i++){M *= m[i];}sum = 0;for (i=0; i<n; i++){// 计算每一个 MiMi = M / m[i];// 计算每一个 yiyi = int_inv(Mi, m[i]) % m[i];// 累积求和sum += r[i] * Mi * yi;}return sum % M;
}int main(int argc, char *argv[])
{int m1[3] = { 3,  5,  7}, r1[3] = { 2,  3,  2}; // 示例1: 孙子算经int m2[3] = { 7, 11, 13}, r2[3] = { 5,  3, 10}; // 示例2: 《密码学原理与实践》第三版, p133, 例 5.3int m3[3] = {25, 26, 27}, r3[3] = {12,  9, 23}; // 示例3: 《密码学原理与实践》第三版, p178, 题 5.6int m4[2] = {37, 49},     r4[2] = {11, 42};     // 示例4: 《密码编码学与网络安全》第七版, p37, 示例int res;res = crt(m1, r1, 3);printf("同余方程组: 除数{ 7, 11, 13}, 余数{ 5,  3, 10}的解为 %d\n", res);res = crt(m2, r2, 3);printf("同余方程组: 除数{ 3,  5,  7}, 余数{ 2,  3,  2}的解为 %d\n", res);res = crt(m3, r3, 3);printf("同余方程组: 除数{25, 26, 27}, 余数{12,  9, 23}的解为 %d\n", res);res = crt(m4, r4, 2);printf("同余方程组: 除数{37, 49},     余数{11, 42}    的解为 %d\n", res);return 0;
}

7. 其它

洛奇工作中常常会遇到自己不熟悉的问题,这些问题可能并不难,但因为不了解,找不到人帮忙而瞎折腾,往往导致浪费几天甚至更久的时间。

所以我组建了几个微信讨论群(记得微信我说加哪个群,如何加微信见后面),欢迎一起讨论:

  • 一个密码编码学讨论组,主要讨论各种加解密,签名校验等算法,请说明加密码学讨论群。
  • 一个Android OTA的讨论组,请说明加Android OTA群。
  • 一个git和repo的讨论组,请说明加git和repo群。

在工作之余,洛奇尽量写一些对大家有用的东西,如果洛奇的这篇文章让您有所收获,解决了您一直以来未能解决的问题,不妨赞赏一下洛奇,这也是对洛奇付出的最大鼓励。扫下面的二维码赞赏洛奇,金额随意:

洛奇自己维护了一个公众号“洛奇看世界”,一个很佛系的公众号,不定期瞎逼逼。公号也提供个人联系方式,一些资源,说不定会有意外的收获,详细内容见公号提示。扫下方二维码关注公众号:

密码学基础算法(二)中国剩余定理相关推荐

  1. 信息安全基础综合实验-中国剩余定理

    最近没有什么事情,打算把之前的作业整理一下发出来,有需要的学弟学妹们可以参考一下. 相关:某电的密码学实验,信安专业必选实验 实验题目:中国剩余定理 实验目的 (包括实验环境.实现目标等等) 实验环境 ...

  2. 密码学基础——辗转相除法,费马小定理,欧拉定理,裴蜀定理,中国剩余定理

    文章主要根据百度百科和维基百科相关相关知识点整理而成! 辗转相除法 辗转相除法, 又名欧几里德算法(Euclidean algorithm),是求最大公约数的一种方法.它的具体做法是:用较小数除较大数 ...

  3. 从孙子算经到中国剩余定理

    中国剩余定理中间涉及一个重要观念:互质: 首先来看<孙子算经>卷下第二十六问:今有物,不知其数.三.三数之,剩二:五.五数之,剩三:七.七数之,剩二.问物几何? 转换为数学语言即是(理解其 ...

  4. 扩展欧几里得算法、乘法逆元与中国剩余定理

    文章目录 前言 定义.定理和部分证明 整除 定义 定理 定理的证明 同余 定义 同余的性质 同余的运算律 运算律的证明 扩展欧几里得算法 代码模板 算法详解 乘法逆元 求解逆元 乘法逆元的作用 中国剩 ...

  5. 中国剩余定理Chinese remainder theorem(CRT)

    中国剩余定理 孙子定理, Chinese remainder theorem(CRT) 参考 : 百度百科-中国剩余定理 有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二.问物几何? x=2mo ...

  6. 中国剩余定理matlab程序,中国剩余定理即孙子定理的五种解法

    中国剩余定理即孙子定理的五种解法 -- 学习初等数论心得笔记 2013-10-04 博文2015-12修改 "中国剩余定理"是公元5-6世纪.我国南北朝时期的一部著名算术著作< ...

  7. 基于Miracl库的中国剩余定理C语言实现

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/tch3430493902/articl ...

  8. 数论一之定理证明——裴蜀/威尔逊/费马/扩展欧几里得/[扩展]欧拉/[扩展]中国剩余定理,欧拉函数,逆元,剩余系,筛法

    打死没想到会在H老师处学懂数论 同余,整除 模运算 埃式筛法 欧拉筛法 最大公约数和最小公倍数 辗转相除法 更相减损术 裴蜀定理 威尔逊定理 费马定理 同余等价类.剩余系.缩系 欧拉函数 欧拉定理 扩 ...

  9. 信奥中的数学:孙子定理 中国剩余定理

    孙子定理 中国剩余定理 孙子定理 中国剩余定理_Dreamer Thinker Doer-CSDN博客 中国剩余问题(简介+详解) 中国剩余问题(简介+详解)_dreamzuora的博客-CSDN博客 ...

最新文章

  1. 支持向量机原理(五)线性支持回归
  2. JavaScript判断是否是手机mobile登录
  3. 油田智能化远程监控系统_十种远程无线视频监控系统拓扑图
  4. Pivotal发布Spring Cloud Data Flow 1.5版本
  5. 实践编译LINUX0.11源码,感觉真爽。
  6. springmvc 拦截器_Spring MVC拦截器学习
  7. 2019 d serv 激活_化疗过程中肌肉减少症的发生机制及维生素D、ω-3脂肪酸的作用...
  8. 一个JSP大马的源码
  9. ES6-ES11新特性_ECMAScript相关名词介绍_---JavaScript_ECMAScript工作笔记002
  10. 手机浏览器被强制跳转_Azure front door 强制http redirect to https
  11. CSS规则重要性以及继承、层叠
  12. 老板下死命令:必须将20M文件从30秒压缩到1秒,我是如何做到的?
  13. 洛谷P3233 [HNOI2014]世界树
  14. Hibernate配置文件,映射文件
  15. java怎么设置_java环境配置怎么设置?Java基础教程
  16. mysql怎么导出insert语句_mysql导出insert语句
  17. 阿帕奇服务器配置站点,Apache的基本服务器配置
  18. s3c6410裸机调试方式总结
  19. 个税计算公式excel_我月薪1万,为啥个税只交150块捏?
  20. 考考你的基础知识:C++ 文件操作ofstream、ifstream使用

热门文章

  1. 从1万到100万的理财法则
  2. 叉乘点乘混合运算公式_用抽象指标记号推导nabla算符相关公式
  3. Vivado HLS常用优化命令介绍
  4. 自然语言处理中CNN模型几种常见的Max Pooling操作
  5. 毕得医药递交科创板注册:年营收6亿 拟募资4.34亿
  6. SpringCloud调用接口流程
  7. 运维体系建设(第二章)
  8. mysql主备集群(高可用)
  9. 从0开始编写一个应用(android端+小程序端+服务器端)第二步 项目经理完成逻辑图。(下:产品细节思考后的实现逻辑图)
  10. 神一般的科学“超人”尼古拉-特斯拉!