使用AES-CFB时Go和Pycrypto中的不同结果

tnkciper  于 2022-12-16  发布在  Go
关注(0)|答案(5)|浏览(174)

我正在给一个已经存在的python代码库添加一个go应用程序,在处理语言之间的加密时遇到了一些问题,我使用的是go 1.2.1和Python 2.7.x / PyCrypto 2.7a1。
下面是Python示例:

import Crypto.Cipher
import Crypto.Hash.HMAC
import Crypto.Hash.SHA256
import Crypto.PublicKey.RSA
from binascii import hexlify, unhexlify

#encrypt
payload =  unhexlify("abababababababababababababababababababababababababababababababab")
password = unhexlify("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF")
iv = unhexlify("00000000000000000000000000000000")

print "IV: ", hexlify(iv), "len: ", len(iv)
print "Password length: ", len(password)

cipher = Crypto.Cipher.AES.new(
            key=password, 
            mode=Crypto.Cipher.AES.MODE_CFB, 
            IV=iv)

payload = cipher.encrypt(payload)

print hexlify(payload) #dbf6b1877ba903330cb9cf0c4f530d40bf77fe2bf505820e993741c7f698ad6b

这是围棋的例子:

package main

import (
    "fmt"
    "crypto/cipher"
    "crypto/aes"
    "encoding/hex"
)

// encrypt
func main() {
    payload, err1 := hex.DecodeString("abababababababababababababababababababababababababababababababab")
    password, err2 := hex.DecodeString("0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF")
    iv, err3 := hex.DecodeString("00000000000000000000000000000000")

    if err1 != nil {
        fmt.Printf("error 1: %v", err1)
        return
    }

    if err2 != nil {
        fmt.Printf("error 2: %v", err2)
        return
    }

    if err3 != nil {
        fmt.Printf("error 3: %v", err3)
        return
    }

    aesBlock, err4 := aes.NewCipher(password)

    fmt.Printf("IV length:%v\n", len(iv))
    fmt.Printf("password length:%v\n", len(password))

    if err4 != nil {
        fmt.Printf("error 4: %v", err4)
        return
    }

    cfbDecrypter := cipher.NewCFBEncrypter(aesBlock, iv)
    cfbDecrypter.XORKeyStream(payload, payload) 

    fmt.Printf("%v\n", hex.EncodeToString(payload)) // db70cd9e6904359cb848410bfa38d7d0a47b594f7eff72d547d3772c9d4f5dbe
}

这是golang link,我找不到安装了PyCrypto的Python粘贴框。
正如标题和源代码所示,这两个代码段生成不同的密文:
Python语言:
戈郎语:db 70 cd 9 e6904359 cb 848410 bfa 38 d 7 d 0a 47 b594 f7 eff 72 d547 d3772 c9 d4 f5 dbe
这两种语言都可以解密他们的“原生”密文,但都不能解密其他的“.因为python实现已经存在,我正在寻找一个解决方案,将允许Go解密用示例PyCrypto AES设置和密钥大小加密的密文.

dxpyg8gm

dxpyg8gm1#

对当前系统的研究表明,我们的python系统使用的是CFB 8(8位段),Go语言并不支持这种开箱即用的方式,但当前CFBDecrypter / CFBEncrypter使用的源代码看起来可以很容易地进行修改。

iyr7buue

iyr7buue2#

如果有人想在Go语言中实现段大小为8的CFB模式,可以使用以下代码:

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
}
xdnvmnnf

xdnvmnnf3#

如果我们把AES对象的segment_size从默认的8修改为AES.block_size*8(即128),似乎就可以使密码与Go语言的crypto/cipher兼容,如下所示:

Crypto.Cipher.AES.new(
            key=password, 
            mode=Crypto.Cipher.AES.MODE_CFB, 
            IV=iv,
            segment_size=AES.block_size*8
)
chy5wohz

chy5wohz4#

我发现从Python方面处理这个问题最简单的方法是使用M2Crypto库。
最终代码如下所示:

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

工作完美,不需要改变一些东西在围棋。

g52tjvyc

g52tjvyc5#

我通过如下修改python代码(golang编码和python解码)来解决:

# 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)

相关问题