【问题标题】:Why is RSACryptoServiceProvider.Encrypt() output not stable?为什么 RSACryptoServiceProvider.Encrypt() 输出不稳定?
【发布时间】:2012-01-08 19:08:48
【问题描述】:

直到今天,我一直认为使用 RSA 进行 RSA 加密是确定性的。毕竟,如果不是,签名验证应该如何工作?

令我大吃一惊的是,.NETs RSACryptoServiceProvider 在使用相同的密钥加密相同的字节集时没有稳定的输出:

[Fact]
public void Learning()
{
    const int keySize = 1024;

    System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider(keySize);

    var bytes = GenerateRandomDataWithLength( 36 );

    for (int i = 0; i < 4; i++)
        Assert.Equal( rsa.Encrypt( bytes, false ), rsa.Encrypt( bytes, false ) );
}

byte[] GenerateRandomDataWithLength( int length )
{
    Random r = new Random();

    byte[] data = new byte[length];
    r.NextBytes( data );

    return data;
}

我浏览了PKCS Specification,并且确实了解 RSA 背后的数学原理,所以我真的很想知道为什么我观察到输出不稳定。

Mono 的 RSA 实现具有稳定的输出。 Encrypt 的不稳定输出不影响解密,这很有可能并产生预期的数据。

【问题讨论】:

    标签: .net cryptography rsa rsacryptoserviceprovider pkcs#1


    【解决方案1】:

    RSA 加密是纯数学的,所以它每次都会给你相同的结果。然而,在 .NET 中调用 Encrypt 并不是简单地进行 RSA 加密。

    为什么? PKCS#1 填充(在Encrypt 中使用false 时的默认设置)将使每个加密结果都不同,因为它包含随机数据(用于填充目的)。

    Mono 具有 same 行为(至少在我的系统上,请参阅注释)。但是,如果您使用的是 Mono 支持但 .NET 不支持的 EncryptValue(CryptoAPI 限制),则将进行 no 填充,并且每次加密的结果都将相同。

    注意:如果您有不同的结果,请在http://bugzilla.xamarin.com 上填写错误报告并附上您正在使用的版本号。

    【讨论】:

    • 好吧,我完全忘记了填充包含随机数据。你显然就在这里。感谢您的回答! (我所指的单声道版本非常旧,实际上它只是 Monos RSA 的来源)。
    • @Johannes 请注意,需要一些随机填充以使 RSA 加密免受选择明文攻击(即再次加密猜测的明文以查看输出是否与之前截获的匹配)。
    • 为了清楚起见,我想补充一点,在Encrypt 中使用true 也会导致随机填充,我相信 (OAEP)。
    猜你喜欢
    • 2015-07-13
    • 1970-01-01
    • 2013-10-20
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-24
    相关资源
    最近更新 更多