为什么RSACryptoServiceProvider.Encrypt()输出不稳定?

Joh*_*lph 11 .net cryptography rsa rsacryptoserviceprovider pkcs#1

直到今天,我仍然生活在使用RSA的RSA加密是确定性的印象中.毕竟,签名验证如果不是,应该如何工作?

令我惊讶的是,RSACryptoServiceProvider当使用相同的密钥加密相同的字节集时,.NET 没有稳定的输出:

[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;
}
Run Code Online (Sandbox Code Playgroud)

我已经浏览了PKCS规范,我确实理解了RSA背后的数学,所以我真的很想知道为什么我观察输出是不稳定的.

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

pou*_*pou 18

RSA加密是纯数学的,所以每次都会给你相同的结果.但是,Encrypt在.NET中调用不仅仅是进行RSA加密.

为什么?在PKCS#1填充(当你使用默认falseEncrypt)会尽一切加密后的结果不同,因为它包含随机数据(填充的目的).

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

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

  • 为了清楚起见,我想补充一点,在`Encrypt`中使用`true`会导致随机填充,我相信(`OAEP`). (2认同)