11 种加密 & 哈希算法的原理及其 Java 实现 - Go语言中文社区

11 种加密 & 哈希算法的原理及其 Java 实现


11 种加密 & 哈希算法的原理及其 Java 实现

一、目的

(1)通过对同一段明文分别进行DES、3DES、AES、PBE、CBC、IDEA、RSA、Caesar 8 种加密、以及 MD5、SHA-1、SHA-256 3 种哈希算法的实现,从而比较不同的加密 / 哈希算法的消耗时间,进而对它们的运行效率进行对比;

(2)学习 Java 中 javax.crypto.Cipher 类的原理,深入理解 JCE 框架的核心;

(3)对各种对称、非对称以及哈希算法的原理进行巩固复习,掌握它们实现的基本原理、密钥长度、实现机制、算法流程、应用环境、优缺点、安全性等基础知识。

二、运行环境

(1)处理器:Inter ® Pentium ® CPU 3825U @1.90 GHz;

(2)安装内存 (RAM):4.00 GB;

(3)系统类型:64 位操作系统;

(4)Windows 版本:Windows 7;

(5)运行平台:Eclipse Java EE IDE for Web Developers;
                          Version: Oxygen Release (4.7.0)。

三、基本原理及步骤

(I)各种加密算法的原理:

① DES 数据加密标准(Data Encryption Standard):

算法介绍

  1. 属于对称加密算法;
  2. 数据分组(64 位)用密钥(64 位;其中 56 位有效位,8 位校验位)加密;
  3. 算法公开,对密钥保护。

算法流程

  1. 根据用户输入,取得一个 64 位的密钥,然后进行等分、移位、选取和迭代形成一套 16 个加密密钥,分别提供每轮运算使用;
  2. 对 64 位明文分组 MM 进行操作,MM 经过初期置换 IPIP,置换为 m0{m_{0}}
  3. 在每一轮中,密码位移位,从密钥的 56 位中选出 48 位,通过一个扩展置换将数据右半边扩展成 48 位,并通过异或操作替代成新的 48 位;然后压缩至 32 位,并通过一个异或与左半边结合,其结果为右半边,原来的右半边成为左半边,该操作执行 16 次;
  4. 经过 16 轮迭代,左右部分合在一起进行一个末置换(数据整理),完成加密过程;
  5. 解密时同样使用此算法。

优点

  算法公开、计算量小、加密速度快、效率高。

缺点

  1. 如果双方都持有密钥,安全性无法保证;
  2. 密钥安全的保护成本高,管理困难。

破解方式

  暴力破解、穷举。

适用场景

  普通数据加密。

安全性

  低。

② 3DES(DES ede)(或称为Triple DES)——是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)的通称 :

算法介绍

  1. 三重 DES 加密算法;
  2. 每个数据块用三次 DES 加密;
  3. 是 DES 向 AES 过渡的加密算法。

算法流程

  1. 加密过程:C=Ek3(Dk2(Ek1(P))){rm{C = }}{{rm{E}}_{{k_3}}}{rm{(}}{{rm{D}}_{{k_2}}}{rm{(}}{{rm{E}}_{{k_1}}}{rm{(P)))}}
  2. 解密过程:P=Dk1(Ek2(Dk3(C))){rm{P = }}{{rm{D}}_{{k_1}}}{rm{(}}{{rm{E}}_{{k_2}}}{rm{(}}{{rm{D}}_{{k_3}}}{rm{(C)))}}

破解方式

  难度较大。

安全性

  较高。

③ AES 高级加密标准(Advanced Encryption Standard,AES):

算法介绍

  1. 属于对称加密算法;
  2. 基于排列置换算法;
  3. 易于软硬件实现;
  4. 属于分组密码体制;
  5. 用于取代原来的 DES。

