兄弟连教育区块链的信息安全(5) 对称加密算法的分组模式及其Go语言实现

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

兄弟连教育区块链的信息安全(5) 对称加密算法的分组模式及其Go语言实现

# 对称加密算法的分组模式及其Go语言实现

之前介绍的DES、3DES、AES加密算法,只能加密固定长度的明文。如果需要加密任意长度的明文,需要对明文分组加密。

DES、3DES、AES等又称分组密码,而分组有很多模式,如:ECB模式、CBC模式、CFB模式、OFB模式、CTR模式,如下将逐一介绍。

## ECB模式

ECB模式,全称Electronic Codebook模式,译为电子密码本模式,即用相同的密码分别对明文分组独立加密。

ECB模式是最简单的模式,因为相同的明文分组会加密为相同的密文分组,因此存在一定风险。

如下为ECB模式示意图:

另外当最后一个明文分组的内容,小于分组长度时,需要用特定的数据进行填充。

## CBC模式

CBC模式,全称Cipher Block Chaining模式,译为密文分组链接模式,即加密算法的输入是上一个密文分组和下一个明文分组的异或。

因为是将上一个密文分组和下一个明文分组的内容混合加密,因此可以避免ECB模式的缺陷。

当加密第一个明文分组时,由于不存在上一个密文分组,因此需要准备与分组等长的初始化向量IV,来代替上一个密文分组。

如下为CBC模式示意图:

go标准库中CBC模式代码如下:

```go

type cbc struct {

//b为加密算法,如DES、AES

b Block

//加密算法支持的明文分组长度

blockSize int

//初始化向量IV

iv []byte

//临时变量

tmp []byte

}

type cbcEncrypter cbc

//指定加密算法和IV

func NewCBCEncrypter(b Block, iv []byte) BlockMode {

if len(iv) != b.BlockSize() {

panic("cipher.NewCBCEncrypter: IV length must equal block size ")

}

if cbc, ok := b.(cbcEncAble); ok {

return cbc.NewCBCEncrypter(iv)

}

return (*cbcEncrypter)(newCBC(b, iv))

}

//加密

func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {

if len(src)%x.blockSize != 0 {

panic("crypto/cipher: input not full blocks")

}

if len(dst) < len(src) {

panic("crypto/cipher: output smaller than input")

}

iv := x.iv

for len(src) > 0 {

//上一个密文分组和下一个明文分组的异或

//当加密第一个明文分组时,使用初始化向量IV

xorBytes(dst[:x.blockSize], src[:x.blockSize], iv)

//执行加密算法

x.b.Encrypt(dst[:x.blockSize], dst[:x.blockSize])

iv = dst[:x.blockSize]

src = src[x.blockSize:]

dst = dst[x.blockSize:]

}

copy(x.iv, iv)

}

//代码位置src/crypto/cipher/cbc.go

```

## CFB模式

CFB模式,全称Cipher FeedBack模式,译为密文反馈模式,即上一个密文分组作为加密算法的输入,输出与明文异或作为下一个分组的密文。

在CFB模式中,明文分组和密文分组之间只有一次异或。

如下为CFB模式示意图:

CFB模式与一次性密码本相似,都是通过将明文与随机比特序列进行异或运算来生成密文。但由于CFB模式中密码算法的输出是通过计算得到的,并非真正的随机数,因此不具备一次性密码本那样理论上不可破译的性质。

CFB模式可以看做使用分组方式实现流密码的方式。

go标准库中CFB模式代码如下:

```go

type cfb struct {

//加密算法

b Block

//加密的输入

next []byte

//加密的输出

out []byte

outUsed int

decrypt bool

}

//加密或解密

//decrypt为true表示解密

func (x *cfb) XORKeyStream(dst, src []byte) {

for len(src) > 0 {

if x.outUsed == len(x.out) {

x.b.Encrypt(x.out, x.next)

x.outUsed = 0

}

if x.decrypt {

copy(x.next[x.outUsed:], src)

}

//加密输出与明文异或作为下一个分组的密文

n := xorBytes(dst, src, x.out[x.outUsed:])

if !x.decrypt {

//上一个密文分组作为加密算法的输入

copy(x.next[x.outUsed:], dst)

}

dst = dst[n:]

src = src[n:]

x.outUsed += n

}

}

//加密器

func NewCFBEncrypter(block Block, iv []byte) Stream { return newCFB(block, iv, false)

相关文档
最新文档