如何解密用 RSA 加密的块?

How to decrypt blocks encrypted with RSA?

我还在做我的 RSA 项目,现在我可以成功创建密钥,并用它们加密字符串

def encrypt(clear_message, public_key):
    
    clear_list = convert_into_unicode (clear_message)
    
    n = public_key[0]
    e = public_key[1]

    message_chiffre = str()
    
    for i, value in enumerate (clear_list) :
        encrypted_value = str( pow (int(value), e, n) )

        encrypted_message += (encrypted_value )

    return encrypted_message 

def convert_into_unicode (clear_message):

    str_unicode = ''
    
    for car in clear_message:
        str_unicode += str (ord (car))
        
    if len (str_unicode ) % 5 != 0: 
        str_unicode += (5 - len (str_unicode ) % 5) * '0'
    
    clear_list = []
    
    i = 5
    
    while i <= len (str_unicode ):
        
        clear_list .append (str_unicode [i-5:i])

        i += 5
        
    return liste_claire

例如,将消息 'Hello World' returns ['72101', '10810', '81113', '28711', '11141', '08100', '32330'] 加密为 clear_list 然后 '3863 111 1616 3015 1202 341 4096' 作为 encrypted_message

encrypt () 函数使用另一个函数将字符串转换为 Unicode 值列表,但放入块中,因为我已经阅读过,否则,很容易找到明确的消息频率分析。

真的那么容易吗?

很可能,我来谈谈我的主要问题。如您所知,字符的 Unicode 值要么是两位数,要么是三位数。在加密之前,Unicode 值被分成 5 位数字的块 ('stack' -> '115 116 97 99 107' -> '11511 69799 10700')

但问题是当我想解密它时,我怎么知道我必须在哪里分隔该字符串以便一个数字代表一个字符?

我的意思是,以前的 Unicode 值可以是 11 或 115(我知道它不可能真的是 11,但这只是作为示例)。所以要解密然后取回字符,问题是,我不知道我要取多少位数。

我曾想过在 Unicode 值 < 100 时添加一个 0,但是

  1. 然后通过频率分析就可以很容易地做和以前一样的事情了
  2. 不过,当我加密它时,'087'可能导致'467','089'可能导致'046',所以问题仍然存在。

您的 convert_into_unicode 函数并没有真正转换任何 "into" Unicode。假设 clear_message 是 Unicode 字符串(Python 3 中的默认字符串类型,或 Python 2 中的 u''),它(自然)已经是 Unicode,并且您正在使用将其转换为可以加密的字节序列的笨拙方法。如果clear_message是一个字节串(Python2中默认,或者Python3中b''),所有的字符都已经在一个字节中了,所以整个过程是没必要。

Unicode 字符串确实需要先编码为字节序列,然后才能对其进行加密。正常的做法是使用 UTF-8 or UTF-16 这样的编码。您可以通过调用 clear_message.encode('utf-8') 来做到这一点。解密后,可以将解密后的字节串转回Unicode串decrypted_bytes.decode('utf-8').

您根本不需要 convert_into_unicode 函数。

您正在尝试用玩具 RSA 问题解决现实世界中的问题。可以执行频率分析,因为没有使用明文消息的随机填充。需要随机填充以使 RSA 安全。

对于此类问题,直接使用每个字符的Unicode代码点(整数值)作为RSA的输入就足够了。然而,RSA 只能直接加密 [0..N) 范围内的值,其中 N 是模数。如果你输入一个更大的值 x 然后值将首先转换为值 x 模数 N。在这种情况下你丢失信息并且解密将不再是确定性的。

至于密文,只需将其作为由space分隔的整数值的字符串表示并将它们拆分以读取它们。这将需要更多space,但RSA总是有一定的开销。


如果您想实施安全的 RSA,请阅读 PKCS#1 标准并提防时间攻击等。并且,正如 Wyzard 已经指出的那样,请使用混合密码术(除了 RSA 之外还使用对称加密)。

或者使用标准库,现在你明白RSA的原理了。