算法流程

  1. 对数据进行 128 位(16 字节)的分组加密,每次对一组数据加密需要多轮;
  2. 输入密钥长度为:128、192 或 256,如果不够则补齐;
  3. 加密基本流程:
    1)生成各轮的扩展密钥,存于 key 数组中,包含用户的输入密钥和扩展密钥;
    2)将待加密数组与第一组密钥异或;
    3)最后一轮前的变换操作:
      SubBytes(state)——对数据进行 S 字节变换;
      ShiftRows(state)——进行行变换;
      MixColumns( state )——进行列混合变换;
      AddRoundKey( state,Keys [当前轮密钥组] )——与当前轮密钥异或。
    4)最后一轮变换操作
      invShiftRows(state)——进行反行变换;
      invSubBytes(state)——对数据进行反 S 字节变换;
      AddRoundKey( state, Keys [第一组] )——与第一组密钥进行异或。
  4. 解密流程:与加密相反。
  5. 分组模式:
    1)ECB(电码本模式):
      优点:简单、并行计算、误差不会传递;
      缺点:不能隐藏明文的模式、可能造成对明文的主动攻击。
    2)CBC(密码分组链接):
      优点:能抵抗主动攻击、安全性好于 ECB、适合传输较长报文、是 SSL,IPSec 的标准;
      缺点:不利于并行计算、有误差传递、需要初始化向量;
    3)CFB(密码反馈模式):
      优点:隐藏明文的模式、将分组密码转化为流模式、可以及时加密传送分组的数据;
      缺点:不利于并行计算、有误差传递、IVIV值唯一。
    4)OFB(输出反馈模式):
      优点:隐藏明文、将分组密码转化流模式、可以及时加密传送分组的数据;
      缺点:不利于并行计算、可能对明文产生主动攻击、误差传递。
    5)CTR(计数器模式):
      优点:并行计算、仅要求实现加密算法而无需解密算法、无需填充、可以作为流进行高效加密。
  6. 常用填充方式:
    NoPadding——不填充;
    ZerosPadding——0 填充;
    PKCS5Padding——每个填充都记录了填充的总数。

优点

  分组模式选择多,加密安全。

缺点

  1. 同 DES 类似,存在密钥管理问题;
  2. 曾遭受线性密码攻击、差分密码攻击。

安全性

  较高。

④ PBE(Password Based Encryption,基于口令加密):

算法原理

  PBE(Password Based Encryption,基于口令加密)是一种基于口令的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数、杂凑、多重加密等方法保证数据的安全性。

  PBE 算法在加密过程中并不是直接使用口令来加密,而是加密的密钥由口令生成,这个功能由 PBE 算法中的 KDF 函数完成。
在这里插入图片描述

算法流程

  KDF 函数的实现过程为:

  1. 将用户输入的口令首先通过“盐”(salt)的扰乱产生准密钥;
  2. 将准密钥经过散列函数,多次迭代后,生成最终的加密密钥;
  3. 密钥生成后,PBE 算法再使用对称加密算法对数据进行加密,可以选择 DES、3DES、RC5 等对称加密算法。

⑤ IDEA(国际数据加密算法):

算法介绍

  国际数据加密算法(IDEA)是上海交通大学教授来学嘉与瑞士学者 James Massey 联合提出的,它在 1990 年正式公布并得到增强。这种算法是在 DES 算法的基础上发展出来的,类似于三重 DES。发展 IDEA 也是因为 DES 密钥太短等缺点,IDEA 的密钥为 128 位,在今后若干年内应该是安全的。

算法特点

  类似于 DES,IDEA 算法也是一种分组加密算法,它设计了一系列加密轮次,每轮加密都使用从完整的加密密钥中生成的一个子密钥。与 DES 的不同之处在于,它在软件和硬件实现上同样快速。
  
  由于 IDEA 是在美国之外提出并发展起来的,避开了美国法律上对加密技术的诸多限制,因此,有关 IDEA 算法和实现技术的书籍都可以自由出版和交流,极大地促进了 IDEA 的发展和完善。

应用领域

  目前 IDEA 在工程中已有大量应用实例:

  1. PGP ( Pretty Good Privacy)使用 IDEA 作为其分组加密算法;
  2. 安全套接字层 SSL(Secure Socket Layer)将 IDEA 包含在其加密算法库 SSLRef 中;
  3. 基于 IDEA 的 Exchange 安全插件;
  4. IDEA 加密芯片;
  5. IDEA 加密软件包等。

⑥ RSA:

算法介绍

  1. 非对称加密;
  2. 密钥长度决定了其复杂度;
  3. 简单原理:公钥加密、私钥解密;
         私钥签名、公钥解密验证。

