对称加密算法AES原理及实现

AES是作为DES的替代标准出现的,全称Advanced Encryption Standard,即:高级加密标准。AES加密算法,经历了公开的选拔,最终2000年,由比利时密码学家Joan Daemen和Vincent Rijmen设计的Rijndael算法被选中,成为了AES标准。
  AES明文分组长度为128位,即16个字节,密钥长度可以为16个字节、24个字节、或32个字节,即128位密钥、192位密钥、或256位密钥。

总体结构

AES中没有使用Feistel网络,其结构称为SPN结构。
  
  和DES相同,AES也由多个轮组成,其中每个轮分为SubBytes、ShiftRows、MixColumns、AddRoundKey 4个步骤,即:字节代替、行移位、列混淆和轮密钥加。根据密钥长度不同,所需轮数也不同,128位、192位、256位密钥,分别需要10轮、12轮和14轮。第1轮之前有一次AddRoundKey,即轮密钥加,可以视为第0轮;之后1至N-1轮,执行SubBytes、ShiftRows、MixColumns、AddRoundKey;最后一轮仅包括:SubBytes、MixColumns、AddRoundKey。
  
AES总体结构示意图:
  


对称加密算法AES原理及实现_第1张图片
结构示意图

分组密码

密码算法可以分为分组密码和流密码两种

  • 分组密码(block cipher)是每次只能处理特定长度的一块数据的一类密码算法,这里的“一块”就称为分组(block)。一个分组的比特数就称为分组长度(block lenght)。

    例如 DES和3DES的分组长度都是64比特。AES的分组长度为128比特。

  • 流密码(stream cipher)是对数据流进行连续处理的一类密码算法。流密码中一般以1比特、8比特、或32比特等为单位进行加密和解密。

分组密码处理完一个分组就结束了,因此不需要通过内部状态来记录加密的进度;相对地,流密码是对一串数据进行连续处理,因此需要保持内部状态。

模式

分组密码算法只能加密固定长度的分组,但是我们需要加密的明文长度可能会超过分组密码的分组长度,这时就需要对分组密码算法进行迭代,以便将一段很长的明文全部加密。而迭代的方法就称为分组密码的模式(mode)。

  • ECB模式:Electronic CodeBook mode(电子密码模式)
  • CBC模式:Cipher Block Chaining mode(密码分组链接模式)
  • CFB模式:Cipher FeedBack mode(密文反馈模式)
  • OFB模式:Output FeedBack mode(输出反馈模式)
  • CTR模式:CounTeR mode(计数器模式)

ECB模式存在很高的风险,下面举例后面4中模式的使用.
加密的过程中使用了随机流,所以每次加密的密文都不一样

CBC模式

func main() {


    key := "1234567890asdfgh"
    data := "hollo, world!"

    cry := AesCBCEncrypt([]byte(data), []byte(key))
    fmt.Println(hex.EncodeToString(cry))

    oriData := AESCBCDECriypt(cry, []byte(key))
    fmt.Println(string(oriData))

}
// AES也是对称加密 AES 是 DES 的替代品
// AES 密钥长度 只能是 16、24、32 字节
//加密
func AesCBCEncrypt(org []byte, key []byte) []byte  {

    //校验密钥
    block,_ := aes.NewCipher(key)

    //按照公钥长度 进行分组补码
    org = PKCS7Padding(org, block.BlockSize())

    //设置CBC的加密模式
    blockMode := cipher.NewCBCEncrypter(block, key)

    //加密处理
    crypted := make([]byte, len(org))
    blockMode.CryptBlocks(crypted, org)

    return crypted
}

//解密
func AESCBCDECriypt(criptText []byte, key []byte) []byte  {

    //校验key的有效性
    block,_:=aes.NewCipher(key)
    //通过CBC模式解密
    blockMode:=cipher.NewCBCDecrypter(block,key)

    //实现解密
    origData:=make([]byte,len(criptText))
    blockMode.CryptBlocks(origData,criptText)

    //去码
    origData = PKCS7UnPadding(origData)
    return origData
}





//PKCS5 分组长度只能为8
//PKCs7 分组长度 1- 255

func PKCS7Padding(org []byte, blockSize int) []byte  {

    pad := blockSize-len(org)%blockSize
    padArr := bytes.Repeat([]byte{byte(pad)}, pad)
    return  append(org, padArr...)

}

func PKCS7UnPadding(cryptText []byte) []byte  {
    
    length := len(cryptText)
    lastByte := cryptText[length - 1]
    return cryptText[:length-int(lastByte)]
    
}

输出

ffa22c136fd3e944255d43e255c98ecc
hollo, world!

CFB模式

