обмен открытым/закрытым ключом в шифровании/дешифровании PKCS#1 OAEP

У меня есть только очень рудиментарные теоретические знания о RSA.

При чтении различных источников о том, как его использовать на практике, казалось, что PKCS#1 OAEP будет хорошей вещью.

Для тестовой реализации я использую Python с PyCrypto. Например. этоявляется примером использования PKCS#1 OAEP.

Шифрование с использованием открытого ключа, а затем расшифровка с использованием закрытого ключа работает нормально. Например. общественность может отправить некоторые данные человеку X с закрытым ключом.

Исходя из моего базового понимания того, как работает RSA, я подумал, что могу просто поменять местами открытый и закрытый ключи, т. е. я могу использовать открытый ключ для шифрования и закрытый ключ для расшифровки. Например. человек X может зашифровать некоторые данные своим закрытым ключом, а публичный может расшифровать их с помощью открытого ключа. Если расшифровка работает нормально, это дает какое-то доказательство того, что данные исходят от человека X.

PyCrypto жалуется, когда я пытаюсь расшифровать с помощью открытого ключа.

Из исходного кода PyCrypto в функции _RSAKey._decrypt( здесь) кажется, что объект ключа сам знает, является ли он закрытым или открытым ключом, и отличается между ними (к моему удивлению, опять же на основе моего очень простого понимания RSA).

Отсюда, похоже, я могу взломать функцию расшифровки, чтобы она использовала открытый ключ.Или несколько иначе: я мог бы просто поменять местами открытый показатель eи частный показатель dв ключевых объектах.

Но похоже, что все это не предназначено для использования/взлома таким образом. Поэтому я хотел спросить здесь о моих недоразумениях.

Кроме того, просто из любопытства я сгенерировал несколько ключей ( RSA.generate(2048)) и посмотрел на n, eи д . Во всех случаях nи dбыли очень большими, в то время как eбыло во всех случаях постоянным(65537) (я бы не стал ожидал этого).

Из всего этого я догадываюсь, что мне действительно не следует просто менять местами eи d.

Так что я думаю, мне следует использовать какой-то другой метод для подписи, такой как PKCS1_PSS.


Код для шифрования/дешифрования, если кому интересно:

def randomString(l):
    import random
    return ''.join(chr(random.randint(0, 0xFF)) for i in range(l))

def genkeypair():
    from Crypto.PublicKey import RSA
    key = RSA.generate(2048)
    pubkey = key.publickey().exportKey("DER")
    privkey = key.exportKey("DER")
    return (pubkey,privkey)

def encrypt(v, rsapubkey):
    from Crypto.PublicKey import RSA
    rsakey = RSA.importKey(rsapubkey)
    from Crypto.Cipher import PKCS1_OAEP
    rsa = PKCS1_OAEP.new(rsakey)
    import binstruct
    from array import array
    aeskey = randomString(32)
    iv = randomString(16)
    from Crypto.Cipher import AES
    aes = AES.new(aeskey, AES.MODE_CBC, iv)
    data = binstruct.varEncode(v)
    data += array("B", (0,) * (-len(data) % 16))
    out = binstruct.strEncode(rsa.encrypt(aeskey + iv))
    out += array("B", aes.encrypt(data))
    return out

def decrypt(stream, rsaprivkey):
    from array import array
    from StringIO import StringIO
    if isinstance(stream, array): stream = stream.tostring()
    if isinstance(stream, str): stream = StringIO(stream)
    from Crypto.PublicKey import RSA
    rsakey = RSA.importKey(rsaprivkey)
    from Crypto.Cipher import PKCS1_OAEP
    rsa = PKCS1_OAEP.new(rsakey)
    import binstruct
    aesdata = binstruct.strDecode(stream)
    aesdata = rsa.decrypt(aesdata)
    aeskey = aesdata[0:32]
    iv = aesdata[32:]
    from Crypto.Cipher import AES
    aes = AES.new(aeskey, AES.MODE_CBC, iv)
    class Stream:
        buffer = []
        def read1(self):
            if len(self.buffer) == 0:
                nextIn = stream.read(16)
                self.buffer += list(aes.decrypt(nextIn))
            return self.buffer.pop(0)
        def read(self, n):
            return "".join([self.read1() for i in range(n)])
    v = binstruct.varDecode(Stream())
    return v

(binstruct— небольшой модуль, который может кодировать/декодировать древовидные структуры данных — аналогично JSON/BSON.)

Именно здесь я подумал, что могу просто использовать шифрованиес закрытым ключом и дешифрованиес открытым ключом.


Окончательную реализацию с (надеюсь) правильной подписью/аутентификацией можно найти здесь в binstruct.

9
задан Albert 15 March 2014 в 14:42
поделиться