对称加密算法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总体结构示意图:
  


结构示意图

分组密码

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

  • 分组密码(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!
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 目录一、对称加密 1、对称加密是什么 2、对称加密的优点 3、对称加密的问题 4、对称加密的应用场景 5、对称加密...
    意一ineyee阅读 61,796评论 8 110
  • 这篇文章主要讲述在Mobile BI(移动商务智能)开发过程中,在网络通信、数据存储、登录验证这几个方面涉及的加密...
    雨_树阅读 2,329评论 0 6
  • 本文主要介绍移动端的加解密算法的分类、其优缺点特性及应用,帮助读者由浅入深地了解和选择加解密算法。文中会包含算法的...
    苹果粉阅读 11,450评论 5 29
  • 概述 之前一直对加密相关的算法知之甚少,只知道类似DES、RSA等加密算法能对数据传输进行加密,且各种加密算法各有...
    Henryzhu阅读 3,000评论 0 14
  • 对称加密算法,即加密和解密使用一样的密钥的加解密算法。分组密码(block cipher),是每次只能处理特定长度...
    linjinhe阅读 11,888评论 3 16