扩展欧几里得算法

算法 专栏收录该内容
1 篇文章 0 订阅

RSA算法中根据公钥求私钥

  1. 什么是RSA算法

    1. 选择两个大素数p, q ;

      计算n=pq, ø(n) = (p-1) (q-1) ;

    2. 公钥的产生

      随机地选择e

      满足1< e < ø(n),gcd(e, ø(n)) = 1

    3. 私钥的产生

      求解同余方程:

      ed ≡ 1 mod ø(n), 0 ≤ dn

  2. 私钥d如何由e计算得出,也就是求e关于ø(n)的乘法逆元

    使用下面介绍的扩展欧几里得算法

背景知识

欧几里得算法

问题描述:已知a,b,求gcd(a,b).也就是a与b的最大公约数

算法:辗转相除法

基于gcd(a,b)=gcd(b,a%b)

//java代码
public static int void gcd(int a,int b){
    return b==0?a:gcd(b,a%b);
}

贝祖定理

如果a、b是整数,那么一定存在整数x、y使得ax+by=gcd(a,b)。

换句话说,如果ax+by=c有解,那么c一定是gcd(a,b)的若干倍。(可以来判断一个这样的式子有没有解)

扩展欧几里得算法

问题描述:整数二元一次不定方程问题。

​ 形如ax+by=c(a,b均不为0)的方程,a,b,c都是整数,求(x,y)的整数解。

x,y其中一个很有可能为负数

算法:

  1. 判断是否有解,使用贝祖定理

    如果有解,可以先求ax+by=gcd(a,b)的解,ax+by=c的解只是前者的c/gcd(a,b)倍而已

    当然,如果有解的话肯定不止一对

    x = x   0   + b / g c d ( a , b ) ∗ t x = x~0~+b/gcd(a,b)*t x=x 0 +b/gcd(a,b)t

    y = y   0   − a / g c d ( a , b ) ∗ t y = y~0~ - a/gcd(a,b)*t y=y 0 a/gcd(a,b)t

  2. 使用扩展欧几里得算法求解(x,y)

    ​ ① a x + b y = g c d ( a , b ) ax + by = gcd(a,b) ax+by=gcd(a,b)

    ​ ② b x 1 + ( a % b ) y 1 = g c d ( b , a % b ) bx1 + (a\%b)y1 = gcd(b,a\%b) bx1+(a%b)y1=gcd(b,a%b)

    根据a%b = a - a/b*b,替换上式a%b

    a/b中的/指的是整除结果

    b x 1 + ( a − a / b ∗ b ) y 1 = g c d ( b , a % b ) bx1 + (a-a/b*b)y1 = gcd(b,a\%b) bx1+(aa/bb)y1=gcd(b,a%b)

    整理一下得

    ​ ③ a y 1 + b ( x 1 − a / b ) y 1 = g c d ( b , a % b ) ay1 + b(x1 - a/b)y1 = gcd(b,a\%b) ay1+b(x1a/b)y1=gcd(b,a%b)

    因为 g c d ( a , b ) = g c d ( b , a % b ) gcd(a,b) = gcd(b,a\%b) gcd(a,b)=gcd(b,a%b)

    ​ 对比①③得

    x = y 1 x = y1 x=y1

    y = x 1 − a / b ∗ y 1 y = x1 - a/b*y1 y=x1a/by1

    ​ 以上过程完全可以用递归实现

    基准情形:b=0时

    ​ 有 a ∗ 1 + b ∗ 0 = g c d a*1 + b*0 = gcd a1+b0=gcd

    一步步返回x1,y1就可以求出最终的特解x,y

    import java.util.Arrays;
    
    public class ExEuclid {
        public static void main(String[] args) {
            long[] longs = exEuclid(7, 20);
            System.out.println(Arrays.toString(longs));
        }
        public static long[] exEuclid(long a,long b){
            long[] result = new long[2];
            //基准情况
            if(b==0){//a*1 + b*0 = gcd,x=1,y=0
                result[0] = 1;
                result[1] = 0;
                return result;
            }
            long[] tmp = new long[2];
            tmp = exEuclid(b,a%b);
            /*
                x = y1
    	        y = (x1 - a/b)*y1
             */
            result[0] = tmp[1];
            result[1] = tmp[0] - a/b*tmp[1];
            return result;
        }
    }
    
    

    求乘法逆元

    ​ 上面说了这么多,到底如何求乘法逆元呢?

    ed ≡ 1 mod ø(n)如何求d

    ​ 将上式换一种写法ed + kø(n) =1,是不是有一种熟悉的感觉,这不就是一种特殊的扩展欧几里得嘛。ø(n)已知,而e是自己选的与ø(n)互素的一个数,gcd(e,ø(n))=1。 d就相当于x,k就相当于y, 利用上面的扩展欧几里得算法就可以求出私钥d,当然也能求出k,但这不是我们关心的东西。

    最后

    ​ 终于是搞懂了扩展欧几里得算法,呼!

  • 1
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值