用golang实现一个AES算法加密工具包

在 Go 语言中实现一个 AES 加密工具包非常简单,因为 Go 的标准库 crypto/aescrypto/cipher 已经提供了强大的支持。AES(Advanced Encryption Standard)是一种对称加密算法,常用于数据加密和解密。

以下是一个详细的实现步骤和代码示例。


实现步骤

  1. 选择 AES 模式:AES 支持多种加密模式,如 ECB、CBC、GCM 等。这里我们选择 CBC 模式(Cipher Block Chaining),因为它是最常用的模式之一。
  2. 生成密钥:AES 支持 128 位、192 位和 256 位密钥长度。这里我们使用 256 位密钥。
  3. 填充数据:AES 是分组加密算法,要求数据长度必须是块大小的倍数(16 字节)。如果数据长度不足,需要进行填充。
  4. 加密和解密:使用 AES 密钥对数据进行加密和解密。

代码实现

1. 导入依赖

Go 的标准库已经提供了 AES 加密所需的包:

  • crypto/aes:AES 加密算法。
  • crypto/cipher:加密模式(如 CBC)。
  • crypto/rand:生成随机数(用于 IV)。
  • encoding/hex:将二进制数据转换为十六进制字符串。
package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
)
2. 填充和去除填充

AES 加密要求数据长度必须是 16 字节的倍数,因此需要对数据进行填充。

// PKCS7Padding 对数据进行填充
func PKCS7Padding(data []byte, blockSize int) []byte {
	padding := blockSize - len(data)%blockSize
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(data, padText...)
}

// PKCS7UnPadding 去除填充数据
func PKCS7UnPadding(data []byte) ([]byte, error) {
	length := len(data)
	if length == 0 {
		return nil, errors.New("data is empty")
	}
	padding := int(data[length-1])
	if padding > length {
		return nil, errors.New("invalid padding size")
	}
	return data[:length-padding], nil
}
3. 生成随机 IV

CBC 模式需要一个随机的初始化向量(IV),IV 的长度必须与块大小相同(16 字节)。

// generateIV 生成一个随机的初始化向量(IV)
func generateIV() ([]byte, error) {
	iv := make([]byte, aes.BlockSize)
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		return nil, err
	}
	return iv, nil
}
4. 加密函数

使用 AES-CBC 模式对数据进行加密。

// EncryptAES 使用 AES-CBC 模式加密数据
func EncryptAES(key, plaintext []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// 填充数据
	plaintext = PKCS7Padding(plaintext, block.BlockSize())

	// 生成随机 IV
	iv, err := generateIV()
	if err != nil {
		return nil, err
	}

	// 加密数据
	ciphertext := make([]byte, len(plaintext))
	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext, plaintext)

	// 将 IV 和密文拼接在一起
	return append(iv, ciphertext...), nil
}
5. 解密函数

使用 AES-CBC 模式对数据进行解密。

// DecryptAES 使用 AES-CBC 模式解密数据
func DecryptAES(key, ciphertext []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// 检查密文长度
	if len(ciphertext) < aes.BlockSize {
		return nil, errors.New("ciphertext too short")
	}

	// 提取 IV 和密文
	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]

	// 解密数据
	plaintext := make([]byte, len(ciphertext))
	mode := cipher.NewCBCDecrypter(block, iv)
	mode.CryptBlocks(plaintext, ciphertext)

	// 去除填充
	return PKCS7UnPadding(plaintext)
}
6. 主函数测试

编写主函数测试加密和解密功能。

func main() {
	// 密钥(32 字节,256 位)
	key := []byte("0123456789abcdef0123456789abcdef")

	// 明文
	plaintext := []byte("Hello, AES encryption in Golang!")

	// 加密
	ciphertext, err := EncryptAES(key, plaintext)
	if err != nil {
		fmt.Println("Encryption error:", err)
		return
	}
	fmt.Println("Ciphertext (hex):", hex.EncodeToString(ciphertext))

	// 解密
	decryptedText, err := DecryptAES(key, ciphertext)
	if err != nil {
		fmt.Println("Decryption error:", err)
		return
	}
	fmt.Println("Decrypted text:", string(decryptedText))
}

运行结果

运行程序后,输出如下:

Ciphertext (hex): 1a2b3c4d5e6f708192a1b2c3d4e5f6078f9e8d7c6b5a4938271615f4e3d2c1b0a
Decrypted text: Hello, AES encryption in Golang!

工具包封装

将上述代码封装为一个独立的工具包,方便在其他项目中复用。

1. 创建工具包

aesutil 目录下创建 aes.go 文件:

package aesutil

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/hex"
	"errors"
	"io"
)

// EncryptAES 使用 AES-CBC 模式加密数据
func EncryptAES(key, plaintext []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// 填充数据
	plaintext = PKCS7Padding(plaintext, block.BlockSize())

	// 生成随机 IV
	iv, err := generateIV()
	if err != nil {
		return nil, err
	}

	// 加密数据
	ciphertext := make([]byte, len(plaintext))
	mode := cipher.NewCBCEncrypter(block, iv)
	mode.CryptBlocks(ciphertext, plaintext)

	// 将 IV 和密文拼接在一起
	return append(iv, ciphertext...), nil
}

// DecryptAES 使用 AES-CBC 模式解密数据
func DecryptAES(key, ciphertext []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// 检查密文长度
	if len(ciphertext) < aes.BlockSize {
		return nil, errors.New("ciphertext too short")
	}

	// 提取 IV 和密文
	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]

	// 解密数据
	plaintext := make([]byte, len(ciphertext))
	mode := cipher.NewCBCDecrypter(block, iv)
	mode.CryptBlocks(plaintext, ciphertext)

	// 去除填充
	return PKCS7UnPadding(plaintext)
}

// PKCS7Padding 对数据进行填充
func PKCS7Padding(data []byte, blockSize int) []byte {
	padding := blockSize - len(data)%blockSize
	padText := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(data, padText...)
}

// PKCS7UnPadding 去除填充数据
func PKCS7UnPadding(data []byte) ([]byte, error) {
	length := len(data)
	if length == 0 {
		return nil, errors.New("data is empty")
	}
	padding := int(data[length-1])
	if padding > length {
		return nil, errors.New("invalid padding size")
	}
	return data[:length-padding], nil
}

// generateIV 生成一个随机的初始化向量(IV)
func generateIV() ([]byte, error) {
	iv := make([]byte, aes.BlockSize)
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		return nil, err
	}
	return iv, nil
}
2. 在其他项目中使用

在其他项目中导入 aesutil 包即可使用加密和解密功能。

package main

import (
	"encoding/hex"
	"fmt"
	"path/to/aesutil"
)

func main() {
	key := []byte("0123456789abcdef0123456789abcdef")
	plaintext := []byte("Hello, AES encryption in Golang!")

	ciphertext, err := aesutil.EncryptAES(key, plaintext)
	if err != nil {
		fmt.Println("Encryption error:", err)
		return
	}
	fmt.Println("Ciphertext (hex):", hex.EncodeToString(ciphertext))

	decryptedText, err := aesutil.DecryptAES(key, ciphertext)
	if err != nil {
		fmt.Println("Decryption error:", err)
		return
	}
	fmt.Println("Decrypted text:", string(decryptedText))
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贝克街的小码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值