AES加密解密函数go语言版

在这个版本中,我们进行了以下几点改进:

使用了 GCM(Galois/Counter Mode)而不是 CBC 模式。GCM 提供了更好的安全性,并且内置了认证,因此你不需要额外进行消息认证代码或 HMAC。

我们现在使用随机的 nonce(数字仅用一次),它是GCM安全性的关键组成部分。这可以防止重放攻击。

我们移除了 PKCS#7 填充,因为在 GCM 中,它不是必需的。这消除了与填充相关的某些攻击向量,如填充oracle攻击。

代码结构更清晰,更易于阅读和维护。

我们检查了密文是否过短,这可能表明密文已损坏或不完整。

这些改进使代码更安全,更符合现代加密的最佳实践。然而,在实际的生产环境中,还需要更多的安全措施,如密钥管理和定期更换、安全的密钥存储、错误日志处理、环境安全性等。

package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"errors"
	"fmt"
	"io"
)

func main() {
	// 示例密钥。在实际应用中,你需要安全地生成和存储这个密钥
	key := []byte("a very very very very secret key") // 32 bytes

	// 示例文本
	plaintext := []byte("Hello, World!")

	ciphertext, err := encrypt(key, plaintext)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Encrypted: %x\n", ciphertext)

	decrypted, err := decrypt(key, ciphertext)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Decrypted: %s\n", decrypted)
}

// 加密函数
func encrypt(key, plaintext []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	// 新的GCM
	gcm, err := cipher.NewGCM(block)
	if err != nil {
		return nil, err
	}

	// 创建一个新的字节切片与GCM标准的Nonce大小
	nonce := make([]byte, gcm.NonceSize())
	// 随机填充nonce
	if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
		return nil, err
	}

	// 使用Seal方法加密数据
	ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
	return ciphertext, nil
}

// 解密函数
func decrypt(key, ciphertext []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	gcm, err := cipher.NewGCM(block)
	if err != nil {
		return nil, err
	}

	if len(ciphertext) < gcm.NonceSize() {
		return nil, errors.New("malformed ciphertext")
	}

	// 分割nonce和实际的密文
	nonce, ciphertext := ciphertext[:gcm.NonceSize()], ciphertext[gcm.NonceSize():]

	// 使用Open方法解密数据
	plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
	if err != nil {
		return nil, err
	}

	return plaintext, nil
}
点赞