密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,这个标准用来替代原先的DES。AES加密数据块分组长度必须为128bit,密钥长度可以是128bit、192bit、256bit中的任意一个。

这里推荐一个 golang 的加解密库:https://github.com/forgoer/openssl

支持的加密模式有:

  • AES-ECB/AES-CBC
  • DES-ECB/DES-CBC
  • 3DES-ECB/3DES-CBC
  • ...

填充

填充主要有三种模式:

ZeroPadding,数据长度不对齐时使用 0 填充,否则不填充。

PKCS7Padding,假设数据长度需要填充 n(n>0) 个字节才对齐,那么填充n个字节,每个字节都是 n ;如果数据本身就已经对齐了,则填充一块长度为块大小的数据,每个字节都是块大小。

PKCS5Padding,PKCS7Padding 的子集,块大小固定为8字节。

下面是一个填充的方法:

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

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

模式

AES的工作模式,体现在把明文块加密成密文块的处理过程中。AES加密算法提供了五种不同的工作模式:

CBC、ECB、CTR、CFB、OFB

下面是ECB模式:

func ECBEncrypt(block cipher.Block, src, key []byte) ([]byte, error) {
    blockSize := block.BlockSize()

    encryptData := make([]byte, len(src))
    tmpData := make([]byte, blockSize)

    for index := 0; index < len(src); index += blockSize {
        block.Encrypt(tmpData, src[index:index+blockSize])
        copy(encryptData, tmpData)
    }
    return encryptData, nil
}

func ECBDecrypt(block cipher.Block, src, key []byte) ([]byte, error) {
    dst := make([]byte, len(src))

    blockSize := block.BlockSize()
    tmpData := make([]byte, blockSize)

    for index := 0; index < len(src); index += blockSize {
        block.Decrypt(tmpData, src[index:index+blockSize])
        copy(dst, tmpData)
    }

    return dst, nil
}

AES/ECB/PKCS7Padding

AES/ECB/PKCS7Padding也是比较常用的加密方法之一。

    // 加密
    src := []byte("123456")
    key := []byte("1234512345123451")

    block, err := aes.NewCipher(key)
    if err != nil {
        panic(err)
    }

    src = PKCS7Padding(src, block.BlockSize())

    dst, err := ECBEncrypt(block, src, key)
    if err != nil {
        panic(err)
    }

    fmt.Println(base64.StdEncoding.EncodeToString(dst)) // SpfAShHImQhWjd/21Pgz2Q==

    // 解密
    src, err = ECBDecrypt(block, dst, key)
    if err != nil {
        panic(err)
    }

    src = PKCS7UnPadding(src)

    fmt.Println(string(src)) // 123456

更多关于Aes、Des等加密的完整实现代码,参考:https://github.com/forgoer/openssl