算法流程

  1. 随意选择两个大的质数 ppqqpp 不等于 qq,计算 N=p×qN = p × q
  2. 根据欧拉函数,求得 r=(p1)(q1)r = (p - 1)(q - 1)
  3. 选择一个小于 rr 的整数 ee,求得 ee 关于模 rr 的模反元素,命名为 dd(模反元素存在,当且仅当 eerr 互质);
  4. ppqq 的记录销毁;
  5. (N,e)(N,e) 是公钥,(N,d)(N,d) 是私钥。

优点

  原理简单。

缺点

  1. 密钥生成较为麻烦,受到素数产生技术的限制,因此难以做到一次一密;
  2. 分组长度太大,不利于数据格式标准化;
  3. 加密难度大。

应用场景

  1. 数字签名;
  2. 公钥加密;
  3. 防止数据篡改;
  4. 用于通讯领域较多。

安全性

  高。

⑦ 凯撒密码:

算法介绍

  作为一种最为古老的对称加密体制,凯撒密码在古罗马的时候就已经很流行了。它的基本思想是:通过把字母移动一定的位数来实现加密和解密。例如,如果字母的位数是 3,明文字母 B 就变成了密文的 E,依次类推,X 将变成 A,Y 变成 B,Z 变成 C……由此可见,位数就是凯撒密码加密和解密的密钥。

算法流程

  一般化的凯撒加密算法为: C=E(k,P)=(P+k)mod26C = E(k, P) = (P + k) mod 26

  一般化的凯撒解密算法为: P=D(k,C)=(Ck)mod26P = D(k, C) = (C - k) mod 26

  1. 由于字母表中共有 26 个字符,因此移位前先将移动的位数 (keykey) 和 26 取模。将字符加上一个正整数即代表在字母表中右移多少位;
  2. 如果移动的位数是负值,则代表在字母表中左移多少位。尽管在移动之前已经将移动的位数和 26 取模,但通过这种方式实现右移或左移仍可能发生超界;
  3. 移位后进行判断,如果向左超界(c <‘a’)则增加 26;向右超界(c >‘z’)则减去 26。

(II)各种 Hash 算法的原理:

① MD5:

算法介绍

  1. 信息摘要算法;
  2. 压缩性:任意长度的数据,可以算出固定长度;
  3. 容易计算:从原数据计算 MD5 很容易;
  4. 抗修改性:对原数据修改 1 个字节,MD5 值的变化都很大;
  5. 强碰撞性:找一个具有相同 MD5 值的数据(伪造)比较困难;
  6. 具有不可逆性。

算法流程

  按照 512 位分组处理,每一个分组分为 16 个 32 位子分组,处理后输出 4 个 32 位分组,将这 4 个分组级联后生成 128 位散列值。

优点

  简单、难以伪造。

缺点

  具有潜在的冲突;有破解的案例。

应用场景

  1. 登录密码保护;
  2. 防止文件篡改;
  3. HTTP 传输内容加密防篡改;
  4. 用于数字签名。

安全性

  较高。

② SHA1:

算法介绍

  1. 属于消息摘要算法;
  2. 用于签名算法,保护数据的完整性;
  3. 算法不可逆;
  4. 消息算法:512 位。

算法流程

  把原始信息变换成位(二进制)字符串,5 个步骤计算:
  1)补位:消息满足长度在对 512 取模后余数是 448,否则补位;
  2)补长度:原始数据长度补到补位操作的后面,如果大于 512,补成 512 的倍数;
  3)使用常量和相关的函数;
  4)计算消息摘要。

优点

  保密性强。

缺点

  效率较低;难度大。

应用场景

  1. 数字签名;
  2. 数据完整性保护。

安全性

  高。

