仅使用 RSA 加密来加密长文本字符串

问题描述 投票:0回答:4

我正在使用此链接上给出的 RSA 加密代码来使用 128 字节公钥加密字符串,例如以下内容:

[7998725336653383203658644639673805448553730986337128386926545744008381384348409264866333582258561179132241508936069720871865895053632019929236743348039021, 1993938860438750843589842757968313427718259534664174282914852335272086243792497573680387148722647412680490224484736059954284097163105446004304579443902885]

由于字符串太长,

RSA_public_encrypt
函数返回
-1
null
字符串。我知道 RSA 应该用于小尺寸文本,有没有同样的方法?

我使用

ERR_error_string()
检查错误代码,它返回了以下错误代码字符串:
error:0406D06E:lib(4):func(109):reason(110)

既然这个问题已被标记为可能重复,那么请让我解释一下,我只需要使用 RSA 来完成它,因为 AES-RSA 组合将使我正在编写的 chrome 扩展的整个系统设计变得更加复杂比现在更。我想尽可能简化它。

c encryption openssl cryptography rsa
4个回答
4
投票

上面的答案已经提到了 RSA-AES。 这是正确的做法。 您使用 RSA 来交易一条小消息(对称密钥),然后您可以使用该会话密钥来进行任何您想要的交谈。

您知道,RSA 的限制是数学上的限制。 我曾经看到有人抱怨 MS 不允许他们的 RSA 为他们的目的加密足够大的消息。 问题是,一旦消息的数字长度达到密钥的 1/2 左右,它就会在数学函数中“翻转”到零以上——超过数字字段的上限——并且不会解密到与开始时的编号相同。 因此,除非在有限的意义上使用更大的 RSA 密钥,否则无法克服此限制。 或者通过对消息进行分块并以 RSA 形式单独发送所有消息,但不鼓励使用相同的公钥/私钥对进行多重加密。

我真的建议您使用 RSA/AES 混合算法。 通过这种方式,您将获得比我能想到的任何其他方式更好的性能。


3
投票

构建某种 RSA 分块方案将比解密对称密钥并使用该密钥执行简单的 AES 解密要复杂得多,并且可能不安全。

就效率而言,RSA 将比 AES 几个数量级,因此您所做的权衡是放弃简单性(即放弃使用 AES 的简单性,转而使用某些 RSA”分块”),但性能较差(RSA 性能较慢。)

我会采用混合 AES-RSA 方法的老路,而不是尝试一些仅 RSA 的方案。


0
投票

如果必须严格使用 RSA,则需要将消息分割成等于 RSA 密钥大小的块,并多次应用 RSA。 但请注意,这样做意味着每个加密块都有自己的填充,并且 RSA 的计算成本比 AES 高得多。

如果您要加密的消息足够大,不仅需要更多时间来处理,而且 RSA 加密的消息可能比 RSA 加密的 AES 密钥加上 AES 加密的消息更大。


0
投票

使用 OAEP 填充块

用于加密:

def encrypt(self, plaintext):
    if not hasattr(self, 'n') or not hasattr(self, 'e'):
        raise AttributeError("Public key not imported")
    
    block_size = self.key_size // 8 - 11  # OAEP padding requires at least 11 bytes
    encrypted_blocks = []
    
    for i in range(0, len(plaintext), block_size):
        block = plaintext[i:i+block_size]
        m = int.from_bytes(block.encode(), 'big')
        c = pow(m, self.e, self.n)
        encrypted_blocks.append(str(c))
    
    return b64encode(','.join(encrypted_blocks).encode())

对于解密,您可以使用 ProcessPoolExecutor 对于 4096 以上的密钥(假设是 8192),解密速度会更快

def decrypt(self, ciphertext):
    if not hasattr(self, 'n') or not hasattr(self, 'd'):
        raise AttributeError("Private key not imported")
    
    ciphertext = b64decode(ciphertext).decode().split(',')
    
    if self.n.bit_length() < 4100:
        decrypted_blocks = []
    
        for c in ciphertext:
            m = pow(int(c), self.d, self.n)
            decrypted_block = m.to_bytes((m.bit_length() + 7) // 8, 'big').decode('utf-8', errors='ignore')
            decrypted_blocks.append(decrypted_block)
        
        return "".join(decrypted_blocks)
    
    else:
        # Convert d and n to gmpy2 objects for faster calculations
        d = gmpy2.mpz(self.d)
        n = gmpy2.mpz(self.n)
        
        # Use multiprocessing to parallelize decryption
        with ProcessPoolExecutor(max_workers=os.cpu_count()) as executor:
            # Include indices to preserve order
            futures = {executor.submit(decrypt_block, (c, d, n)): i for i, c in enumerate(ciphertext)}
            # Collect results in order of their original blocks
            decrypted_blocks = [None] * len(ciphertext)
            for future in as_completed(futures):
                decrypted_blocks[futures[future]] = future.result()
        
        return ''.join(decrypted_blocks)

我在 Windows 上,所以我使用了 as_completed 你可以在 Unix 系统上使用普通的 ProcessPoolExecutor

© www.soinside.com 2019 - 2024. All rights reserved.