func main()  {


    key := []byte("1234567890asdfgh")
    data := []byte("abc hello world!")
    cry := AESCFBEncrypt(data, key)

    fmt.Println(hex.EncodeToString(cry))
    //fmt.Println(base64.StdEncoding.EncodeToString(cry))

    ori := AESCFBDecrypt(cry, key)
    fmt.Println(string(ori))

}

//CFB分组模式加密
func AESCFBEncrypt(oriData []byte, key []byte) []byte  {

    //校验密钥
    block,_ := aes.NewCipher(key)

    //拆分iv和密文
    cipherText := make([]byte, aes.BlockSize + len(oriData))

    iv := cipherText[:aes.BlockSize]

    //向iv切片数组初始化 reader(随机内存流)
    io.ReadFull(rand.Reader, iv)

    //设置加密模式CFB
    stream := cipher.NewCFBEncrypter(block,iv)

    //加密
    stream.XORKeyStream(cipherText[aes.BlockSize:], oriData)

    return  cipherText


}

//解密
func AESCFBDecrypt(cryptText []byte, key []byte) []byte {

    //校验密钥
    block,_ := aes.NewCipher(key)

    //拆分iv 和密文
    iv := cryptText[:aes.BlockSize]
    cipherText := cryptText[aes.BlockSize:]


    //设置解密模式
    stream := cipher.NewCFBDecrypter(block, iv)

    var des = make([]byte, len(cipherText))

    //解密
    stream.XORKeyStream(des, cipherText)

    return des
}

输出

92e5c5d7bc54b337a7edbb548ee1a62c8c3c079b71f465a3f0566c0d74b8d513
abc hello world!

OFB模式

func main()  {

    key := []byte("1234567890asdfgh")
    data := []byte("abcd hello world!")
    cry := AESOFBEncrypt(data, key)

    fmt.Println(hex.EncodeToString(cry))

    ori := AESOFBDecrypt(cry, key)
    fmt.Println(string(ori))
}

//AES OFB分组加密模式  CTR也是一样
func AESOFBEncrypt(plaintxt []byte, key []byte) []byte  {

    //校验密钥
    block,_ := aes.NewCipher(key)

    cipherText := make([]byte, aes.BlockSize + len(plaintxt))

    iv := cipherText[:aes.BlockSize]

    //向iv切片数组初始化 reader(随机内存流)
    io.ReadFull(rand.Reader, iv)

    //设置加密模式CFB
    stream := cipher.NewOFB(block,iv)

    //加密
    stream.XORKeyStream(cipherText[aes.BlockSize:], plaintxt)

    return  cipherText

}


//解密
func AESOFBDecrypt(cryptText []byte, key []byte) []byte {

    //校验密钥
    block,_ := aes.NewCipher(key)

    //拆分iv 和 密文
    iv := cryptText[:aes.BlockSize]
    plaintxt := make([]byte, len(cryptText)-aes.BlockSize)


    //设置解密模式
    stream := cipher.NewOFB(block, iv)

    //解密
    stream.XORKeyStream(plaintxt, cryptText[aes.BlockSize:])

    return plaintxt
}

输出

9ee409f8513e3fcba2f1ba726da0b2a5d80251efa073544220b44c8e8fee18fce4
abcd hello world!

CTR模式

func main()  {

    key := []byte("1234567890asdfgh")
    data := []byte("abcd hello world!")
    cry := AESCTREncrypt(data, key)

    fmt.Println(hex.EncodeToString(cry))

    ori := AESCTRDecrypt(cry, key)
    fmt.Println(string(ori))
}

//AES CTR分组加密模式
func AESCTREncrypt(plaintxt []byte, key []byte) []byte  {

    //校验密钥
    block,_ := aes.NewCipher(key)

    cipherText := make([]byte, aes.BlockSize + len(plaintxt))

    iv := cipherText[:aes.BlockSize]

    //向iv切片数组初始化 reader(随机内存流)
    io.ReadFull(rand.Reader, iv)

    //设置加密模式CTR
    stream := cipher.NewCTR(block,iv)

    //加密
    stream.XORKeyStream(cipherText[aes.BlockSize:], plaintxt)

    return  cipherText

}


//解密
func AESCTRDecrypt(cryptText []byte, key []byte) []byte {

    //校验密钥
    block,_ := aes.NewCipher(key)

    //拆分iv 和 密文
    iv := cryptText[:aes.BlockSize]
    plaintxt := make([]byte, len(cryptText)-aes.BlockSize)


    //设置解密模式
    stream := cipher.NewCTR(block, iv)

    //解密
    stream.XORKeyStream(plaintxt, cryptText[aes.BlockSize:])

    return plaintxt
}

输出

c645da2d14896d2b75d41a538a5a3efe3c7721f51f2eb2e92b0c5b8ba141caf534
abcd hello world!

你可能感兴趣的:(对称加密算法AES原理及实现)