亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

AES 加密 Golang 和 Python

AES 加密 Golang 和 Python

Go
海綿寶寶撒 2021-12-20 15:11:16
我正在為自己做一個有趣的副項目。一個 golang 服務器和一個 python 客戶端。我希望傳輸的數據被加密,但似乎無法讓這兩種加密方案協同工作。我是加密方面的新手,所以請像在和蹣跚學步的孩子交談一樣解釋。這是我的 golang 加密函數:import (    "crypto/aes"    "crypto/cipher"    "crypto/rand"    "errors"    "io"    "fmt")func Encrypt(key, text []byte) (ciphertext []byte, err error) {    var block cipher.Block    if block, err = aes.NewCipher(key); err != nil {        return nil, err    }    ciphertext = make([]byte, aes.BlockSize+len(string(text)))    iv := ciphertext[:aes.BlockSize]    fmt.Println(aes.BlockSize)    if _, err = io.ReadFull(rand.Reader, iv); err != nil {        return    }    cfb := cipher.NewCFBEncrypter(block, iv)    cfb.XORKeyStream(ciphertext[aes.BlockSize:], text)    return}func Decrypt(key, ciphertext []byte) (plaintext []byte, err error) {    var block cipher.Block    if block, err = aes.NewCipher(key); err != nil {        return    }    if len(ciphertext) < aes.BlockSize {        err = errors.New("ciphertext too short")        return    }    iv := ciphertext[:aes.BlockSize]    ciphertext = ciphertext[aes.BlockSize:]    cfb := cipher.NewCFBDecrypter(block, iv)    cfb.XORKeyStream(ciphertext, ciphertext)    plaintext = ciphertext    return}這是我的 Python 實現: class AESCipher:    def __init__( self, key ):        self.key = key        print "INIT KEY" + hexlify(self.key)    def encrypt( self, raw ):        print "RAW STRING: " + hexlify(raw)        iv = Random.new().read( AES.block_size )        cipher = AES.new( self.key, AES.MODE_CFB, iv )        r = ( iv + cipher.encrypt( raw ) )        print "ECRYPTED STRING: " + hexlify(r)        return r    def decrypt( self, enc ):        enc = (enc)        iv = enc[:16]        cipher = AES.new(self.key, AES.MODE_CFB, iv)        x=(cipher.decrypt( enc ))        print "DECRYPTED STRING: " + hexlify(x)        return x我也無法弄清楚我的 python 函數的輸出。我的 Go 例程運行良好。但我希望能夠在 Go 中加密,在 python 中解密,反之亦然。如您所見,消息已解密,但最終出現在字符串的末尾?
查看完整描述

2 回答

?
幕布斯6054654

TA貢獻1876條經驗 獲得超7個贊

Python 使用 8 位段,而 Go 使用 128 位段,因此第一個字符起作用但后面的字符不起作用的原因是因為每個段都依賴于前一個,因此不同的段大小破壞了鏈。


我為 Python 制作了這些 URL 安全(非填充 base64 編碼)加密/解密函數,以便像 Go 一樣(當您指定時block_segments=True)有選擇地加密。


def decrypt(key, value, block_segments=False):

    # The base64 library fails if value is Unicode. Luckily, base64 is ASCII-safe.

    value = str(value)

    # We add back the padding ("=") here so that the decode won't fail.

    value = base64.b64decode(value + '=' * (4 - len(value) % 4), '-_')

    iv, value = value[:AES.block_size], value[AES.block_size:]

    if block_segments:

        # Python uses 8-bit segments by default for legacy reasons. In order to support

        # languages that encrypt using 128-bit segments, without having to use data with

        # a length divisible by 16, we need to pad and truncate the values.

        remainder = len(value) % 16

        padded_value = value + '\0' * (16 - remainder) if remainder else value

        cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)

        # Return the decrypted string with the padding removed.

        return cipher.decrypt(padded_value)[:len(value)]

    return AES.new(key, AES.MODE_CFB, iv).decrypt(value)



def encrypt(key, value, block_segments=False):

    iv = Random.new().read(AES.block_size)

    if block_segments:

        # See comment in decrypt for information.

        remainder = len(value) % 16

        padded_value = value + '\0' * (16 - remainder) if remainder else value

        cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128)

        value = cipher.encrypt(padded_value)[:len(value)]

    else:

        value = AES.new(key, AES.MODE_CFB, iv).encrypt(value)

    # The returned value has its padding stripped to avoid query string issues.

    return base64.b64encode(iv + value, '-_').rstrip('=')

請注意,為了安全的消息傳遞,您需要額外的安全功能,例如防止重放攻擊的隨機數。


以下是 Go 等效函數:


func Decrypt(key []byte, encrypted string) ([]byte, error) {

    ciphertext, err := base64.RawURLEncoding.DecodeString(encrypted)

    if err != nil {

        return nil, err

    }

    block, err := aes.NewCipher(key)

    if err != nil {

        return nil, err

    }

    if len(ciphertext) < aes.BlockSize {

        return nil, errors.New("ciphertext too short")

    }

    iv := ciphertext[:aes.BlockSize]

    ciphertext = ciphertext[aes.BlockSize:]

    cfb := cipher.NewCFBDecrypter(block, iv)

    cfb.XORKeyStream(ciphertext, ciphertext)

    return ciphertext, nil

}


func Encrypt(key, data []byte) (string, error) {

    block, err := aes.NewCipher(key)

    if err != nil {

        return "", err

    }

    ciphertext := make([]byte, aes.BlockSize+len(data))

    iv := ciphertext[:aes.BlockSize]

    if _, err := io.ReadFull(rand.Reader, iv); err != nil {

        return "", err

    }

    stream := cipher.NewCFBEncrypter(block, iv)

    stream.XORKeyStream(ciphertext[aes.BlockSize:], data)

    return base64.RawURLEncoding.EncodeToString(ciphertext), nil

}


查看完整回答
反對 回復 2021-12-20
?
PIPIONE

TA貢獻1829條經驗 獲得超9個贊

您忘記在 Python 解密期間切掉 IV。改變

x=(cipher.decrypt( enc ))

x = cipher.decrypt( enc[16:] )

或者

x = cipher.decrypt( enc )[16:]


查看完整回答
反對 回復 2021-12-20
  • 2 回答
  • 0 關注
  • 169 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號