前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Golang AES 加解密

Golang AES 加解密

作者头像
恋喵大鲤鱼
发布2022-05-09 11:15:54
1.6K0
发布2022-05-09 11:15:54
举报
文章被收录于专栏:C/C++基础

文章目录

AES 简介

利用 Go 提供的 AES 加解密与 Base64 编解码包,我们可以轻松实现 AES 加解密。实现之前,首先了解一下 AES 的基本知识。

AES(Advanced Encryption Standard)高级加密标准,是流行的对称加密算法,由美国国家标准与技术研究院(NIST)于 2001 年发布,用于取代 DES。Rijndael 算法 是 AES 标准的一个实现,一般说 AES 指的就是 Rijndael 算法。

(1)AES 有 5 种加密模式,分别是:

  • 电子密码本模式(ECB,Electronic Code Book);
  • 加密块链模式(CBC,Cipher Block Chaining),如果明文长度不是分组长度 16 字节的整数倍需要进行填充;
  • 计数模式(CTR,Counter);
  • 密码反馈模式(CFB,Cipher FeedBack);
  • 输出反馈模式(OFB,Output FeedBack)。

(2)AES 是对称分组加密算法,每组长度为 128bits,即 16 字节。

(3)AES 秘钥的长度只能是16、24 或 32 字节,分别对应三种加密模式 AES-128、AES-192 和 AES-256,三者的区别是加密轮数不同。

AES

分组长度(字节)

密钥长度(字节)

加密轮数

AES-128

16

16

10

AES-192

16

24

12

AES-256

16

32

14

AES 加解密实现

下面以 CBC 模式为例,实现 AES 加解密。

代码语言:javascript
复制
package main

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

// PKCS7Padding fills plaintext as an integral multiple of the block length
func PKCS7Padding(p []byte, blockSize int) []byte {
	pad := blockSize - len(p)%blockSize
	padtext := bytes.Repeat([]byte{byte(pad)}, pad)
	return append(p, padtext...)
}

// PKCS7UnPadding removes padding data from the tail of plaintext
func PKCS7UnPadding(p []byte) []byte {
	length := len(p)
	paddLen := int(p[length-1])
	return p[:(length - paddLen)]
}

// AESCBCEncrypt encrypts data with AES algorithm in CBC mode
// Note that key length must be 16, 24 or 32 bytes to select AES-128, AES-192, or AES-256
// Note that AES block size is 16 bytes
func AESCBCEncrypt(p, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	p = PKCS7Padding(p, block.BlockSize())
	ciphertext := make([]byte, len(p))
	blockMode := cipher.NewCBCEncrypter(block, key[:block.BlockSize()])
	blockMode.CryptBlocks(ciphertext, p)
	return ciphertext, nil
}

// AESCBCDecrypt decrypts cipher text with AES algorithm in CBC mode
// Note that key length must be 16, 24 or 32 bytes to select AES-128, AES-192, or AES-256
// Note that AES block size is 16 bytes
func AESCBCDecrypt(c, key []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	plaintext := make([]byte, len(c))
	blockMode := cipher.NewCBCDecrypter(block, key[:block.BlockSize()])
	blockMode.CryptBlocks(plaintext, c)
	return PKCS7UnPadding(plaintext)
}

// Base64AESCBCEncrypt encrypts data with AES algorithm in CBC mode and encoded by base64
func Base64AESCBCEncrypt(p, key []byte) (string, error) {
	c, err := AESCBCEncrypt(p, key)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(c), nil
}

// Base64AESCBCDecrypt decrypts cipher text encoded by base64 with AES algorithm in CBC mode
func Base64AESCBCDecrypt(c string, key []byte) ([]byte, error) {
	oriCipher, err := base64.StdEncoding.DecodeString(c)
	if err != nil {
		return nil, err
	}
	p, err := AESCBCDecrypt(oriCipher, key)
	if err != nil {
		return nil, err
	}
	return p, nil
}

使用示例如下:

代码语言:javascript
复制
func main() {
   	p := []byte("plaintext")
	key := []byte("12345678abcdefgh")
	
	ciphertext, _ := Base64AESCBCEncrypt(p, key)
	fmt.Println(ciphertext)

	plaintext, _ := Base64AESCBCDecrypt(ciphertext, key)
	fmt.Println(string(plaintext))
}

运行输出:

代码语言:javascript
复制
A67NhD3RBiNaMgG6HTm8LQ==
plaintext

小结

以上代码已放到开源 Go 工具库 go-huge-util,大家如果需要,可直接通过 go mod 方式进行 import 然后使用。

代码语言:javascript
复制
import (
	huge "github.com/dablelv/go-huge-util"
)

p := []byte("plaintext")
key := []byte("12345678abcdefgh")

ciphertext, _ := huge.Base64AESCBCEncrypt(p, key)			// A67NhD3RBiNaMgG6HTm8LQ==
plaintext, _ := huge.Base64AESCBCDecrypt(ciphertext, key)	// plaintext

如果想了解 AES 实现原理。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-04-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • AES 简介
  • AES 加解密实现
  • 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档