(III)javax.crypto.Cipher 类的原理

  基于 Java 中的 javax.crypto.Cipher 类,可以实现各种算法的加密和解密功能,该类是 JCE 框架的核心。

  1. 与所有的引擎类一样,可以通过调用 Cipher 类中的 getInstance 静态工厂方法得到 Cipher 对象:
     public static Cipher getInstance(String transformation,String provider);

  参数 transformation 是一个字符串,它描述了由指定输入产生输出所进行的操作或操作集合。它包含密码学算法名称,比如 DES,也可以在后面包含模式和填充方式。如果没有指定模式或填充方式,就使用特定提供者指定的默认模式或默认填充方式。

  当以流密码方式请求以块划分的 Cipher 时,可以在模式名后面跟上一次运算需要操作的 bit 数目。如果没有指定数目,则使用提供者指定的默认值。

  通过 getInstance 得到的 Cipher 对象使用下列四个模式之一进行初始化,这四个模式在 Cipher 类中被定义为 final integer 常数,可以使用符号名来引用这些模式:

    ENCRYPT_MODE, 加密数据;
    DECRYPT_MODE, 解密数据;
    WRAP_MODE, 将一个 Key 封装成字节,可以用来进行安全传输;
    UNWRAP_MODE, 将前述已封装的密钥解开成 java.security.Key 对象。

  每个 Cipher 初始化方法使用一个模式参数 opmod,并用此模式初始化 Cipher 对象。此外还有其他参数,包括密钥 key、包含密钥的证书 certificate、算法参数 params 和随机源 random。

  加密和解密必须使用相同的参数。当 Cipher 对象被初始化时,它将失去以前得到的所有状态,即初始化 Cipher 对象与新建一个 Cipher 实例后将它初始化是等价的。

  1. 调用 doFinal()方法完成单步的加密或解密数据:

  在多步加密或解密数据时,首先需要一次或多次调用 update 方法,用以提供加密或解密的所有数据。

  如果还有输入数据,多步操作可以使用 doFinal 方法之一结束。如果没有数据,多步操作可以使用 doFinal 方法结束。

  如果在 transformation 参数部分指定了 padding 或 unpadding 方式,则所有的 doFinal 方法都要注意所用的 padding 或 unpadding 方式。

  调用 doFinal 方法将会重置 Cipher 对象到使用 init 进行初始化时的状态,也就是说,Cipher 对象被重置,使得可以进行更多数据的加密或解密。这两种模式可以在调用 init 时进行指定。

3、wrap 密钥必须先使用 WRAP_MODE 初始化 Cipher 对象,然后调用方法:

    public final byte[] wrap(Key key);

  如果将调用 wrap 方法后的密钥字节提供给 unwrap 的人使用,必须向接收者发送额外信息。

  (1)密钥算法名称:

  调用 Key 接口提供的 getAlgorithm 方法:

      public String getAlgorithm();

  (2)包裹密钥的类型:

     (Cipher.SECRET_KEY,Cipher.PRIVATE_KEY,Cipher.PUBLIC_KEY)
  1. SunJCE 提供者实现的 Cipher 算法参数:

  (1)采用 CBC、CFB、OFB、PCBC 模式的 DES、DES-EDE 和 Blowfish算法使用初始化向量 IVIV 作为参数。可以使用 javax.crypto.spec.IvParameterSpec 类并使用给定的 IVIV 参数来初始化 Cipher 对象。

  (2)PBEWithMD5AndDES 使用的参数是一个由盐值和迭代次数组成的参数集合。可以使用 javax.crypto.spec.PBEParameterSpec 类并利用给定盐值和迭代次数来初始化 Cipher 对象。

  (3)Cipher 中的某些 update 和 doFinal 方法允许调用者指定加密或解密数据的输出缓存。此时,保证指定的缓存足够大以容纳加密或解密运算的结果是非常重要的,可以使用 Cipher 的以下方法来决定输出缓存应该有多大:

    public int getOutputSize(int inputLen)。

四、数据记录、仿真及设计

  对于待验证的所有 11 种加解密以及哈希算法,为保证时间效率计算的一致性,因此下面均使用相同的明文 “In doing we learn.” 对其进行加密,具体结果分析如下:

(一)DES 算法的结果分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  计算 10 次 DES 加密的时间消耗平均值,可以得出,在本系统平台上,DES 算法的平均时间消耗约为 1826 ms。

(二)3DES 算法的结果分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  计算 10 次 3DES 加密的时间消耗平均值,可以得出,在本系统平台上,3DES 算法的平均时间消耗约为 2021 ms。

(三)AES 算法的结果分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  计算 10 次 AES 加密的时间消耗平均值,可以得出,在本系统平台上,AES 算法的平均时间消耗约为 1941 ms。

(四)PBE 算法的结果分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  计算 10 次 PBE 加密的时间消耗平均值,可以得出,在本系统平台上,PBE 算法的平均时间消耗约为 1376 ms。

(五)CBC 算法的结果分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  计算 10 次 CBC 加密的时间消耗平均值,可以得出,在本系统平台上,CBC 算法的平均时间消耗约为 1318 ms。

