GoLang AES加解密算法

原文链接:http://www.jianshu.com/p/b63095c59361

  • 对称加密算法,即加密和解密使用一样的密钥的加解密算法。
  • 分组密码(block cipher),是每次只能处理特定长度的一块(block)数据的一类加解密算法。
  • 目前常见的对称加密算法DES、3DES、AES都是属于分组密码。

AES高级加密标准,这个标准用来替代原先的DES,是现行的对称加密标准。
分组:128bit
秘钥:128bit、192bit、256bit

ECB模式##

  • 全称Electronic CodeBook mode,电子密码本模式。
  • 分组方式:将明文分组加密之后的结果直接称为密文分组。
  • 优点:
    1、一个分组的损坏不影响其他分组
    2、可以并行加解密
  • 缺点:
    1、相同的明文分组会转换为相同的密文分组。
    2、无需破译密码就能操纵明文(每个分组独立且前后文无关,直接增加或删除一个分组不影响其它分组解密过程的正确性)。

CBC模式##

  • 全称Cipher Block Chaining mode,密码分组链接模式。
  • 分组方式:将明文分组与前一个密文分组进行XOR运算,然后再进行加密。每个分组的加解密都依赖于前一个分组。而第一个分组没有前一个分组,因此需要一个初始化向量(initialization vector)。
  • 优点:
    1、加密结果与前文相关,有利于提高加密结果的随机性。
    2、可并行解密。
  • 缺点
    1、无法并行加密。
    2、一个分组损坏,如果密文长度不变,则两个分组受影响。
    3、一个分组损坏,如果密文长度改变,则后面所有分组受影响。

CFB模式##

  • 全称Cipher FeedBack mode,密文反馈模式。
  • 分组方式:前一个密文分组会被送回到密码算法的输入端。
    在CBC和EBC模式中,明文分组都是通过密码算法进行加密的。而在CFB模式中,明文分组并没有通过加密算法直接进行加密,明文分组和密文分组之间只有一个XOR。
  • CFB模式是通过将“明文分组”与“密码算法的输出”进行XOR运行生成“密文分组”。
  • CFB模式中由密码算法生成的比特序列称为密钥流(key stream)。密码算法相当于密钥流的伪随机数生成器,而初始化向量相当于伪随机数生成器的种子。(CFB模式有点类似一次性密码本。)
  • 优点:
    1、支持并行解密。
    2、不需要填充(padding)。
  • 缺点:
    1、不能抵御重放攻击(replay attack)。
    2、不支持并行加密。

OFB模式##

  • Output FeedBack mode 输出反馈模式
  • 密码算法的输出会反馈到密码算法的输入中(具体见下图)。
  • OFB模式中,XOR所需的比特序列(密钥流)可以事先通过密码算法生成,和明文分组无关。只需要提前准备好所需的密钥流,然后进行XOR运算就可以了。

分组模式小结###

推荐使用CBC模式。为什么要填充?ECB和CBC模式要求明文数据必须填充至长度为分组长度的整数倍。那么需要填充多少个字节?
paddingSize = blockSize - textLength % blockSize
填充什么内容?

  • ANSI X.923:填充序列的最后一个字节填paddingSize,其它填0。
  • ISO 10126:填充序列的最后一个字节填paddingSize, 其它填随机数。
  • PKCS7:填充序列的每个字节都填paddingSize。

下面使用CBC模式+PKCS7 填充方式实现AES的加密和解密:

package main

import (
    "bytes"
    "crypto/cipher"
    "crypto/aes"
    "encoding/base64"
    "fmt"
)

func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
    padding := blockSize - len(ciphertext) % blockSize
    padtext := bytes.Repeat([]byte{byte(padding)}, padding)
    return append(ciphertext, padtext...)
}

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

func AesEncrypt(origData, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    blockSize := block.BlockSize()
    origData = PKCS7Padding(origData, blockSize)
    blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
    crypted := make([]byte, len(origData))
    blockMode.CryptBlocks(crypted, origData)
    return crypted, nil
}

func AesDecrypt(crypted, key []byte) ([]byte, error) {
    block, err := aes.NewCipher(key)
    if err != nil {
        return nil, err
    }
    blockSize := block.BlockSize()
    blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
    origData := make([]byte, len(crypted))
    blockMode.CryptBlocks(origData, crypted)
    origData = PKCS7UnPadding(origData)
    return origData, nil
}

func main() {
    key := []byte("0123456789abcdef")
    result, err := AesEncrypt([]byte("hello world"), key)
    if err != nil {
        panic(err)
    }
    fmt.Println(base64.StdEncoding.EncodeToString(result))
    origData, err := AesDecrypt(result, key)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(origData))
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本文主要介绍移动端的加解密算法的分类、其优缺点特性及应用,帮助读者由浅入深地了解和选择加解密算法。文中会包含算法的...
    苹果粉阅读 11,586评论 5 29
  • 概述 什么是模式 第三章介绍的对称密码算法DES、AES都属于分组密码,分组密码的特点是分组的长度是固定的。但是由...
    JMasche阅读 3,149评论 0 4
  • 0x01 目录 常见编码: ASCII编码 Base64/32/16编码 shellcode编码 Quoted-p...
    H0f_9阅读 12,997评论 2 17
  • 前言 本文章是对《图解密码技术》一书第一部分的一个总结。 密码分类 密码算法需要密钥,根据密钥的使用方法,可以将密...
    发仔很忙阅读 1,475评论 1 2
  • 挑战埃及是全球首套能够同时适配PRINCE2认证人群,PMP认证人群的项目管理沙盘演练游戏。沙盘通过使用乐高积木作...
    Dan独记忆阅读 459评论 0 0