在这个版本中,我们进行了以下几点改进:
使用了 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 }