-
Notifications
You must be signed in to change notification settings - Fork 18k
crypto/cipher: AES encrypted cipher text in CFB mode is incorrect #30201
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
/cc @FiloSottile |
Can you provide some details on the other tools you compared against? An example showing a failure would be great. |
CFB is a stream cipher, the error is almost certainly in your padding function, which is not supported for AES block sizes.
PKCS5 padding does not support arbitrary block sizes. It only supports size 8. I have compared the CFB output to a clean re-implementation using a block diagram along with ecb mode: half of the code can be found here: https://play.golang.org/p/hn422wOs6NI The output of the stream is identical to what one would get with stdlib CFB. See rfc2898 for more details. |
@FiloSottile |
Because the result of running in CFB and OFB mode is the same, I think it is a bug. package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"fmt"
)
func main() {
var key = "1234567887654321"
var vector = "8765432112345678"
var info = "AES in CFB mode"
Enc_str := EncryptAES_OFB(info, key, vector)
fmt.Println(Enc_str)
Dec_str := DecryptAES_OFB(Enc_str, key, vector)
fmt.Println(Dec_str)
}
func EncryptAES_OFB(src, key, vector string) string {
data := []byte(src)
iv := []byte(vector)
keyByte := []byte(key)
block, err := aes.NewCipher(keyByte)
if err != nil {
panic(err)
}
data = PKCS5Padding(data, block.BlockSize())
ciphertext := make([]byte, len(data))
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(ciphertext, data)
return fmt.Sprintf("%X", ciphertext)
}
func DecryptAES_OFB(src, key, vector string) string {
keyByte := []byte(key)
iv := []byte(vector)
data, err := hex.DecodeString(src)
if err != nil {
panic(err)
}
block, err := aes.NewCipher(keyByte)
if err != nil {
panic(err)
}
plaintext := make([]byte, len(data))
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(plaintext, data)
plaintext = PKCS5UnPadding(plaintext)
return string(plaintext)
}
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
} |
That's because it's based on the first block, and the operations on that block result in identical output from both modes. Try it with a bigger plaintext. |
@as |
OpenSSL agrees with Go: https://play.golang.org/p/q0R-wgj2BcQ I think you are encountering encoding or implementation issues in your web tools. They do not pass FIPS test vectors and their input format is ambiguous (is it hex? Base64?). Because openSSL outputs the same ciphertext as Go, I think that this is not a Go issue. |
@as |
The text was updated successfully, but these errors were encountered: