Reputation: 4607
Trying to emulate an algorithm in Go that is basically AES ECB Mode encryption.
Here's what I have so far
func Decrypt(data []byte) []byte {
cipher, err := aes.NewCipher([]byte(KEY))
if err == nil {
cipher.Decrypt(data, PKCS5Pad(data))
return data
}
return nil
}
I also have a PKCS5Padding algorithm, which is tested and working, which pads the data first. I cant find any information on how to switch the encryption mode in the Go AES package (it's definitely not in the docs).
I have this code in another language, which is how I know this algorithm isn't working quite correctly.
EDIT: Here is the method as I have interpreted from on the issue page
func AESECB(ciphertext []byte) []byte {
cipher, _ := aes.NewCipher([]byte(KEY))
fmt.Println("AESing the data")
bs := 16
if len(ciphertext)%bs != 0 {
panic("Need a multiple of the blocksize")
}
plaintext := make([]byte, len(ciphertext))
for len(plaintext) > 0 {
cipher.Decrypt(plaintext, ciphertext)
plaintext = plaintext[bs:]
ciphertext = ciphertext[bs:]
}
return plaintext
}
This is actually not returning any data, maybe I screwed something up when changing it from encripting to decripting
Upvotes: 12
Views: 19810
Reputation: 1
Ideally you want to implement the crypto/cipher#BlockMode interface. Since an official one doesn't exist, I used crypto/cipher#NewCBCEncrypter as a starting point:
package ecb
import "crypto/cipher"
type ecbEncrypter struct { cipher.Block }
func newECBEncrypter(b cipher.Block) cipher.BlockMode {
return ecbEncrypter{b}
}
func (x ecbEncrypter) BlockSize() int {
return x.Block.BlockSize()
}
func (x ecbEncrypter) CryptBlocks(dst, src []byte) {
size := x.BlockSize()
if len(src) % size != 0 {
panic("crypto/cipher: input not full blocks")
}
if len(dst) < len(src) {
panic("crypto/cipher: output smaller than input")
}
for len(src) > 0 {
x.Encrypt(dst, src)
src, dst = src[size:], dst[size:]
}
}
Upvotes: 1
Reputation: 99195
Why? We left ECB out intentionally: it's insecure, and if needed it's trivial to implement.
https://github.com/golang/go/issues/5597
Upvotes: 8
Reputation: 1022
Electronic codebook ("ECB") is a very straightforward mode of operation. The data to be encrypted is divided into byte blocks, all having the same size. For each block, a cipher is applied, in this case AES, generating the encrypted block.
The code snippet below decrypts AES-128 data in ECB (note that the block size is 16 bytes):
package main
import (
"crypto/aes"
)
func DecryptAes128Ecb(data, key []byte) []byte {
cipher, _ := aes.NewCipher([]byte(key))
decrypted := make([]byte, len(data))
size := 16
for bs, be := 0, size; bs < len(data); bs, be = bs+size, be+size {
cipher.Decrypt(decrypted[bs:be], data[bs:be])
}
return decrypted
}
As mentioned by @OneOfOne, ECB is insecure and very easy to detect, as repeated blocks will always encrypt to the same encrypted blocks. This Crypto SE answer gives a very good explanation why.
Upvotes: 11
Reputation: 1
I was confused by a couple of things.
First i needed a aes-256 version of the above algorithm, but apparently the aes.Blocksize (which is 16) won't change when the given key has length 32. So it is enough to give a key of length 32 to make the algorithm aes-256
Second, the decrypted value still contains padding and the padding value changes depending on the length of the encrypted string. E.g. when there are 5 padding characters the padding character itself will be 5.
Here is my function which returns a string:
func DecryptAes256Ecb(hexString string, key string) string {
data, _ := hex.DecodeString(hexString)
cipher, _ := aes.NewCipher([]byte(key))
decrypted := make([]byte, len(data))
size := 16
for bs, be := 0, size; bs < len(data); bs, be = bs+size, be+size {
cipher.Decrypt(decrypted[bs:be], data[bs:be])
}
// remove the padding. The last character in the byte array is the number of padding chars
paddingSize := int(decrypted[len(decrypted)-1])
return string(decrypted[0 : len(decrypted)-paddingSize])
}
Upvotes: -2
Reputation: 41
I used your code so I feel the need to show you how I fixed it.
I am doing the cryptopals challenges for this problem in Go.
I'll walk you through the mistake since the code is mostly correct.
for len(plaintext) > 0 {
cipher.Decrypt(plaintext, ciphertext)
plaintext = plaintext[bs:]
ciphertext = ciphertext[bs:]
}
The loop does decrypt the data but does not put it anywhere. It simply shifts the two arrays along producing no output.
i := 0
plaintext := make([]byte, len(ciphertext))
finalplaintext := make([]byte, len(ciphertext))
for len(ciphertext) > 0 {
cipher.Decrypt(plaintext, ciphertext)
ciphertext = ciphertext[bs:]
decryptedBlock := plaintext[:bs]
for index, element := range decryptedBlock {
finalplaintext[(i*bs)+index] = element
}
i++
plaintext = plaintext[bs:]
}
return finalplaintext[:len(finalplaintext)-5]
What this new improvement does is store the decrypted data into a new []byte called finalplaintext. If you return that you get the data.
It's important to do it this way since the Decrypt function only works one block size at a time.
I return a slice because I suspect it's padded. I am new to cryptography and Go so anyone feel free to correct/revise this.
Upvotes: 4