密码学系列 - 对称加密( 二 )


ECB 模式电子密码本模式(electronic codebook ),最简单的模式,将明文分组直接作为加密算法的输入,加密算法的输出直接作为密文分组 。
CBC 模式密文分组链接模式(Cipher Block Chaining),密文之间是链状的,明文分组跟上个密文分组异或之后作为加密算法的输入,加密算法的输出作为密文分组 。第一个明文分组加密时需要一个初始化向量 。
CFB 模式密文反馈模式(Cipher FeedBack),上一个密文分组作为下一个加密算法的输入,加密算法的输出与明文分组异或结果作为密文分组 。同样需要一个初始化向量
OFB 模式输出反馈模式(OutPut FeedBack),上一个加密算法的输出作为下一个加密算法的输入,明文与加密算法的输出异或作为密文分组 。需要初始化向量
CTR 模式计数器模式(Counter),将计数器作为加密算法的输入,加密算法的输出与明文分组异或作为密文分组,计数器是累加的 。需要一个初始的计数器值
以上各种模式,ECB 不推荐使用golang 代码实战:
func TestCBCMode(t *testing.T) { key:=[]byte{0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01} cipherBlock,err:=aes.NewCipher(key) if err!=nil{t.Error(err) } src:=[]byte{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08} inv:=[]byte{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08} cbcEncrypter:=cipher.NewCBCEncrypter(cipherBlock,inv) encrptDst :=make([]byte,len(src)) cbcEncrypter.CryptBlocks(encrptDst,src) t.Log(encrptDst) plainDst:=make([]byte,len(encrptDst)) cbcDecrypter:=cipher.NewCBCDecrypter(cipherBlock,inv) cbcDecrypter.CryptBlocks(plainDst,encrptDst) t.Log(plainDst)}//out [182 174 175 250 117 45 192 139 81 99 151 49 118 26 237 0 98 117 59 208 145 166 116 62 43 199 115 70 250 251 56 226]//out [1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8]关于本文作者更多信息请查看: https://tpkeep.com
密码学系列 - 对称加密本文讨论的对称加密算法主要包括 DES、3DES、AES
DES明文:64 bit 密文:64 bit 密钥:56/64 bit(每 7 位插入一个校验位的时候为 64 bit) 其设计思想充分体现了香农提出的混淆和扩散原则

密码学系列 - 对称加密

文章插图
 
DES 使用的是 Feistel 结构来加密的,一共需要 16 轮,加密过程如下:
  1. 将明文进行初始置换(通过置换表)
  2. 将置换后的数据分为左右 L1 R1 各 32 bit
  3. 将 48 bit 的子密钥与 R1 作为轮函数F的输入
  4. 将 L1 与轮函数的输出异或运算,得到 L1密文
  5. 将 L1 密文与 R1 交换位置,分别作为下一轮的 R2,L2
  6. 将 2-5 再重复 15 次
  7. 将 L17 R17 交换位置,并拼接为 64bit 数据
  8. 将 64bit 数据进行逆初始置换,得到最终密文
需要注意的是:
  • 子密钥在每一轮中都是不一样的
  • 每一轮之间会将左侧和右侧对调(右侧没有加密)
  • 解密的过程就是将输出用相同的子密钥再走一遍,如果加密的子密钥顺序是key1 key2 key3,则解密的子密钥为key3 key2 key1
  • 轮函数可以设计为不可逆函数如hash,对解密没有影响

密码学系列 - 对称加密

文章插图
 
golang 代码实战:
func TestDesEncrypt(t *testing.T) {key:=[]byte{0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}cipherBlock,err:=des.NewCipher(key)if err!=nil{t.Error(err)}src:=[]byte{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}encrptDst :=make([]byte,len(src))cipherBlock.Encrypt(encrptDst,src)t.Log(encrptDst)plainDst:=make([]byte,len(encrptDst))cipherBlock.Decrypt(plainDst, encrptDst)t.Log(plainDst)}//out: [206 173 55 61 184 14 171 248]//out: [1 2 3 4 5 6 7 8]三重DES明文:64 bit 密文:64 bit 密钥:56/64 * 3 bit(加入校验位的时候为64 bit)
为了增加 DES 的强度,明文经过 3 次 DES 处理后变成最后的密文,因此密钥长度为 56/64 * 3 bit 。3 次 DES 处理并不是简单的 3 次加密的过程,而是加密、解密、加密,解密的过程相应的就是解密、解密、解密 。这样设计是因为在 3 个密钥相同时,可以兼容 DES 算法
密码学系列 - 对称加密

文章插图
 
golang 代码实战:
func TestTripleDesEncrypt(t *testing.T) {key:=[]byte{0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}cipherBlock,err:=des.NewTripleDESCipher(key)if err!=nil{t.Error(err)}src:=[]byte{0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}encrptDst :=make([]byte,len(src))cipherBlock.Encrypt(encrptDst,src)t.Log(encrptDst)plainDst:=make([]byte,len(encrptDst))cipherBlock.Decrypt(plainDst, encrptDst)t.Log(plainDst)}//此处3个密钥相同,兼容DES//out: [206 173 55 61 184 14 171 248]//out: [1 2 3 4 5 6 7 8]


推荐阅读