2016-03-05 1 views
2

Я работаю над проектом для удовольствия. Сервер golang и клиент python. Я хочу, чтобы передаваемые данные были зашифрованы, но, похоже, не работают две схемы шифрования. Я новичок, когда дело доходит до шифрования, поэтому, пожалуйста, объясните, как вы разговариваете с малышами.AES Шифрование 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 

я наклоняю достаточно выяснить, выход из моих функций питона либо. Мои ходы работают отлично. Но я хочу, чтобы иметь возможность шифровать в Go дешифровать в python и наоборот.

Пример вывода из Python:

INIT KEY61736466617364666173646661736466 
RAW STRING: 54657374206d657373616765 
ECRYPTED STRING: dfee33dd40c32fbaf9aac73ac4e0a5a9fc7bd2947d29005dd8d8e21a 
dfee33dd40c32fbaf9aac73ac4e0a5a9fc7bd2947d29005dd8d8e21a 
DECRYPTED STRING: 77d899b990d2d3172a3229b1b69c6f2554657374206d657373616765 
77d899b990d2d3172a3229b1b69c6f2554657374206d657373616765 
wØ™¹�ÒÓ*2)±¶œo%Test message 

Как вы можете увидеть сообщение расшифрованы, но заканчивается в конце строки?

EDIT: Образец выходного расшифровки с GO. Если я попытаться расшифровать с GO ниже (генерируемся с Python)

ECRYPTED STRING: (Test Message) 7af474bc4c8ea9579d83a3353f83a0c2844f8efb019c82618ea0b478 

Я получаю

Decrypted Payload: 54 4E 57 9B 90 F8 D6 CD 12 59 0B B1 
Decrypted Payload: TNW�����Y� 

Странная части является первым символом всегда правильно

здесь являются полными проектами :

Github

+1

Я настоятельно рекомендую вам использовать https://godoc.org/golang.org/x/crypto/nacl/secretbox и https://pynacl.readthedocs.org/en/latest/ (для Python), если вам нужно зашифровать сообщения. – elithrar

ответ

3

Вы забыли отрезать IV во время дешифрования в Python. Изменение

x=(cipher.decrypt(enc)) 

в

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

или

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

Эти два предложения эквивалентны для таких режимов, как CFB (с полным блочным сдвиговым регистром) и CBC, но не будут работать для таких режимов, как CTR. В этом случае перейдите к первому. –

+0

спасибо, что помогли с частью python, я сделал надпись для расшифровки с помощью Go. Благодаря! – stihl

1

Python использует 8-битные сегменты в то время как Go использует 128-битные сегменты так, по причине первые работы характера, но следующие из них надевают 't состоит в том, что каждый сегмент зависит от предыдущего и, следовательно, другой размер сегмента разбивает цепочку.

Я сделал эти безопасные URL (кодирование без кодирования base64) для шифрования/дешифрования функций для Python, чтобы, при необходимости, шифровать так же, как и 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 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^