I am adding a go application to an already existing python codebase. I\'ve been having trouble dealing with encryption between the languages. This is using go 1.2.1 and Pyth
It seems that the cipher can be made compatible to Go's crypto/cipher if we change segment_size of AES object from the default 8 to AES.block_size*8 (which is 128), like this:
Crypto.Cipher.AES.new(
key=password,
mode=Crypto.Cipher.AES.MODE_CFB,
IV=iv,
segment_size=AES.block_size*8
)
Research on the current system has revealed that our python system uses CFB8 (8 bit segments). Go does not support this out of the box, but the source code used in the current CFBDecrypter / CFBEncrypter looks like it can be adapted fairly easily.
I found that easiest way to deal with this from Python side is to use M2Crypto library.
Final code looks like:
import M2Crypto.EVP
iv = ciphertext[:16]
ciphertext = ciphertext[16:]
cipher = M2Crypto.EVP.Cipher('aes_256_cfb', t, iv, 0)
text = cipher.update(ciphertext)
print text
Works perfect without need to change something in Go.
i solve by adapt python code like this (golang encode and python decode):
# golang encode
padNum := len(data) % 16
if padNum != 0 {
for i := 0; i < 16-padNum; i++ {
data = append(data, ',')
}
}
# python decode
cipher = AES.new(key=self.key, mode=AES.MODE_CFB, IV=iv,segment_size=128)
If anyone is looking for Go implementation of CFB mode with segment size = 8 you can use this:
import "crypto/cipher"
// CFB stream with 8 bit segment size
// See http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
type cfb8 struct {
b cipher.Block
blockSize int
in []byte
out []byte
decrypt bool
}
func (x *cfb8) XORKeyStream(dst, src []byte) {
for i := range src {
x.b.Encrypt(x.out, x.in)
copy(x.in[:x.blockSize-1], x.in[1:])
if x.decrypt {
x.in[x.blockSize-1] = src[i]
}
dst[i] = src[i] ^ x.out[0]
if !x.decrypt {
x.in[x.blockSize-1] = dst[i]
}
}
}
// NewCFB8Encrypter returns a Stream which encrypts with cipher feedback mode
// (segment size = 8), using the given Block. The iv must be the same length as
// the Block's block size.
func newCFB8Encrypter(block cipher.Block, iv []byte) cipher.Stream {
return newCFB8(block, iv, false)
}
// NewCFB8Decrypter returns a Stream which decrypts with cipher feedback mode
// (segment size = 8), using the given Block. The iv must be the same length as
// the Block's block size.
func newCFB8Decrypter(block cipher.Block, iv []byte) cipher.Stream {
return newCFB8(block, iv, true)
}
func newCFB8(block cipher.Block, iv []byte, decrypt bool) cipher.Stream {
blockSize := block.BlockSize()
if len(iv) != blockSize {
// stack trace will indicate whether it was de or encryption
panic("cipher.newCFB: IV length must equal block size")
}
x := &cfb8{
b: block,
blockSize: blockSize,
out: make([]byte, blockSize),
in: make([]byte, blockSize),
decrypt: decrypt,
}
copy(x.in, iv)
return x
}