Шифрование сообщения, содержащего открытый ключ с другим открытым ключом

У меня есть две асимметричные пары ключей client_key, A и another_key, B.
I want to send a encrypt a dict with B’s public key. Однако дикт должен содержать открытый ключ A, как показано в следующем примере:

message_dict = {
  'hostname': socket.getfqdn(),
  'request': 'MY_REQUEST',
  'client_pub_key': client_key.publickey().exportKey(),
}

Я сделал a json.dumpsиз вышеперечисленного и зашифровал с открытым ключом B. После того, как я расшифрую его, я не получу то же самое сообщение. Я заметил, что все идет не так, только если я включаю client_pub_keyв дикт.

Я искал ответы в интернете, и, возможно, поэтому это может быть неправильно:

  • Сообщение слишком длинно для шифрования с открытым ключом B
  • client_pub_keyИмеет специальные символы, что приводит к ситуации, когда кодировка JSON запутана

Я попробовал следующее:

  • Используется pickleвместо JSON
  • Используется binascii.hexlifyдля кодирования client_pub_key
  • Используется base64.b64encodeдля кодирования client_pub_key
  • Используется Crypto.Util.RFC1751.key_to_englishдля преобразования в некоторые символы client_pub_key
  • Установите ключ B 2048 байт и ключ A 1024 байта

Все вышеперечисленные усилия не увенчались успехом. Поэтому я здесь в поисках помощи.

Мой вопрос: как зашифровать сообщение вышеуказанного формата dict, чтобы я мог отправить его на сервер?
(Я использую бережливость TTornadoStreamTransportиTBinaryProtocol, если это поможет)

Фрагмент кода теста:

#!/usr/bin/env python

import base64
import binascii
import json
import pickle
import socket

from Crypto.PublicKey import RSA
from Crypto.Util.RFC1751 import key_to_english

client_key = RSA.generate(1024)

message_dict = {
  'hostname': socket.getfqdn(),
  'request': 'MY_REQUEST',
  'client_pub_key': int(binascii.hexlify(client_key.publickey().exportKey()),16),
}

another_key = RSA.generate(2048)

print 'nnDICT: {0}'.format(message_dict)
message = json.dumps(message_dict)

print 'nnMESSAGE: {0}'.format(message)
encrypted = another_key.publickey().encrypt(message, 32)[0]

print 'nnENCRYPTED: {0}'.format(encrypted)

decrypted = another_key.decrypt(encrypted)
print 'nnMESSAGE: {0}'.format(decrypted)

result = json.loads(decrypted)
print 'nnDICT: {0}'.format(result)
# result should be same message_dict

1 ответ

  1. Ваша проблема будет состоять в том, что сообщение, которое вы пытаетесь зашифровать, никогда не должно быть больше n-модуля!

    Потому что:

    cipher = сообщение * * e (mod N)

    Если ваше сообщение численно больше, чем модуль RSA (в вашем случае 2048 бит — не байт), вы не получите правильный зашифрованный текст, и декрипция никогда не будет работать. (математически)

    В вашем случае это происходит.

    Вы должны быть осторожны, потому что я думаю, что после json.dumps() сообщение не должно быть больше (в вашем случае another_key 2048bit) 2048//8 = 256 байт длиной — вы можете проверить его после json.dumps () через len (сообщение).
    В приведенном выше примере длина сообщения будет больше 700 байт… и 700 > 256.

    Просто, чтобы показать смысл этого:
    сначала попробуйте сообщение длиной ровно 256байт:

    >>> import json
    >>> from Crypto.PublicKey import RSA
    >>> another_key = RSA.generate(2048)
    >>> message_dict = {'t':'a'*248}
    >>> message = json.dumps(message_dict)
    >>> len(str(message))
    256
    >>> enc = another_key.publickey().encrypt(message, 32)[0]
    >>> dec = another_key.decrypt(enc)
    

    Вы увидите, что в этом примере длина сообщения составляет ровно 256 байт (не бит, а 256*8 = 2048 бит) — и это работает отлично!

    Но теперь попробуем длину 257 байт (больше длины n по модулю (2048 бит = 256 байт):

    >>> import json
    >>> from Crypto.PublicKey import RSA
    >>> another_key = RSA.generate(2048)
    >>> message_dict = {'t':'a'*249}
    >>> message = json.dumps(message_dict)
    >>> len(str(message))
    257
    >>> enc = another_key.publickey().encrypt(message, 32)[0]
    >>> dec = another_key.decrypt(enc)
    

    В этом случае dec != enc — потому что сообщение численно больше, чем N по модулю.

    Если вы математически поймете причину этого, посмотрите в значении » шифр = сообщение * * e (mod N)» 😉