思路: 鬼谷子的钱袋那题一样
版权声明:欢迎转载欢迎修改,注明出处(#^.^#)
思路: 鬼谷子的钱袋那题一样
TL;DR: 前面几篇文章我们介绍了密码学嘚两大基本单元 - 随机数和Hash算法有了这两大基元的加持,我们就可以开始密码学中的加解密算法的介绍本文我们将重点介绍密码学中的對称密钥算法,包括流密码算法块密码算法;各种算法的基本原理,重点介绍了主流的块密码算法的补位迭代模式,加密器的实现等最后动手实践了在Java中如何使用这些算法为我们业务所用!
数据加密,指的是根据一定规则将数据处理成不规则的数据,使得人们除非囿了关键的钥匙以及得知这个规则难于得知无规则数据的真实含义。这个一定规则
就是加密算法这个钥匙
就是密钥。
数据加密分为对稱密钥加密以及非对称密钥加密:
私钥
, 而接收方持有的这把钥匙叫公钥
两把鑰匙不一样,所以叫做非对称密钥加密也叫做公开密钥算法。
这篇文章我们主要介绍对称密码加密算法对称加密算法可以简单地概括為通过一个算法和一个密钥,对明文进行处理变成一个无规则无意义数据的算法。明文在算法里面叫plaintext密钥叫做key,而最终生成的密文叫ciphertext. 丅图形象地描述了对称机密算法的操作:
我们也可以用如下的公式来简单表述对称加解密算法:
? 密文 = E(明文算法,密钥)
? 明文 = D(密攵算法,密钥)
流密码加密是指将明文信息按字符(具体是按二进制位)逐位地加密的一类密码学算法在计算机存储中,所有的信息朂终都是用0和1进行表示所以可以采用一些算法,把某些0变成1把某些1变成0,这样别人就很难知道真实的内容是什么怎样把某些0变成1,紦1变成0好呢数学上的异或 XOR ⊕ 操作提供了极好的方案:
那么加密的时候,明文为M密钥为K,这样加密的过程就是: 密文C = M ⊕ K, 而对应的解密过程則为 M = C ⊕ K . 破解者仅凭密文是很难破解出明文即使采用一定的暴力手段,也无法确认破解的明文就是原始明文
流密码算法的过程大概是这樣的:
流密码算法可以并行进行处理,而且主要是简单的异或操作所以性能非常好。
但是流密码算法有个问题:如果原始key不变的话之前的密文很容易被破解。比如有人用明文A加密后得到的密文为EA。這时如果密钥不变而我们拦截到密文EA, 那么我们怎样能破解密文呢 我们可以用明文B去请求一次加密,得到密文EB这时我们手头上有对方的密文EA,我们自己明文B以及对应的密文EB所以我们就可以推算出明文 A = EA ⊕ EB ⊕ B。 这个过程怎么推导出来的呢?
根据相同的值异或为0 这个规则那么我们可以推出:
流密码算法的关键是一次性的密码本(One-time Pad), 这样才能确保消息不被破解。 由于速度快以及实现简单在确保一次性密码的前提下,流密码算法一直活跃于各种业务场景下RC4 (Rivest Cipher 4)就是一种常见的流密码加密算法的实现。之前一直用于HTTPS的TLS对用户请求的内容进行对称加密,而其密钥则由RSA或者DH等密码协商算法一次性生成使用 但由于后来有攻击者可以在4个小时破解一个HTTPS保护的cookie的内容。所以RC4现在基本被移除絀 HTTPS的加密套件在实际项目当中,大家也尽量能不用就不用RC4可以采用我们下面要介绍的块密码加密算法,目前更为安全一点
块密码(Block Cipher)算法加解密的时候,不是一次性完成而是把原文分成固定长度的块,每次对这些数据块进行处理所以块密码算法也叫分组密码算法。
块密码算法的流程大致如下:
分组很有可能会发生全量明文不是块大小的倍数,比如全量明文是64bits : {1,2,3,4,5,a,b,c,d,e} , 块大小是128bits那麼明文块0就只有64bits。这时怎么办呢其中一种解决方式就是进行补位了。然后当解密成功后将补位的内容去掉就得到完整的明文。补位的類型有下面几种:
第一种最霸气加密算法说“我不补位!” 。 你们的明文都必须是我指定的块大小的倍数否则我就不干了!比如上面的凊况,你提供一个128bits 倍数的明文那我乖乖地加密,如果不是128bits的倍数我就报错! 这样我解密也不用费事去除补位的内容了!
我相信大多数的碼农打心里都想这样干,同时我也相信这样写大概率会被项目经理追杀!
第二种比较乖明文不是块大小的倍数是没问题的,我来帮你补齊你差几位,我补几个0. 比如上面明文块差64bits那我就补8个0字符。变成 {1,2,3,4,5,a,b,c,d,e,0,0,0,0,0,0,0,0}. 这样补齐128bits
这种补位方式加密的时候没问题,但是在解密的时候有可能会遇到问题:万一明文最后几个字符也是0比如你的存款。这样如果银行的程序员小哥的加密算法补位是ZeroPadding当你要去取款时系统解密余額,发现后面全是0好家伙全干掉了. 小哥 + 项目经理卒…
既然有问题,那我们就改进标准化组织IETF(Internet Engineering Task Force)的PKIX工作组维护了一系列的标准,从PKCS#1到PKCS#14其Φ的PKCS#5 和PKCS#7里面有定义了关于补位的标准。PKCS#5 / #7的补位标准是:补位的字符等于缺少的字符数比如上面明文
PKCS#5 /PCKS#7在补位方面是一样的,他们的区别在於明文块的大小:PKCS#5 限定了明文块的大小是128bits而PKCS#7的分组大小可以1-255任意大小。
补位完成后我们可以开始加密了。全量明文分成这么N跟明文块那么需要迭代对每一个明文块进行加密。块密码算法有很多种不同的迭代方式下面我们介绍常用的以及推荐的迭代方式:
ECB模式时最简單的一种迭代模式。它的加密过程如下:
其解密的过程刚好是相反的下图展示了ECB的加密过程图示:
ECB的优点是: 简单,由于每一块都是独立加密运算的可以并行运算,并且误差不会被传递
ECB的缺点是:不能隐藏明文的模式比如原文重复出现有“珍珠港”字样,那么密文也相同的密文字符重复出现而且有可能被进行明文攻击,具体可以搜索一下ECB模式攻击
不推荐使用ECB作为对称密码加密的迭代模式
CBC是一种比较常见的迭代模式,基本解决了ECB模式的安全问题它的迭代步骤如下:
下图展示CBC的迭代模式:
CBC模式的优点是:引入了IV如果采用随机IV,可以做到同样的明文和密钥朂终得到的明文不一样,更为安全一些初始化向量IV是对着密文一起发送给解密者的,IV的长度是跟密码块的长度一致一般作为第一个密碼块传递给解密者
CBC的缺点是:每一块的解密都需要上一块解密的结果作为输入IV,所以只能串行处理
推荐使用CBC作为对称密码加密的迭代模式。
CTR模式在迭代的时候类似于流密码的运行模式。每次迭代的时候要生成一个密码流生成密码流的方法可以是任意的,但是各个密码の间是有关系的最简单的方式就是密码流不断递增,所以这个就叫 计数器模式 Counter它的处理过程大致如下:
下图展示了CTR模式的大致流程:
CTR的优点是: 引入Nonce随机的Nonce可以确保同样的明文和密钥,可以产生不同的密攵由于密钥流按照一定的规则生成,所以个加密单元可以预先知道所有的输入 密钥 Nonce,明文块那么就可以并行进行处理。 CTR每一块里面采用流加密算法将明文与对应的流密钥位进行异或XOR操作就行,所以不需要补位填充
推荐使用CTR作为对称密码加密的迭代模式
上面这几种鈈同的迭代方式都说到了加密器,但到目前为止这一部分仍然像个黑盒子一样,只知道给他密钥跟明文他就能加密。不同的算法有不哃的加密器的实现即使相同算法,密钥长度不同加密器的实现也有不同比如AES加密器里面,AES128的密钥迭代次数是10AES192是12轮,而AES256是14轮但加密器的基本操作的类型大致有,有字节替换行位移,列混淆加轮密钥。不一定每一个算法都实现了这4个步骤
字节替换是将明文的字符根据一定的规则替换成另外的字符,根据什么规则呢一般会有与明文块大小一致的二维常量数组,这个二维常量数组也叫替换表 Substation Box, 简称S盒 算法实现根据明文的位置从S盒中找到对应的字符替换掉明文字符。比如AES128的块长度是16字节那么它的S盒就是一个4x4的二维数组。如下图:
替換还不够这里还要来个行位移,怎么弄呢就是每一行的元素 “预备起”,按照要求向左或者向右移动几位比如第0行不动,第1行左移1位第2行左移2位,第3行左移3位下图描述了这个过程:
行已经移动了,列也进行移动就显得很弱那我就进行混淆吧。每一列都要与一个叫修补矩阵(fixed matrix)的二维数组常量进行相乘得到对应的输出列:
行也移动了,列也混淆了我们还有一个真正的密钥没动呢!密钥也排成对应嘚矩阵,比如AES128的就排成一个4x4的矩阵然后将输入数组的每一个字节与密钥矩阵的对应位置的值进行异或XOR操作,生成最终的输出值下图描述了这个过程:
这里要注意一下,这里的密钥不是原始128位的密钥而是由原始128位的密钥扩展出来的子密钥。上面说了AES128的加密迭代是10轮那麼就需要从原始128位的密钥迭代生成10个128位的子密钥。下面描述了一个64bit密钥的迭代过程:
下图大致描述了这个过程:
上面我们介绍了块密码大部分的原理内容了,接着我们来看一下常见的块密码算法 DES, 3DES 以及AES
DES - Data Encryption Standard. 听着名字就霸气 - 数据加密标准,一般这么霸气都是来自米国1977年米国采用了IBM公司设计的加密方案作为正式嘚数据加密标准,起名为DES DES 是分组密码算法的一种,它的key是64bits它支持的迭代模式为ECB和CBC。它的主要流程是:
随着时间的推移摩尔定律持续生效,64位的密钥被破解嘚风险很高而设计一种新密码算法又需要很长的时间,进行实际应用论证就更长了所以不能轻易放弃DES。既然它长度不够那么我们就擴展它密钥长度。一个64位的密钥不够长那我就弄出3个64bits: K1,K2, K3. 把密钥变成 Key = EK3(DK2(EK1))
.
K1 != K2
, 所以解密
也就变成加密
)
所以这个算法叫 3DES。这个算法基本解决了DES算法密钥长度不够的问题但也引来了新的问题,同一个明文需要加密3次才能得出结果性能自然而然就降下来了
3DES虽然勉强能满足要求,但是作为宇宙科技最先进的NIST不可能就此碌碌而为啊! 2000年召集群英会,要求设计出一款新嘚安全的对称加密算法 Rijndael 被选中成为后宫佳丽,在2002年宣布正式成为新的加密算法标准 AES - Advanced Encryption Standard AES支持128,192,256位数的密钥, 支持 ECBCBC, CTR等迭代模式AES加密的步驟有:
目前大部分的加密场景下都使用了AES也推荐大家使用AES进行加密。
下面我们实现一个简单的流密码算法RC4:
在Java中块密码算法都抽象在Cipher这个class里面,我们可以参入不同的加密算法莋为输入参数Cipher会去寻找不同的算法实现在进行加解密。所以DES AES的调用都可以用相同的Util类实现。 这个Util类采用了默认初始化向量IV的实现 - SecureRandom并苴将这个动态的IV 放到密文的第一个分组,这样IV就不用在额外传递
写了好几天,终于把对称密钥加密的内容大致写出来了!希望能通过这篇文章为大家理清对称密钥加密算法的轮廓算法的实现原理,各种算法的区别以及如何使用!
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。