密码学:RSA加密算法详解

密码学:RSA加密算法详解RSA算法一直是最广为使用的”非对称加密算法”。本文旨在说明RSA加密算法的原理及实现,而其相关的数学部分的证明则不是本文内容。

大家好,又见面了,我是你们的朋友全栈君。

概述

  本文旨在说明RSA加密算法的原理及实现,而其相关的数学部分的证明则不是本文内容。


版权说明

著作权归作者所有。

商业转载请联系作者获得授权,非商业转载请注明出处。

作者:Q-WHai

发表日期: 2016年2月29日

本文链接:http://blog.csdn.net/lemon_tree12138/article/details/50696926

来源:CSDN

更多内容:分类 » 数据加密与信息安全


RSA简介

  1977年,三位数学家Rivest、Shamir 和 Adleman 设计了一种算法,可以实现非对称加密。这种算法用他们三个人的名字命名,叫做RSA算法。从那时直到现在,RSA算法一直是最广为使用的”非对称加密算法”。毫不夸张地说,只要有计算机网络的地方,就有RSA算法。

                                                                                   — 摘自网络


数学背景

  此部分旨在补充本文的完整性。如果说你已经了解,或是不想了解此部分内容。那么可以直接跳过此部分的阅读。

  虽说只是补充说明(只能是补充的原因是因为博主的数学也是比较差的-_-!!!),但是此部分的内容却是相当重要的。博主还是希望可以重新阅读一下此部分。

1.互质

  从小学开始,我们就了解了什么是质数。互质是针对多个数字而言的,如果两个正整数,除了1以外,没有其他公因子,那么就称这两个数是互质关系(注意,这里并没有说这两个数一定是质数或有一个为质数。比如15跟4就是互质关系)。以下有一些关于质数与互质的性质:

  • 质数只能被1和它自身整除
  • 任意两个质数都是互质关系
  • 如果两个数之中,较大的那个数是质数,则两者构成互质关系
  • 如果两个数之中,较小的那个数是质数,且较大数不为较小数的整数倍,则两者构成互质关系
  • 1和任意一个自然数是都是互质关系
  • p是大于1的整数,则p和p-1构成互质关系
  • p是大于1的奇数,则p和p-2构成互质关系

2.欧拉函数

  欧拉函数是求小于x并且和x互质的数的个数。其通式为:φ(x) = x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn)

  其中p1, p2……pn为x的所有质因数,x是不为0的整数。看到这里是不是有一些头疼,太理论的东西的确不够具象。我们且不去理会后面公式计算与论证,因为已经超出本文的范围了。就前一句来说说吧,欧拉函数是求小于x并且和x互质的数的个数。这里我可以列举一个例子:

  令x = 16,那么x的所有质因数为:φ(16) = 16 * (1 – 1/2) = 8

  我们也可以枚举出所有比16小,且与16互质的数:1, 3, 5, 7, 9, 11, 13, 15

  现在也给出部分欧拉函数的性质:

  • 若n是素数p的k次幂,密码学:RSA加密算法详解,因为除了p的倍数外,其他数都跟n互质
  • 欧拉函数是积性函数——若m,n互质,密码学:RSA加密算法详解
  • 当n为奇数时,密码学:RSA加密算法详解
  • p是素数,密码学:RSA加密算法详解,φ(p)称为p的欧拉值

  欧拉函数更多参考请见这里的链接


3.模反元素

定义:如果两个正整数a和n互质,那么一定可以找到整数b,使得 ab-1 被n整除,或者说ab被n除的余数是1。

关于模反元素的求解,使用的是朴素的解法。如果读者想要更进一步了解的话,请自行搜索其他解法(比如:辗转相除法、欧几里德算法)。


