zoukankan      html  css  js  c++  java
  • 理解RSA算法

    一、概述

    RSA算法是1977年由Ron Rivest、Adi Shamir 和 Leonard Adleman三人组在论文A Method for Obtaining Digital Signatures and Public-Key Cryptosystems提出的公钥加密算法。由于加密与解密使用不同的秘钥,从而回避了秘钥配送问题,还可以用于数字签名。该算法的诞生很大程度上有受到了论文New Directions in Cryptography(由Whitfield Diffie和Martin Hellman两人合作发表)的启发,关于RSA诞生背后的趣事见RSA 算法是如何诞生的

    原论文可以说思路非常清晰、浅显易懂,是学习该算法非常不错的英文资料。原文首先梳理了公钥加密系统和数字签名的特性和需满足的要求(这部分是实际上是借鉴了Whitfield Diffie和Martin Hellman的思想);然后阐述如何利用不同的加密秘钥和解密秘钥实现加解密流程,这是RSA算法工作的核心部分;接着介绍其背后的数学原理并证明算法的正确性,主要涉及基础数论知识(例如欧拉函数,费马定理,欧拉定理等);为了使算法更具有操作性,还介绍了如何利用"反复平法"算法进行快速的计算幂取模,从而快速的进行加解密运算,以及算法中涉及到其他参数选取(例如大素数p,qp,q选取,ee和dd的选取和计算);同时也用一个简单的小实例模拟算法的流程;最后一个重要的话题是讨论该算法的安全性,通过考虑不同方法尝试破解该算法,并从计算量的角度解释了破解该算法的困难程度,以及其他的细节bla bla bla。。。。

    所以原论文几乎是比较全地阐述了RSA算法的方方面面且不失可读性,非常值得借鉴。一些中文书籍也对该算法做了浅显易懂的解释,比如密码编码学与网络安全原理与实践图解密码技术两本书的相关章节,都是很好的学习资料。

    二、公钥加密系统

    公钥加密系统主要特点是采用不同的加密秘钥和解密秘钥。在该系统中每个用户均生成自己的加密秘钥和解密秘钥,其中加密秘钥需公开出去,任何人都可以获得,加密秘钥也称为公钥;解密秘钥必须保密妥善保管,解密秘钥也称为私钥。在进行通信的时候,发送方先用接收方的加密秘钥(也就是公钥)加密消息,得到密文消息,发送给接收方;接收方收到消息用自己的解密秘钥(也就是私钥)可以解密得到明文。采用这样的加解密方式从而规避了传统加密系统中秘钥配送问题。

    在密码学中,加密算法往往都是公开的,尝试通过保密加密算法来获得加密安全性的做法都是不值得推荐的(此所谓隐蔽式安全)。事实上,发明一个可行的加密算法并非易事,将其公之于众经受时间和广大使用者的检验是很好的做法。加密算法在秘钥的配合使用下进行加密和解密。因此在加密算法是公开的前提下,保证加密的安全依赖于秘钥的安全性。

    将加密过程(encryption)和解密过程(decryption)分别视为一种处理程序,分别用EE和DD表示表示。明文消息和密文消息分别用MM和CC表示。则公钥加密系统有如下四种特性:

    (a)对于加密后的密文C=E(M)C=E(M),对应的解密程序能够处理得到明文:D(C)=D(E(M))=MD(C)=D(E(M))=M。

    (b)加密过程EE和解密过程DD是容易计算的。

    (c)由公开的加密程序EE不能轻易的得到解密程序DD,这样可以保证由EE加密的消息只能由DD解密。

    (d)对明文消息先解密处理在做加密处理仍可以得到明文,也即保证逆向处理的可行性:E(D(M))=ME(D(M))=M。

    特性(a)保证了加密的原始目的,如果加密后的密文不能由接受者解密还原回明文,那彼此就不能正常通信了。特性(a)和(b)在传统的对称加密系统中也是成立的。特性(d)用于数字签名,之所以能够对明文进行解密处理这实际上并不奇怪:抛开加密与机密的概念,EE和MM实际上就是一个从输入到输出的映射,明文和密文的概念是站在人的立场行划分的,对于计算机,无论是明文还是密文,都是比特序列,并没有其他任何差别,因此对明文做加密无非是进行一次函数运算。

    三、秘钥生成与加密解密流程

     接下来的问题在于Bob一定能够解密得到明文MM吗?其原理何在呢?答案是肯定的,其原理这正是下一节需要解释的内容。

    四、数学原理

    五、一个具体的实例

     

    六、更多的细节

    以上内容大致解释了该算法的流程和原理,但实际上还有很多的细节值得思考,比如加解密如何快速计算幂取模,p,qp,q两个大素数如何有效选取,模反元素dd如何计算等等,这些细节的处理的对该算法的实践性很重要。

    1、快速幂取模算法

    加密和解密过程实际上都是幂取模的操作,也即是计算:abmodnabmodn。实际应用中各参数都是极大的整数,能够找到一种高效的算法呢?

    确实有一种算法能够比较高效计算幂取模,称为“反复平方”算法,在算法导论中也有描述该算法。其算法流程如下:

    反复平方法的Demo实现:

    复制代码

        public static long doModularExponentiation(long a, long b, long n) {
            long digit = Long.toBinaryString(b).length();// 得到b的二进制表示位数
            long mask = 1 << (digit - 1);
            long remainder = 1;
            for (long i = digit - 1; i >= 0; i--) {
                remainder = (remainder * remainder) % n;
                if (mask == (b & mask)) {// 当该位为1时,需要补充考一次a
                    remainder = (remainder * a) % n;
                }
                mask >>= 1;
            }
            return remainder;
        }

    复制代码

     

    复制代码

    100110101000011001
    100000000000000000
     10000000000000000
      1000000000000000
       100000000000000
        10000000000000
         1000000000000
          100000000000
           10000000000
            1000000000
             100000000
              10000000
               1000000
                100000
                 10000
                  1000
                   100
                    10
                     1

    复制代码

    2、挑选大素数和素数测试

    3、挑选e和计算d

     

    复制代码

        public static long[] gcdExt(long a,long b){  
            long ans;  
            long[] result=new long[3];  
            if(b==0)  
            {  
                result[0]=a;  
                result[1]=1;  
                result[2]=0;  
                return result;  
            }  
            long [] temp=gcdExt(b,a%b);  
            ans = temp[0];  
            result[0]=ans;  
            result[1]=temp[2];  
            result[2]=temp[1]-(a/b)*temp[2];  
            return result;  
        } 

    复制代码

    七、数字签名

    数字签名是纸质签字的电子化。

    数字签名涉及两个问题:首先消息的接受者要能够确认消息来源,也就是确认该消息确实是所期望的人发送的;其次接受者也能够说服第三方来验证此消息确实是签名者发送的而并非是其他人伪造的签名,这样可以反驳发送者的否认行为。数字签名必须同时是消息依赖(能够识别篡改)和签名人依赖的。数字签名其重要意义在于特定的签名者与特定的消息绑定在一起。

    数字签名依赖于特性(d),加密算法会作用在未加密的明文消息上,其实就是加密过程的逆向使用。

    所以签名SS实际上就是由如下规则计算得出:

    S=D(M)S=D(M)

    这样Bob将这个数字签名发送给Alice,Alice可以根据Bob的公钥,验证确实是Bob签名的,同时,Alice也可以让第三方来验证这个签名,因为这个签名只能由Bob的私钥计算得出,所以Alice和别人不能伪造签名,因此Bob也就无法否认。

    八、破解

    由于秘钥生成过程中,只对外公开公钥对(e,n),所以破解者只能尝试从这两个信息试图去计算得出私钥(d,n)。

    破解RSA算法可以从如下几个方面做尝试:

    (1)素因子分解n

    (2)在不分解n的前提下计算ϕ(n)

    (3)在不分解nn和不计算ϕ(n)的前提下,暴力破解d

    然而以上问题并不容易,都没有十分高效的算法求解。

    理论上,只要秘钥空间是有限的,花费大量计算和大量时间都是可以破解的,然而只要秘钥长度选取足够,在现实的时间破解该算法变得不太可能,因此RSA的安全性其实是在讨论一个时效性的问题。随着硬件计算速度的升级,以前被认为足够安全的秘钥位数会被逐渐攻破,不得不进一步增加秘钥的长度,因此RSA算法的秘钥长度普遍比对称加密和椭圆曲线加密的秘钥长度更长。也就是说加密算法的安全等级并非完全取决于秘钥的长度,与加密算法本身的特性和原理有很大的关系。

    九、其他

    由于对公钥的获取过程可能会存在中间人攻击,导致收到的公钥不是对方的公钥而是中间人自己的公钥,对消息的机密性造成威胁。为避免这样中间人攻击,目前普遍采用公钥认证的方式,即由权威认证机构颁布公钥证书,将公钥的信任问题交由可信度更高认证机构(CA)去核实,而认证机构本身的可信度由公信力作为担保。

    RSA公钥加密算法在运算速度上比对称加密慢,因此实际运用中并不会用来真正加密消息,而是用作数字签名和或者在混合密码系统中与对称加密配合使用。

    在混合密码系统中组合使用对称加密和公钥加密算法:

    (1)发送者产生临时秘钥,称为会话秘钥,用对称加密的算法加密消息。

    (2)发送者用公钥加密算法配合接受者的公钥加密会话秘钥,然后加密后的消息与加密后的会话秘钥组合发送给接受者。

    (3)接受者分理出加密后的会话秘钥,并用自己的私钥解密处会话秘钥,然后用会话秘钥在解密加密消息。

    十、References

    1、A Method for Obtaining Digital Signatures and Public-Key Cryptosystems

    2、密码编码学与网络安全原理与实践

    3、图解密码技术

  • 相关阅读:
    Java StringBuffer 和 StringBuilder 类
    Java String 类
    Java Character 类
    windows server R2 搭建ftp服务
    虫师的使用经验
    Linux 使用NC命令监听本地端口
    MYSQL让别人远程访问自己的数据库
    crontab
    tomcat日志切割脚本
    测试分布式部署页面sso
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13312637.html
Copyright © 2011-2022 走看看