首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >相同明文的RSA不同密文

相同明文的RSA不同密文
EN

Cryptography用户
提问于 2022-08-11 16:15:13
回答 3查看 800关注 0票数 2

General

我的目标是加密一些字符串并将它们存储在数据库中。

我在Go (Golang)中使用RSA OAEP:

代码语言:javascript
复制
rsa.EncryptOAEP(sha256.New(), rng, rsaPublickey, plaintext, nil)
rsa.DecryptOAEP(sha256.New(), rng, rsaPrivatekey, ciphertext, nil)

我生成了一个具有4096位的公钥/私钥对。

我对RSA的理解是非常基本的。我在堆栈溢出上读到了一些类似的问题,这些问题说RSA OAEP添加了填充,以确保为相同的明文生成不同的密文用于安全目的。

我对使用AES更有信心,因为如果您提供相同的对称密钥和相同的初始化向量,您将始终得到相同的密文。

P.S:我知道RSA和AES在通过网络发送数据时有不同的用例,我不应该同样对待它们,但是对于我个人的用例,我想用它们来加密/解密字符串。

问题

  1. 由于不同的密文是为相同的明文生成的,是否可以保证我将来能够解密这些RSA OAEP密文?

实现发生变化,使用新的库、函数和编程语言运行时的新版本,等等。

我对将用于解密的RSA OAEP实现漠不关心(Go,Java,Python,openssl,.)只要我能从密文中得到明文。

Go文档上写着Encryption and decryption of a given message must use the same hash function。在我的例子中,这个散列函数是SHA256。

此外,Go文档说,The random parameter is used as a source of entropy to ensure that encrypting the same message twice doesn't result in the same ciphertext.我还没有看到在其他编程语言中使用这个随机参数(在我的例子中是rng)。它似乎是特定于Go RSA OAEP实现。

因此,如果我使用RSA OAEP解密实现,则相同:

  • 私钥
  • 散列函数

我应该能够从所有加密的字符串中获取明文。据我所见,这两件事似乎是解密所需的唯一条件。这是对的吗?答案可能是肯定的,但如果可能的话,最好能收到更多关于这方面的信息,以增强我的信心。

EN

回答 3

Cryptography用户

发布于 2022-08-11 17:43:05

对于同一明文的每一种加密,每种非对称加密方法都必须返回不同的密文。否则,给定密文和公钥,而不是相应的私钥,攻击者可以尝试猜测明文:对手可以通过尝试加密并将实际的密文与他们计算的密文进行比较来验证猜测。

为了确保每个加密都返回不同的密文,加密的结果需要依赖于仅从密文、明文和公钥中无法找到或猜测的值。随机值是唯一可行的选择。根据库设计器的选择,生成随机值的方法可能是实现的内部细节,也可能是加密接口的参数。在内部执行它可以使接口更容易使用,这通常更好,但以它作为参数有一些优点:它允许重复进行审计或调试的操作序列,并获得完全相同的输出,并且允许实现不依赖于全局状态,例如RNG状态(在纯函数语言中是必需的)。

对称加密的接口通常是不同的,因为安全性特性不同,而且常用的方法也不同。对称加密通常用于与多条消息使用相同密钥的协议中,该协议指定加密和解密时要使用的唯一输入(IV/nonce) (这允许不存储或传输此唯一输入)。与RSA-OAEP,随机的现在被编码在密文内无论如何。对称加密通常不需要现在是秘密的,而我们已经看到它对于非对称加密非常重要。对称加密实际上可以不使用nonce:您可以获得确定性加密,其中密文仅依赖于秘密密钥和明文。当同一个明文被加密两次时,确定性加密就很明显了,但由于攻击者没有加密密钥(与解密密钥相同),因此无法利用此加密来猜测未知密文的明文。正如我们所看到的,这将是非对称加密的一个主要问题,因为攻击者拥有加密密钥。

无法通过将结果与已知值进行比较来验证非对称加密是否成功。您需要应用解密过程(这需要拥有私钥)。(类似地,许多非对称签名方法都是随机的,因此您无法通过将签名与已知值进行比较来检查签名是否正确-但是,可以设计一种安全的、确定性的非对称签名机制,例如,如果使用空盐,PSS就是其中一种。)

OAEP有一个精确规格。要解密,只需指定:

  • 用于标签的散列函数;
  • 掩码生成函数,在实际应用中始终是具有相同哈希函数的MGF1;
  • 私钥;
  • 密文。

使用这些输入,解密过程指定如何将密文转换为数字,应用RSA私钥操作获得另一个数字,将该数字转换为填充和蒙面明文,分解该数字并揭开掩码部分以获取密文。(可以选择使用标签--但您可以在不事先知道标签的情况下解密。)相反,加密过程需要5个输入:哈希函数、掩码生成函数、公钥、明文和随机种子。(加上影响掩蔽和填充的可选标签。)给定这些输入,它指定如何将随机种子转换为掩码,将该掩码应用于纯文本并填充结果,将填充和蒙面的明文转换为数字,应用RSA公钥操作获得另一个数字,并将该数字转换为一个字符串,即密文。如果给定相同的输入(包括随机数),RSA-OAEP加密的两个实现总是产生相同的密文(通常不是由调用方单独传递,而是由实现直接获得)。如果给出相同的输入,两个RSA-OAEP解密实现总是会产生相同的明文。

票数 2
EN

Cryptography用户

发布于 2022-08-11 17:09:37

听起来不错。

具体来说,在OAEP中,由加密器创建一个一次性随机种子,该加密器确定填充消息的掩码,然后将种子本身屏蔽并包含在有效载荷中。解密器不必以与加密器相同的方式重新创建种子,因为它们可以从解密的有效载荷中获取掩码种子,并且应该能够通过删除掩码恢复种子。

当然,恢复的有效载荷需要与发送的有效载荷相同,以便解密器必须具有与加密器使用的公钥相关联的私钥。同样,解密器必须能够重建加密器使用的相同掩码,因此必须使用相同的掩码擦除函数(MDF)。在您的实现中,它听起来像是一个加密哈希函数被用作MDF,因此加密器和解密器必须使用相同的散列。

只要密文未被修改,且解密器具有解密密钥和用于生成掩码的功能,则保证恢复。

票数 1
EN

Cryptography用户

发布于 2022-08-17 03:00:15

我还没有看到在其他编程语言中使用这个随机参数(在我的例子中是rng)。

Python有一个默认参数也适用于PKCS1 1-v1的“遗留”_5衬垫“

OpenSSL的内部有一个(相当复杂的) RNG方案。通常,您不指定任何内容,它使用默认值,但您可以选择在执行使用它的操作(如RSA加密或v1_5加密)之前进行单独的调用来配置/调整它。

WebCrypto (在浏览器javascript中)也有一个内建RNG,在需要时可以隐式使用。(对于在nodejs上运行的javascript来说,内置的'crypto‘模块-对于最近的版本也是一个WebCrypto shim -实际上是OpenSSL的包装器,请参见上面的内容。)

Java对所有密码器和密码模式都使用单一的“facade”类javax.crypto.Cipher,而不管它们需要哪些参数(包括随机性)。正如您所看到的,javadoc有多个init重载,它们对应于不同的用例,有些包括RNG,有些则不;如果您使用一个不包含的,例如对于需要随机性的实例(如RSA)使用init(int,Key,AlgorithmParameterSpec),那么它将使用默认的RNG。

票数 1
EN
页面原文内容由Cryptography提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://crypto.stackexchange.com/questions/101443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档