Golang中使用AES解密时遇到的问题:消息验证失败

Golang中使用AES解密时遇到的问题:消息验证失败 我正在编写一个自定义的AES-256加密和解密函数,并将这些函数保存在一个名为zeus的包中。

/*
索引:
101 --> 哈希函数
102 --> 加密函数
*/

package zeus

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"crypto/sha256"
	"crypto/sha512"
	"fmt"
	"golang.org/x/crypto/bcrypt"
	"io"
	"log"
)

// 101 --> 哈希函数

// 接收一个字符串,使用sha256进行哈希,并返回哈希后的字符串
func SHA_256(plainText string) (hashedString string) {
	bytes := []byte(plainText)
	hash := sha256.Sum256(bytes)
	hashedString = fmt.Sprintf("%X\n", hash)
	return hashedString
}

// 接收一个字符串,使用sha512进行哈希,并返回哈希后的字符串
func SHA_512(plainText string) (hashedString string) {
	bytes := []byte(plainText)
	hash := sha512.Sum512(bytes)
	hashedString = fmt.Sprintf("%X\n", hash)
	return hashedString
}

// 接收明文和成本值,使用bcrypt进行哈希,并返回哈希后的字符串
func Bcrypt(plainText string, cost int) (hashedString string) {
	bytes := []byte(plainText)
	// 生成哈希字符串
	hash, err := bcrypt.GenerateFromPassword(bytes, cost)
	if err != nil {
		log.Fatal(err)
	}
	hashedString = fmt.Sprintf("%s\n", hash)
	return hashedString
}

// 检查哈希是否与明文匹配
func Bcrypt_Check(hashedString string, plainText string) {
	hashedString_bytes := []byte(hashedString)
	plainText_bytes := []byte(plainText)
	result := bcrypt.CompareHashAndPassword(hashedString_bytes, plainText_bytes)
	if result != nil {
		log.Fatal(result)
	}
	fmt.Println("匹配成功!")
}

// 对你输入的密钥字符串进行哈希,将其修剪为32字节并转换为字节
func GenerateKey(key string) (final_key []byte) {
	hashed_key := SHA_256(key)
	// 将密钥修剪为32字节(AES-256)
	trimmed_key := hashed_key[0:32]
	// 将修剪后的密钥转换为字节
	final_key = []byte(trimmed_key)
	return final_key
}

// 102 --> 加密函数

// AES_256加密,接收明文和密钥,返回密文字符串
func Encrypt_AES_256(plainText string, key string) (cipherText_String string) {
	// 将消息(文本)转换为字节
	plainText_bytes := []byte(plainText)
	// 生成密钥
	final_key := GenerateKey(key)
	// 创建一个新的密码块
	cipher1, err := aes.NewCipher(final_key)
	// 检查是否有错误,如果有则退出脚本
	if err != nil {
		log.Fatal(err)
	}
	// 将密码块传递给伽罗瓦/计数器模式(GCM)
	gcm, err := cipher.NewGCM(cipher1)
	if err != nil {
		log.Fatal(err)
	}
	// 创建一个大小为Nonce的新字节数组
	nonce := make([]byte, gcm.NonceSize())
	// 用加密安全的随机序列填充字节数组
	_, err = io.ReadFull(rand.Reader, nonce)
	if err != nil {
		log.Fatal(err)
	}
	// Seal对明文进行加密和认证,并对附加数据进行认证
	cipherText := gcm.Seal(nonce, nonce, plainText_bytes, nil)
	cipherText_String = fmt.Sprintf("%X\n", cipherText)
	return cipherText_String
}

这是我的主文件:

package main

import (
	"crypto/aes"
	"crypto/cipher"
	// "crypto/rand"
	// "crypto/sha256"
	// "crypto/sha512"
	// "encoding/hex"
	"fmt"
	"github.com/kkaskdf/zeus"
	// "golang.org/x/crypto/bcrypt"
	// "io"
	// "io/ioutil"
	"log"
)

func Decrypt_AES_256(cipherText_String string, key string) (plainText string) {
	final_key := zeus.GenerateKey(key)
	cipher1, err := aes.NewCipher(final_key)
	if err != nil {
		log.Fatal(err)
	}
	gcmDecrypt, err := cipher.NewGCM(cipher1)
	if err != nil {
		log.Fatal(err)
	}
	nonceSize := gcmDecrypt.NonceSize()
	cipherText_byte := []byte(cipherText_String)
	if len(cipherText_byte) < nonceSize {
		log.Fatal(err)
	}
	nonce, encryptedMessage := cipherText_byte[:nonceSize],
		cipherText_byte[nonceSize:]
	nonce_byte := []byte(nonce)
	encryptedMessage_byte := []byte(encryptedMessage)
	plaintext, err := gcmDecrypt.Open(nil, nonce_byte, encryptedMessage_byte, nil)
	fmt.Println("err0")
	if err != nil {
		log.Fatal(err)
	}
	return fmt.Sprintf("%s", plaintext)
}