RSA原理

  在RSA原理之前,我想还是有必要了解一下非对称加密算法的加密跟解密过程。下面就是一幅非称加密算法的流程图。

  密码学:RSA加密算法详解

  在此可以看到,非对称加密是通过两个密钥(公钥-私钥)来实现对数据的加密和解密的。公钥用于加密,私钥用于解密。对于非对称的加密和解密为什么可以使用不同的密钥来进行,这些都是数学上的问题了。不同的非对称加密算法也会应用到不同的数学知识。上面也对RSA中使用的数学问题做了一个小小的介绍。现在就来看看RSA算法是怎么来对数据进行加密的吧,如下是一幅RSA加密算法流程及加密过程图。

  密码学:RSA加密算法详解


RSA应用

1. 实例模型

  就以上图中的Bob和Alice来举例吧。

  现在Alice通过密钥生成器生成了一对密钥(公钥-私钥)。只把公钥对外公开了。并说,你有什么要跟我说的,就用模幂运算和公钥加密后发给我吧。

  此时,Bob已经获得了Alice发布的公钥。使用模幂运算对明文进行了加密,就把加密后的密文发送给了Alice。

  Alice获得Bob发来的密文并没有使用公钥对密文进行解密,并获得了明文。因为解密过程需要使用的密钥是私钥。


2. RSA算法实现

  下面的代码只是根据RSA算法的定义,使用Java开发语言实现。且这里只是展示了一些关键步骤,完整过程可以参见下面的源码下载文档。

public class RSA {    
    /**
     * 获得(公/私)密钥
     */
    public final Map<String, RSAKey> getCipherKeys() {
        ...
        int[] primes = getRandomPrimes(2);
        int modulus = modulus(primes[0], primes[1]);
        int euler = euler(primes[0], primes[1]);
        int e = cipherExponent(euler);
        int inverse = inverse(euler, e);
        publicKey.setExponent(e);
        publicKey.setModulus(modulus);
        privateKey.setExponent(inverse);
        privateKey.setModulus(modulus);
        ...
    }
    
    /**
     * 加密
     */
    public int encode(int plaintext, RSAPublicKey key) {
        return modularPower2(plaintext, key.getExponent(), key.getModulus());
    }
    
    /**
     * 解密
     */
    public int decode(int chipertext, RSAPrivateKey key) {
        return modularPower2(chipertext, key.getExponent(), key.getModulus());
    }

    // 随机生成count个素数
    private final int[] getRandomPrimes(int count) {
        ...
        try {
            primeLabels = FileReadUtils.readLines("./data/prime_table");
        } catch (IOException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < primes.length; i++) {
            primes[i] = Integer.parseInt(primeLabels.get(indexs.get(i)));
        }

        return primes;
    }

    // 计算公共模数
    private final int modulus(int p, int q) {
        return p * q;
    }

    // 计算欧拉数
    private final int euler(int p, int q) {
        return (p - 1) * (q - 1);
    }

    // 计算加密指数
    private final int cipherExponent(int euler) {
        Random random = new Random();

        int e = 7;
        do {
            e = random.nextInt(euler - 1);
        } while (!isCoprime(e, euler) || e <= 1);

        return e;
    }

    // 判断两个数互素
    private final boolean isCoprime(int number1, int number2) {

        int sqrt = (int) Math.sqrt(Math.max(number1, number2));
        for (int i = 2; i <= sqrt; i++) {
            if (number1 % i == 0 && number2 % 2 == 0) {
                return false;
            }
        }

        return true;
    }

    // 计算“模的逆元”
    // (d * e) ≡ 1 mod euler
    private final int inverse(int euler, int e) {
        ...
        while (flag) {
            q = m[2] / n[2];
            for (int i = 0; i < 3; i++) {
                temp[i] = m[i] - q * n[i];
                m[i] = n[i];
                n[i] = temp[i];
            }
            if (n[2] == 1) {
                if (n[1] < 0) {
                    n[1] = n[1] + euler;
                }
                return n[1];
            }
            if (n[2] == 0) {
                flag = false;
            }
        }
        return 0;
    }
    
    // 模幂运算
    private final int modularPower(int base, int e, int modular) {
        int result = 1;
        do {
            if (isOdd(e)) {
                result = (result * (base % modular)) % modular;
                e -= 1;
            } else {
                base = (base * base) % modular;
                e /= 2;
            }
        } while (e > 0);
        
        result %= modular;
        
        return result;
    }
}