(六)IDEA 算法的结果分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  计算 10 次 IDEA 加密的时间消耗平均值,可以得出,在本系统平台上,IDEA 算法的平均时间消耗约为 2328 ms。

(七)RSA 算法的结果分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  计算 10 次 RSA 加密的时间消耗平均值,可以得出,在本系统平台上,RSA 算法的平均时间消耗约为 2288 ms。

(八)MD5 算法的结果分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  计算 10 次 MD5 哈希算法的时间消耗平均值,可以得出,在本系统平台上,MD5 算法的平均时间消耗约为 97 ms。

(九)SHA1 算法的结果分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  计算 10 次 SHA-1 哈希算法的时间消耗平均值,可以得出,在本系统平台上,SHA-1 算法的平均时间消耗约为 117 ms。

(十)SHA256 算法的结果分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  计算 10 次 SHA-256 哈希算法的时间消耗平均值,可以得出,在本系统平台上,SHA-256 算法的平均时间消耗约为 145 ms。

(十一)凯撒加密算法的结果分析

  n = 5:

在这里插入图片描述
  n = 8 :

在这里插入图片描述
  n = 16:

在这里插入图片描述
  n = 21:

在这里插入图片描述
  计算 10 次 Caesar 加密的时间消耗平均值,可以得出,在本系统平台上,Caesar 算法的平均时间消耗约为 2 ms。

  综合上述各种算法的运行时间,统计出它们分别的效率对比,如图所示:

在这里插入图片描述

五、测试结果及分析

①结果分析

  通过上面的统计结果可以大致看出:

  (1)针对各种加密算法,在本运行平台上的消耗时间为:

         IDEA > RSA > 3DES > AES > DES > PBE > CBC > Caesar

  (2)针对各种 Hash 算法,在本运行平台上的消耗时间为:

         SHA-256 > SHA-1 > MD5

②总结

  1. 对称算法:
      密钥管理:比较难,不适合互联网,一般用于内部系统;
      安全性:中;
      速度:快好几个数量级(软件加解密速度至少快 100 倍,每秒可以加解密几兆比特的数据),适合大数据量的加解密处理。

  2. 非对称算法:
      密钥管理:密钥容易管理;
      安全性:高;
      速度:慢,适合小数据量加解密或数据签名。

  3. Hash 算法:
      MD5 输出 128 bit、SHA1 输出 160 bit、SHA256 输出 256 bit。

  SHA-1 是 160 位的哈希值,而 SHA-2 是组合值,有不同的位数,其中最受欢迎的是 256 位。

  因为 SHA-2 有多种不同的位数,导致这个名词有一些混乱。但无论是“SHA-2”、“SHA-256” 或 “SHA-256 位”,其实都是同一种加密算法。SHA-224、SHA-384 或 SHA-512 表示 SHA-2 的二进制长度。

  SSL 行业选择 SHA 作为数字签名的散列算法,但随着互联网技术的提升,SHA-1 的缺点越来越突显。在 SHA-2 成为了新的标准之后,签发的 SSL 证书必须使用该算法签名。

  安全性方面,SHA-256 的安全性最高,但是耗时要比其他两种多很多。MD5 相对较容易破解,因此,SHA-1 是这三种中性能较好的一款哈希算法。

③遇到的问题及解决方法:

i)字符串编码出现乱码

  一开始,我在编写加密函数时,由于对字节数组 byte[] 以及 String 对象之间的转化不当,导致了程序加密的输出结果呈现乱码,有许多问号 ?? 等特殊字符,这显然不符合加密结果的要求,如图所示:

在这里插入图片描述
在这里插入图片描述

  之后,我尝试在调用 toString 方法时,将输出结果用参数 “utf-8” 强制转换,但效果不佳。在查阅了相关的资料后,我发现可以编写一个函数,将结果用 Base64 编码来表示:

    public static String encryptBase64(byte[] key) throws Exception {
            return (new BASE64Encoder()).encodeBuffer(key);
    }

  这样一来,就可以将加密的编码方式转换为 Base64,此时的加密输出结果也更加易于表示、传输与解密。

ii)com.sun.crypto.provider.SunJCE() 报错

  报错内容:

Access restriction: The constructor SunJCE() is not accessible due to restriction on required library C:Program FilesJavajre7libextsunjce_provider.jar

  查找相关文档的解释说明后,我发现该错误是由于

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/carol980206/article/details/96705859
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