英文:
Golang- AES Decryption is not returning same Text
问题
我正在遵循这个文档,尝试使用Go语言实现简单的AES加密和解密。对于普通文本,它运行良好,但对于UUID则不行。希望能解决这个问题,并了解为什么会出现这种情况。这是我的示例代码:
package main
import (
"crypto/aes"
"encoding/hex"
"fmt"
)
func main() {
key := "thisis32bitlongpassphraseimusing"
pt := "a30a1777-e9f4-ed45-4755-add00172ebae"
c := EncryptAES([]byte(key), pt)
fmt.Println(pt)
fmt.Println(c)
DecryptAES([]byte(key), c)
}
func EncryptAES(key []byte, plaintext string) string {
c, err := aes.NewCipher(key)
CheckError(err)
out := make([]byte, len(plaintext))
c.Encrypt(out, []byte(plaintext))
return hex.EncodeToString(out)
}
func DecryptAES(key []byte, ct string) {
ciphertext, _ := hex.DecodeString(ct)
c, err := aes.NewCipher(key)
CheckError(err)
pt := make([]byte, len(ciphertext))
c.Decrypt(pt, ciphertext)
s := string(pt[:])
fmt.Println("DECRYPTED:", s)
}
func CheckError(err error) {
if err != nil {
panic(err)
}
}
以下是输出结果:
a30a1777-e9f4-ed45-4755-add00172ebae
e0f32a5bcf576754da4206cc967157ae0000000000000000000000000000000000000000
DECRYPTED: a30a1777-e9f4-ed
正如你所看到的,UUID的最后一部分消失了。我附上了一个截图,说明它没有正确解密最后一部分。 有人知道这背后的原因吗?我看到了一个类似的问题,但不完全相同。
英文:
I am following this documentation and was trying to implement a simple AES encryption and decryption with using GoLang. For plain text it is working fine however, for UUID it is not working. Excepting a resolution of this and why this is happening. Here is my sample code
package main
import (
"crypto/aes"
"encoding/hex"
"fmt"
)
func main() {
key := "thisis32bitlongpassphraseimusing"
pt := "a30a1777-e9f4-ed45-4755-add00172ebae"
c := EncryptAES([]byte(key), pt)
fmt.Println(pt)
fmt.Println(c)
DecryptAES([]byte(key), c)
}
func EncryptAES(key []byte, plaintext string) string {
c, err := aes.NewCipher(key)
CheckError(err)
out := make([]byte, len(plaintext))
c.Encrypt(out, []byte(plaintext))
return hex.EncodeToString(out)
}
func DecryptAES(key []byte, ct string) {
ciphertext, _ := hex.DecodeString(ct)
c, err := aes.NewCipher(key)
CheckError(err)
pt := make([]byte, len(ciphertext))
c.Decrypt(pt, ciphertext)
s := string(pt[:])
fmt.Println("DECRYPTED:", s)
}
func CheckError(err error) {
if err != nil {
panic(err)
}
}
And here is the output
a30a1777-e9f4-ed45-4755-add00172ebae
e0f32a5bcf576754da4206cc967157ae0000000000000000000000000000000000000000
DECRYPTED: a30a1777-e9f4-ed
As you can see in the remaining last part of the UUID is disappearing. I have attached as a snap which says it didn't decrypt the last part properly. Does anyone know reasoning behind this? I have seen a close question like that but not and exactly one.
答案1
得分: 3
如果你查看AES分组密码的页面,你会发现aes.NewCipher
返回一个Block
,正如Jake在评论中提到的那样。
现在,如果你转到那个页面,你会看到该页面指出了各种可以用来将块密码创建为真正安全的密码的模式。块密码只处理数据块,对于AES来说,数据块始终是128位/16字节。所以这就是为什么密文后面有那么多零的原因,它只加密了16字节的数据。请注意,密文应该始终看起来像是随机的字节。
不幸的是,它没有直接列出认证(AEAD)模式,所以请在这里也查看一下。也就是说,你可以看到CTR模式在其中,包括示例,这是问题和我之前回答中缺少的主要内容。你的代码中没有显示出任何操作模式,尤其不是计数器模式。
英文:
If you look at the page for the AES block cipher you'll find out that aes.NewCipher
returns a Block
as mentioned by Jake in the comments.
Now if you go to that page you'll see that this page points out various modes that you can use to create a real, secure cipher out of a block cipher. A block cipher only handles blocks of data, which are always 128 bits / 16 bytes in the case of AES. So this is precisely why there are all those zero's after the ciphertext, it encrypted 16 bytes and that was that. Note that ciphertext should always look as randomized bytes.
Unfortunately it doesn't directly list the authenticated (AEAD) modes, so please take a look here as well. That said, you can see that CTR mode is in there including examples, and that's the main idea missing from the question + my answer that you've linked to. Nothing in your code shows a mode of operation, and certainly not counter mode.
答案2
得分: -1
你的代码问题在于AES加密要求输入的长度必须是块大小的倍数(对于AES-128来说是16字节),但你尝试加密的UUID("a30a1777-e9f4-ed45-4755-add00172ebae")长度为36字节,这导致了加密出错。
修复这个问题的一种方法是在加密之前对明文进行填充,使其长度成为块大小的倍数。Go标准库中有一个名为crypto/padding的包,提供了用于给明文添加填充的函数。
你可以像这样修改你的EncryptAES函数:
func EncryptAES(key []byte, plaintext string) string {
c, err := aes.NewCipher(key)
CheckError(err)
plaintextBytes := []byte(plaintext)
// 添加填充到明文
blockSize := c.BlockSize()
padding := blockSize - (len(plaintextBytes) % blockSize)
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
plaintextBytes = append(plaintextBytes, padtext...)
out := make([]byte, len(plaintextBytes))
c.Encrypt(out, plaintextBytes)
return hex.EncodeToString(out)
}
然后在DecryptAES函数中,在解密密文之前,你可以移除填充,像这样:
func DecryptAES(key []byte, ct string) {
ciphertext, _ := hex.DecodeString(ct)
c, err := aes.NewCipher(key)
CheckError(err)
pt := make([]byte, len(ciphertext))
c.Decrypt(pt, ciphertext)
// 移除填充
padLen := int(pt[len(pt)-1])
s := string(pt[:len(pt)-padLen])
fmt.Println("解密结果:", s)
}
至于填充方案,你可以尝试使用pkcs#5或pkcs#7填充方案。
英文:
The problem with your code is that AES encryption requires the input to be a multiple of the block size (16 bytes for AES-128), but the UUID you're trying to encrypt ("a30a1777-e9f4-ed45-4755-add00172ebae")is 36 bytes long and it is causing the cipher to error.
One way to fix this issue is by padding the plaintext so that its length is a multiple of the block size before encryption. The Go standard library has a package called crypto/padding that provides functions for adding padding to plaintext.
You can modify your EncryptAES function like this:
func EncryptAES(key []byte, plaintext string) string {
c, err := aes.NewCipher(key)
CheckError(err)
plaintextBytes := []byte(plaintext)
// Add padding to plaintext
blockSize := c.BlockSize()
padding := blockSize - (len(plaintextBytes) % blockSize)
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
plaintextBytes = append(plaintextBytes, padtext...)
out := make([]byte, len(plaintextBytes))
c.Encrypt(out, plaintextBytes)
return hex.EncodeToString(out)
}
Then in the DecryptAES function, you can remove the padding before decrypting the ciphertext like this:
func DecryptAES(key []byte, ct string) {
ciphertext, _ := hex.DecodeString(ct)
c, err := aes.NewCipher(key)
CheckError(err)
pt := make([]byte, len(ciphertext))
c.Decrypt(pt, ciphertext)
//Remove padding
padLen := int(pt[len(pt)-1])
s := string(pt[:len(pt)-padLen])
fmt.Println("DECRYPTED:", s)
}
As for padding schemes, you might want to try padding scheme like pkcs#5 or pkcs#7.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论