1 回答

TA貢獻1880條經(jīng)驗 獲得超4個贊
在線工具結(jié)果的密文,如果是明文:
aaaaaaaaaaaa{"key1": "value1", "key2": "value2"}
用 PKCS#7 填充,發(fā)布的密鑰和 IV 是 UTF8 編碼的。由于明文的大小(48 字節(jié))已經(jīng)是塊大?。ˋES 為 16 字節(jié))的整數(shù)倍,因此根據(jù)PKCS#7 填充規(guī)則填充一個完整的塊,從而產(chǎn)生 64 字節(jié)的明文和密文。
從問題中不清楚使用的是哪種在線工具,但可以使用任何可靠的加密工具(例如 CyberChef,s。這個在線計算。CyberChef 默認為 AES/CBC 應(yīng)用 PKCS#7 填充。
發(fā)布的代碼會產(chǎn)生不同的密文,因為:
沒有應(yīng)用 PKCS#7 填充。這使得密文短了一個塊(即最后一個塊ccd202bac41937be75731f23796f1516丟失了)。
aes.BlockSize + len(plaintext)
為密文分配了字節(jié)大小。這導(dǎo)致分配的大小字節(jié)太大aes.BlockSize
(即密文末尾包含 16 個 0x00 值)。
因此,要使 Go 代碼生成與在線工具相同的密文,1. 必須添加 PKCS#7 填充,并且 2.len(plaintext)
必須為密文分配僅字節(jié)的大小。
以下代碼是一個可能的實現(xiàn)(對于 PKCS#7 ,使用pkcs7pad填充):
import (
...
"github.com/zenazn/pkcs7pad"
)
...
key := []byte("b8ae2fe8669c0401fb289e6ab6247924")
iv := []byte("e0332fc2a9743e4f")
plaintext := []byte("aaaaaaaaaaaa{\"key1\": \"value1\", \"key2\": \"value2\"}")
plaintext = pkcs7pad.Pad(plaintext, aes.BlockSize) // 1. pad the plaintext with PKCS#7
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
ciphertext := make([]byte, len(plaintext)) // 2. allocate len(plaintext)
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext, plaintext)
fmt.Printf("%x\n", ciphertext) // caf8fe667f4087e1b67d8c9c57fcb1f56b368cafb4bfecbda1e481661ab7b93d87703fb140368d3034d5187c53861c74ccd202bac41937be75731f23796f1516
請注意,由于 PKCS#7 填充,a不再需要顯式填充。
上述代碼中使用的靜態(tài)IV 是一個漏洞,因為它會導(dǎo)致密鑰/IV 對的重用,這是不安全的。因此,在實踐中,通常會為每次加密生成一個隨機 IV。IV 不是秘密的,是解密所必需的,并且通常與密文連接在一起。在解密端,將IV和密文分開,用于解密。
由于 IV 的大小對應(yīng)于塊大小,aes.BlockSize + len(plaintext)因此必須為密文分配一個大小,它等于原始代碼中的大小??赡苓@不是偶然的,而是在設(shè)計時考慮了隨機 IV,但后來沒有實現(xiàn)。一個后續(xù)的實現(xiàn)是:
import (
...
"crypto/rand"
"io"
"github.com/zenazn/pkcs7pad"
)
...
key := []byte("b8ae2fe8669c0401fb289e6ab6247924")
plaintext := []byte("{\"key1\": \"value1\", \"key2\": \"value2\"}")
plaintext = pkcs7pad.Pad(plaintext, aes.BlockSize)
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
_, err = io.ReadFull(rand.Reader, iv) // create a random IV
if err != nil {
panic(err)
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
fmt.Printf("%x\n", ciphertext)
輸出的前 16 個字節(jié)對應(yīng)于(隨機)IV,其余對應(yīng)于實際密文。
- 1 回答
- 0 關(guān)注
- 274 瀏覽
添加回答
舉報