func main() {
	// str1 := "Hi man Can"
	// str2 := "Hi man Can"
	// fmt.Printf("%v", zeus.SHA_256(str1))
	// fmt.Printf("%v", zeus.SHA_512(str1))
	// fmt.Printf("%v", zeus.Bcrypt(str1, 5))

	// zeus.Bcrypt_Check(zeus.Bcrypt(str1, 5), str2)

	password := "This is the password"
	plainText := "Hi man Can 32 Hi man Can 23 Hi man Can"
	cipherText := zeus.Encrypt_AES_256(plainText, password)
	fmt.Printf("%v", cipherText)
	fmt.Printf("%v", Decrypt_AES_256(cipherText, password))

}

现在,当我尝试解密密文时,我得到以下输出:

4E4E31C4D70AC4F6F6696CB2921C208BE3124F3CBB5E73AFEE7FBB81F503034AA64EFAB3CC35784D25ED125943E835B9371BA4D3AAC9A292C00A4F256CECEF9A815B
err0
2020/12/11 00:51:49 cipher: message authentication failed

输出中的第一行是加密文本,它是Encrypt_AES_256()函数的输出。

第二行是我打印的一个字符串,用于定位Decrypt_AES_256()函数内部的错误位置。

第三行是此处错误的输出:

plaintext, err := gcmDecrypt.Open(nil, nonce_byte, encryptedMessage_byte, nil)
	fmt.Println("err0")
	if err != nil {
		log.Fatal(err)
	}

错误出现在Decrypt_AES_256()函数的这一行:

plaintext, err := gcmDecrypt.Open(nil, nonce_byte, encryptedMessage_byte, nil)

有人知道如何解决这个问题吗?

我遵循了这篇文章的说明:

Golang Encryption Decryption Example | AES Encryption In Go

Golang Encryption Decryption Example | AES Encryption In Go

Golang加密解密示例。我们将看到使用AES算法进行非对称和对称加密解密。我们在Go中实现AES-GCM代码。

预计阅读时间:7分钟


更多关于Golang中使用AES解密时遇到的问题:消息验证失败的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中使用AES解密时遇到的问题:消息验证失败的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


问题出在Encrypt_AES_256函数返回的是十六进制字符串,而Decrypt_AES_256函数直接将其作为字节处理。fmt.Sprintf("%X\n", cipherText)生成的字符串包含十六进制字符和换行符,需要先解码为原始字节。

以下是修正后的解密函数:

package main

import (
    "crypto/aes"
    "crypto/cipher"
    "encoding/hex"
    "fmt"
    "github.com/kkaskdf/zeus"
    "log"
)

func Decrypt_AES_256(cipherText_String string, key string) (plainText string) {
    // 解码十六进制字符串
    cipherText_byte, err := hex.DecodeString(cipherText_String)
    if err != nil {
        log.Fatal(err)
    }
    
    final_key := zeus.GenerateKey(key)
    cipher1, err := aes.NewCipher(final_key)
    if err != nil {
        log.Fatal(err)
    }
    
    gcmDecrypt, err := cipher.NewGCM(cipher1)
    if err != nil {
        log.Fatal(err)
    }
    
    nonceSize := gcmDecrypt.NonceSize()
    if len(cipherText_byte) < nonceSize {
        log.Fatal("ciphertext too short")
    }
    
    nonce, encryptedMessage := cipherText_byte[:nonceSize], cipherText_byte[nonceSize:]
    plaintext, err := gcmDecrypt.Open(nil, nonce, encryptedMessage, nil)
    if err != nil {
        log.Fatal(err)
    }
    
    return string(plaintext)
}

func main() {
    password := "This is the password"
    plainText := "Hi man Can 32 Hi man Can 23 Hi man Can"
    cipherText := zeus.Encrypt_AES_256(plainText, password)
    
    // 移除换行符
    cipherText = cipherText[:len(cipherText)-1]
    
    fmt.Printf("密文: %v\n", cipherText)
    fmt.Printf("明文: %v\n", Decrypt_AES_256(cipherText, password))
}

同时建议修改Encrypt_AES_256函数,移除末尾的换行符:

func Encrypt_AES_256(plainText string, key string) (cipherText_String string) {
    // ... 原有代码 ...
    cipherText := gcm.Seal(nonce, nonce, plainText_bytes, nil)
    cipherText_String = fmt.Sprintf("%X", cipherText) // 移除\n
    return cipherText_String
}

主要问题:

  1. 加密返回的十六进制字符串包含换行符\n
  2. 解密时未将十六进制字符串解码为字节
  3. 解密函数中对nonce和encryptedMessage进行了不必要的类型转换

修正后应该能正常解密。

回到顶部