RSA算法判别

RSA算法优点

  1. 不需要进行密钥传递,提高了安全性
  2. 可以进行数字签名认证

RSA算法缺点

  1. 加密解密效率不高,一般只适用于处理小量数据(如:密钥)
  2. 容易遭受小指数攻击


Ref

  1. 《算法导论》
  2. 《算法的乐趣》
  3. 《深入浅出密码学》
  4. RSA算法原理(一) — 阮一峰
  5. RSA算法原理(二) — 阮一峰
  6. 逆元详解 — ACdreamers
  7. JAVA实现扩展欧几里德算法求乘法逆元

源码下载

http://download.csdn.net/detail/u013761665/9439852

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/131028.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 怎么保存退出 vim 编辑

    怎么保存退出 vim 编辑保存命令按ESC键跳到命令模式,然后::w保存文件但不退出vim:wfile将修改另外保存到file中,不退出vim:w!强制保存,不推出vim:wq保存文件并退出vim:wq!强制保存文件,并退出vimq:不保存文件,退出vim:q!不保存文件,强制退出vim:e!放弃所有修改,从上次保存文件开始再编辑本文来自ij2155的CSDN博客…

  • Win10共享打印机提示0x0000011b错误代码的解决方法[通俗易懂]

    Win10共享打印机提示0x0000011b错误代码的解决方法[通俗易懂]首先是在共享打印机的主机Windows是更新kb5005565这个补丁所导致的,那么我们在控制面板-卸载程序里卸载掉2021-09-15Windows更新的补丁KB5005565后重启电脑就好了。然后禁止Win10更新操作方法:鼠标右键“win”图标在弹出的菜单栏中选择“运行”选项,打开运行窗口后输入“services.msc”, 在打开的窗口中找到“windowsUpdate”启用选项,并双击打开, 在弹出的小窗口中的启动类型选项处点击选择“禁用”,点击“确定”另外win11出现的错误代.

  • python fileinput_python模块fileinput

    python fileinput_python模块fileinput在python脚本语言中的fileinput模块可以对一个或多个文件的内容进行迭代,编历操作.常用的函数:fileinput.input()#读取文件的内容fileinput.filename()#文件的名称fileinput.lineno()#当前读取行的数量fileinput.filelineno()#读取行的行号fileinput.isfir…

  • 安装vmware虚拟机步骤_如何安装vmware虚拟机

    安装vmware虚拟机步骤_如何安装vmware虚拟机一、基础介绍VMWare虚拟机软件是一个“虚拟PC”软件,它使你可以在一台机器上同时运行二个或更多Windows、DOS、LINUX系统。与“多启动”系统相比,VMWare采用了完全不同的概念。多启

  • COM组件原理_Com组件

    COM组件原理_Com组件在COM中,接口就是一个象类,每个接口有一个接口ID(uuid)。一个COM组件通常是连续继承下来的类,比如IUNknow->IDispath->IXX->CXX。这就形成了一个COM组件,当然组件一般是一个钻石继承的样子,这里为了简化原理把他们当成一个串形继承下来。每个COM组件都有一个CLSID(uuid),这个CLSID是注册的时候写进注册表的。这样就可以通过查询注册表中的CLSID

  • win10无法生成常规子目录下的列表_windows无法更新怎么办

    win10无法生成常规子目录下的列表_windows无法更新怎么办1.问题背景Win10只要系统安装好之后会自动生成一系列的系统文件夹,如下:这类文件夹比较特殊,它们比普通文件夹多一个“位置”选项卡,如默认的“下载”文件夹,edge和chrome浏览器会默认下载到这个文件夹,所以新系统拿到手之后,往往都需要将这些文件夹修改到其他硬盘上,不然C盘会因为下载文件的不断增多而变得异常臃肿:如果这个时候你手抖了,需要修改……………

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号