返回
北京兄弟连IT
置顶
该校与厚学网暂未合作,平台不保证课程的真实有效性,如有侵权等争议,请及时与厚学网联系处理
招生热线:400-800-2181

学校地址:北京市昌平区回龙观文华西路育荣教育园区兄弟连IT教育

兄弟连区块链教程信息安全对称加密算法

238 2018-11-12 11:27:29

学习笔记

  兄弟连区块链教程区块链背后的信息安全对称加密算法的分组模式,2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需求与身价似乎正在回落。但事实上,正是初期泡沫的渐退,让人们更多的关注点放在了区块链真正的技术之上。

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

 

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

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

 

## ECB模式

 

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

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

 

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

 

## CBC模式

 

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

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

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

 

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模式可以看做使用分组方式实现流密码的方式。

 

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)

}

 

//解密器

func NewCFBDecrypter(block Block, iv []byte) Stream {

    return newCFB(block, iv, true)

}

 

func newCFB(block Block, iv []byte, decrypt bool) Stream {

    //分组长度

    blockSize := block.BlockSize()

    if len(iv) != blockSize {

        //初始化向量要求与分组长度等长

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

    }

    x := &cfb{

        b:       block,

        out:     make([]byte, blockSize),

        next:    make([]byte, blockSize),

        outUsed: blockSize,

        decrypt: decrypt,

    }

    //加密的输入

    copy(x.next, iv)

 

    return x

}

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

```

 

## OFB模式

 

OFB模式,全称Output Feedback模式,译为输出反馈模式。

OFB模式与CFB模式类似,只是加密算法的输入是上一次加密的输出。

OFB模式中,异或所需的密钥流,可以事先通过密码算法生成,即生成密钥流的操作可以与异或运算并行。

 

OFB模式加密和处理解密逻辑相同,明文与密钥流异或生成密文,密文与密钥流异或生成明文。

 

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

 

```go

type ofb struct {

    //加密算法

    b       Block

    //加密的输入

    cipher  []byte

    out     []byte

    outUsed int

}

 

func NewOFB(b Block, iv []byte) Stream {

    //分组长度

    blockSize := b.BlockSize()

    if len(iv) != blockSize {

        return nil

    }

    //const streamBufferSize = 512

    bufSize := streamBufferSize

    if bufSize < blockSize {

        bufSize = blockSize

    }

    x := &ofb{

        b:       b,

        cipher:  make([]byte, blockSize),

        out:     make([]byte, 0, bufSize),

        outUsed: 0,

    }

 

    //加密的输入

    copy(x.cipher, iv)

    return x

}

 

//生成密钥流

func (x *ofb) refill() {

    bs := x.b.BlockSize()

    remain := len(x.out) - x.outUsed

    if remain > x.outUsed {

        return

    }

    copy(x.out, x.out[x.outUsed:])

    x.out = x.out[:cap(x.out)]

    for remain < len(x.out)-bs {

        x.b.Encrypt(x.cipher, x.cipher)

        copy(x.out[remain:], x.cipher)

        remain += bs

    }

    x.out = x.out[:remain]

    x.outUsed = 0

}

来源:北京兄弟连IT

热门课程 全部课程

热门动态

申请免费试听

只要一个电话

我们为您免费回电

立即申请
刷新
图形验证
关闭
>>
拖动左边滑块完成上方拼图