• 6.3 公钥算法的基本数论知识(欧几里得算法、扩展欧几里得算法、欧拉函数、费马小定理与欧拉定理)


    欧几里得算法

    首先介绍计算最大公约数 ( g c d ) (gcd) (gcd)的问题。两个正整数 r 0 r_0 r0 r 1 r_1 r1 g c d gcd gcd表示为 g c d ( r 0 , r 1 ) gcd(r_0,r_1 ) gcd(r0,r1)它指的是被 r 0 r_0 r0 r 0 r_0 r0同时整除的最大正整数。例如 g c d ( 21 , 9 ) = 3 gcd(21,9)=3 gcd(219)=3。对小整数而言, ( g c d ) (gcd) (gcd)的计算非常容易,就是将两个整数因式分解,并找出最大的公共因子。

    然而,对公钥方案中使用的大整数而言,因式分解通常是不可能的。所以,人们通常使用一种更有效的算法计算 ( g c d ) (gcd) (gcd),那就是欧几里得算法。此算法基于一个简单的观察,即 g c d ( r 0 , r 1 ) = g c d ( r 0 − r 1 , r 1 ) gcd(r_0,r_1 )=gcd(r_0 - r_1,r_1 ) gcd(r0,r1)=gcd(r0r1,r1)其中,通常假设 r 0 > r 1 r_0 > r_1 r0>r1,并且两个数均为正整数。

    此属性的证明非常简单: 假设 g c d ( r 0 , r 1 ) = g gcd(r_0,r_1 )=g gcd(r0,r1)=g,由于 g g g可以同时除 r 0 r_0 r0 r 1 r_1 r1,则可以记作 r 0 = g ⋅ x r_0=g·x r0=gx r 1 = g ⋅ y r_1=g·y r1=gy,其中x > y,且x和y为互素的整数,即它们没有公共因子。此外,证明(x-y)与y互素也非常简单,这里可以使用反证法很容易证明(x-y)与y互素。因此可以得到: g c d ( r 0 , r 1 ) = g c d ( r 0 − r 1 , r 1 ) = g c d ( g . ( x − y ) , g . y ) = g gcd(r_0,r_1 )=gcd(r_0 - r_1,r_1 )=gcd(g.(x-y),g.y )=g gcd(r0,r1)=gcd(r0r1,r1)=gcd(g.(xy),g.y)=g

    示例: 假设 r 0 = 84 , r 1 = 30 r_0=84, r_1=30 r0=84r1=30,则 r 0 − r 1 r_0 - r_1 r0r1 r 1 r_1 r1的gcd为:
    r 0 − r 1 = 84 − 30 = 54 = 2 ∗ 3 ∗ 3 ∗ 3 r_0 - r_1 = 84 - 30 = 54 = 2 * 3 * 3 * 3 r0r1=8430=54=2333 r 1 = 30 = 2 ∗ 3 ∗ 5 r_1 = 30 = 2 * 3 * 5 r1=30=235
    最大公因子仍然是: 2 ⋅ 3 = 6 = g c d ( 30 , 54 ) = g c d ( 30 , 84 ) 。 2·3 = 6 = gcd(30,54) = gcd(30,84)。 23=6=gcd(30,54)=gcd(30,84)

    只要满足 ( r 0 − m r 1 ) > 0 (r_0-mr_1)>0 (r0mr1)>0,迭代地使用这个过程可以得到: g c d ( r 0 , r 1 ) = g c d ( r 0 − r 1 , r 1 ) = g c d ( r 0 − 2 r 1 , r 1 ) = … = g c d ( r 0 − m r 1 , r 1 ) gcd(r_0, r_1)= gcd(r_0 - r_1,r_1)= gcd(r_0 - 2r_1, r_1)=…=gcd(r_0 - mr_1, r_1) gcd(r0,r1)=gcd(r0r1,r1)=gcd(r02r1,r1)==gcd(r0mr1,r1)如果m选择了最大值,则此算法使用的步骤也是最少的。这种情况可以表示为:
    g c d ( r 0 , r 1 ) = g c d ( r 0 m o d r 1 , r 1 ) gcd(r_0, r_1) = gcd(r_0 mod r_1, r_1) gcd(r0,r1)=gcd(r0modr1,r1)由于第一项 ( r 0 m o d r 1 ) (r_0 mod r_1) (r0modr1)比第二项 r 1 r_1 r1小,通常可以交换它们: g c d ( r 0 , r 1 ) = g c d ( r 1 , r 0 m o d r 1 ) gcd(r_0 , r_1)= gcd(r_1, r_0 mod r_1) gcd(r0,r1)=gcd(r1,r0modr1)这个过程的核心关注点在于,我们可将查找两个给定整数的 g c d gcd gcd简化为查找两个较小整数的 g c d gcd gcd。迭代地进行这个过程,直到最后得到 g c d ( r l , 0 ) = r l gcd(r_l, 0)=r_l gcd(rl,0)=rl。由于每轮迭代都保留了前一轮迭代步骤的 g c d gcd gcd,事实证明:最终的 g c d gcd gcd就是原始问题的 g c d gcd gcd,即: g c d ( r o , r 1 ) = … = g c d ( r l , 0 ) = r l gcd(ro, r_1)= … = gcd(r_l, 0) = r_l gcd(ro,r1)==gcd(rl,0)=rl
    示例: 假设 r 0 = 973 , r 1 = 301 r_0=973, r_1=301 r0=973r1=301,则 g c d gcd gcd为:

    解: g c d ( 973 , 301 ) = g c d ( 301 , 973 m o d 301 ) = g c d ( 301 , 70 ) = g c d ( 70 , 301 m o d 70 ) = g c d ( 70 , 21 ) = g c d ( 21 , 70 m o d 21 ) = g c d ( 21 , 7 ) = g c d ( 7 , 21 m o d 7 ) = g c d ( 7 , 0 ) = 7 gcd(973, 301) = gcd(301, 973 mod 301) = gcd(301, 70) = gcd(70, 301 mod 70) = gcd(70, 21) = gcd(21, 70 mod 21) = gcd(21, 7) = gcd(7, 21 mod 7) = gcd(7, 0) = 7 gcd(973,301)=gcd(301,973mod301)=gcd(301,70)=gcd(70,301mod70)=gcd(70,21)=gcd(21,70mod21)=gcd(21,7)=gcd(7,21mod7)=gcd(7,0)=7

    Java实现欧几里得算法

    /**
     * @Author Mr.Lu
     * @Date 2022/6/25 16:11
     * @ClassName EuclideanAlgorithm
     * @Version 1.0
     */
    public class EuclideanAlgorithmDemo {
        public static void main(String[] args) {
            System.out.println(euclideanAlgorithm(973, 301));
        }
    
        public static int euclideanAlgorithm(int r0, int r1){
            // 利用位运算,始终保持ro >= r1
            if(r1 >  r0){
                r0 =  r0 ^ r1;
                r1 =  r0 ^ r1;
                r0=  r0 ^ r1;
            }
    
            // 递归结束条件r1 == 0
            if(r1 == 0){
                return r0;
            }
    
            int temp =  r0 % r1;  // 取模
            r0 = r1;
            r1 = temp;
    
            return euclideanAlgorithm( r0, r1);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    扩展欧几里得算法

    欧拉函数

    在环 Z m = { 0 , 1 , . . . , m − 1 } Z_m={\{0,1,...,m-1\}} Zm={0,1...,m1}中,如何求这个集合中有多少个数字与m互素呐??。这个数目可以由欧拉(Euler’s Phi)函数给出,其定义如下:

    欧拉函数 Z m Z_m Zm内与m互素的整数的个数可以表示为 Φ ( m ) \Phi(m) Φ(m)

    Φ ( m ) \Phi(m) Φ(m)计算方法:假设m可以因式分解为以下数的连乘 m = p 1 e 1 ∗ p 2 e 2 ∗ . . . . . . . ∗ p n e n m={p_1}^{e_1}*{p_2}^{e_2}*.......*{p_n}^{e_n} m=p1e1p2e2.......pnen其中, p i p_i pi表示不同元素的个数, e i e_i ei表示正整数,则有 Φ ( m ) = ∏ i = 1 n ( p i e i − p i e i − 1 ) \Phi(m)=\quad \prod_{i=1}^n({p_i}^{e_i} - {p_i}^{e_i-1}) Φ(m)=i=1n(pieipiei1)

    示例: 假设m=240,240因式分解对应的连乘形式为: m = 240 = 16 ∗ 15 = 2 4 ∗ 3 ∗ 5 = p 1 e 1 ∗ p 2 e 2 ∗ p 3 e 3 m = 240=16*15=2^4*3*5 = {p_1}^{e_1}*{p_2}^{e_2}*{p_3}^{e_3} m=240=1615=2435=p1e1p2e2p3e3其中有三个不同的质因子,即n= 3,则欧拉函数的值为 Φ ( m ) = ( 2 4 − 2 3 ) ∗ ( 3 1 − 3 0 ) ( 5 1 − 5 0 ) = 8 ∗ 2 ∗ 4 = 64 \Phi(m)=(2^4 - 2^3) * (3^1 - 3^0)(5^1-5^0)=8*2*4=64 Φ(m)=(2423)(3130)(5150)=824=64这意味着在范围 { 0 , 1 , . . . , 239 } \{0,1,...,239\} {01...239}内存在64个整数与m = 240互素。而替代方法需要计算240次 g c d gcd gcd,也就是需要把0-239中的每个数与240进行判读是否互素,即使对较小的整数而言,这个计算过程也会非常慢。

    注意: 在用这种方法快速计算欧拉函数时,前提是必须要知道m的因式分解。这个特性也是RSA公钥方案的核心; 如果已知某个整数的因式分解,就可以计算出欧拉函数并解密密文。如果因式分解未知,也就不能计算欧拉函数,也无法解密。

    Java实现欧拉函数(暴力求解方式)

    /**
     * @Author Mr.Lu
     * @Date 2022/6/25 20:51
     * @ClassName EulerFunctionDemo
     * @Version 1.0
     */
    public class EulerFunctionDemo {
        public static void main(String[] args) {
            System.out.println(eulerFunction(240));
        }
    
        /**
         * 求{0, m-1}中与m互素的个数
         * @param m
         * @return
         */
        public static int eulerFunction(int m){
            int eul = 0;  // 集合中与m互素的个数
            for(int i = 0; i < m; i++){
                if(gcd(i, m) == 1){
                    eul++;
                }
            }
    
            return eul;
        }
    
        /**
         * 求r0与r1的最大公约数
         * @param r0
         * @param r1
         * @return
         */
        public static int gcd(int r0, int r1){
            // 利用位运算,始终保持 ro > r1
            if(r1 >  r0){
                r0 =  r0 ^ r1;
                r1 =  r0 ^ r1;
                r0 =  r0 ^ r1;
            }
    
            // 递归结束条件
            if(r1 == 0){
                return  r0;
            }
    
            int temp =  r0 % r1;  // 取模
            r0 = r1;
            r1 = temp;
    
            return gcd( r0, r1);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    费马小定理与欧拉定理

    费马小定理:假设 a a a为一个整数, p p p为一个素数,则: a p ≡ a ( m o d p ) a^p \equiv a(modp) apa(modp)注意,有限域 G F ( p ) GF(p) GF(p)上的算术运算都是通过 m o d p mod p modp实现的,因此,对有限域 G F ( p ) GF(p) GF(p)内的所有整数元素 a a a而言,此定理始终成立。此定理也可表示为以下形式: a p − 1 ≡ 1 ( m o d p ) a^{p-1} \equiv 1(mod p) ap11(modp)此等式也可以写成 a ∗ a p − 2 ≡ 1 ( m o d p ) a*a^{p-2} \equiv 1(modp) aap21(modp)这个表示形式正是乘法逆运的定义。因此,我们可以得到反转整数a模一个素数的方法 a − 1 ≡ a p − 2 ( m o d p ) a^{-1} \equiv a^{p-2}(mod p) a1ap2(modp)注意:只有在p为素数的时候这种反转方法才成立。

    示例:假设p=7,a= 2,计算a的逆元可以表示为: a p − 2 = 2 5 = 32 ≡ 4 ( m o d 7 ) a^{p-2} = 2^5 = 32 \equiv 4(mod 7) ap2=25=324(mod7)结果验证: 2 ∗ 4 ≡ 1 m o d 7 2*4 \equiv 1mod7 241mod7

    将费马小定理的模数推广到任何整数模,即p不一定为素数的模,就可得到欧拉定理。

    欧拉定理:假设 a a a m m m都是整数,且 g c d ( a , m ) = 1 gcd(a, m)=1 gcd(a,m)=1, 则有: a Φ ( m ) ≡ 1 ( m o d m ) a^{\Phi(m)} \equiv 1(mod m) aΦ(m)1(modm)由于这个定理对模数m适用,所以它也适用于整数环 Z m Z_m Zm内的所有整数。

    示例:假设m = 12,a = 5。首先计算m的欧拉函数: Φ ( 12 ) = Φ ( 2 2 ∗ 3 ) = ( 2 2 − 2 1 ) ( 3 1 − 3 0 ) = ( 4 − 2 ) ( 3 − 1 ) = 4 \Phi(12) = \Phi(2^2*3) = (2^2 - 2^1)(3^1 - 3^0) = (4 - 2)(3 - 1) = 4 Φ(12)=Φ(223)=(2221)(3130)=(42)(31)=4验证欧拉定理: 5 Φ ( 12 ) = 5 4 = 2 5 2 = 625 ≡ 1 ( m o d m ) 5^{\Phi(12)} = 5^4 = 25^2 = 625 \equiv 1(mod m) 5Φ(12)=54=252=6251(modm)费马小定理是欧拉定理的一个特例。如果p为一个素数,则 Φ ( p ) = ( p 1 − p 0 ) = p − 1 \Phi(p) = (p^1 - p^0) = p - 1 Φ(p)=(p1p0)=p1成立。如果将这个值用于欧拉定理,则可得到: a Φ ( p ) = ( p 1 − p 0 ) = p − 1 a^{\Phi(p)} = (p^1 - p^0) = p - 1 aΦ(p)=(p1p0)=p1,而这正是费马小定理。




    参考资料:《深入浅出密码学》–Christof Paar,Jan Pelzl著

  • 相关阅读:
    C#实战:基于腾讯OCR技术实现企业证书识别和数据提取实践
    软件测试/测试开发丨基于人工智能的代码分析与 Bug 检测实战
    【面试题精讲】Java字符型常量和字符串常量的区别?
    NOIP2023模拟13联测34 总结
    AIGC , 超级热点 or 程序员创富新起点?
    accelerate 分布式技巧(一)
    《剑指 Offer》专项突破版 - 面试题 79 ~ 84 : 详解回溯法(C++ 实现)
    uniapp项目打包H5后 希望可以修改固定的配置(接口地址,系统名称等)
    2022年全球市场先进封装检测系统总体规模、主要生产商、主要地区、产品和应用细分研究报告
    【shell】限制任务并发
  • 原文地址:https://blog.csdn.net/qq_43751200/article/details/125460326