RSACryptoServiceProvider 工作正常吗?

Posted

技术标签:

【中文标题】RSACryptoServiceProvider 工作正常吗?【英文标题】:Is RSACryptoServiceProvider working correctly? 【发布时间】:2017-01-18 11:45:57 【问题描述】:

我正在使用 .NET 的 RSA 实现,有两件事对我来说很奇怪。我想确认它运行正常。

背景

使用 System.Security.Cryptography.RSACryptoServiceProvider 和 2048 位关键字大小来执行非对称加密/解密,最初遵循 this question, "AES 256 Encryption: public and private key how can I generate and use it .net" 中的示例。

作为第一个实现,这似乎可行:

public const int  CSPPARAMETERS_FLAG = 1;      // Specifies RSA: https://msdn.microsoft.com/en-us/library/ms148034(v=vs.110).aspx
public const bool USE_OAEP_PADDING   = false;
public const int  KEYWORD_SIZE       = 2048;

public static byte[] Encrypt(byte[] publicKey, byte[] dataToEncrypt)

    var cspParameters = new System.Security.Cryptography.CspParameters(CSPPARAMETERS_FLAG);
    byte[] encryptedData = null;

    using (var rsaProvider = new System.Security.Cryptography.RSACryptoServiceProvider(cspParameters))
    
        try
        
            rsaProvider.PersistKeyInCsp = false;
            rsaProvider.ImportCspBlob(publicKey);
            encryptedData = rsaProvider.Encrypt(dataToEncrypt, USE_OAEP_PADDING);
        
        finally
        
            rsaProvider.PersistKeyInCsp = false;
            rsaProvider.Clear();
        
    
    return encryptedData;


public static byte[] Decrypt(byte[] privateKey, byte[] dataToDecrypt)

    var cspParameters = new System.Security.Cryptography.CspParameters(CSPPARAMETERS_FLAG);
    byte[] encryptedData = null;

    using (var rsaProvider = new System.Security.Cryptography.RSACryptoServiceProvider(cspParameters))
    
        try
        
            rsaProvider.PersistKeyInCsp = false;
            rsaProvider.ImportCspBlob(privateKey);
            encryptedData = rsaProvider.Decrypt(dataToDecrypt, USE_OAEP_PADDING);
        
        finally
        
            rsaProvider.PersistKeyInCsp = false;
            rsaProvider.Clear();
        
    

    return encryptedData;

在进一步研究了这些方法之后,我从the example 生成的公钥似乎在开始时有很多非常可预测的数据,它有 276 字节长。

显然rsaProvider.ExportCspBlob(bool includePrivateParameters)rsaProvider.ExportParameters(bool includePrivateParameters) 的功能替代品;主要区别在于 blob 已经序列化为 byte[] 而另一个发出对象版本 RSAParameters

关于方法的两个观察:

    .Exponent 始终为 0x010001$=65537$。 与序列化的类型版本相比,导出的 blob 包含 17 个额外字节。 rsaProvider.ExportCspBlob(): 公钥为 276 字节。 私钥为 1172 字节。 RSAParameters: 公钥为 259 字节。 .Exponent.Length = 3 .Modulus .Length = 256 私钥为 1155 字节。 .D .Length = 256 .DP .Length = 128 .DQ .Length = 128 .Exponent.Length = 3 .InverseQ.Length = 128 .Modulus .Length = 256 .P .Length = 128 .Q .Length = 128 额外的 17 个字节似乎位于二进制 blob 的标头中。

担忧

由此,有两个担忧:

    指数不是随机的可以吗? 如果指数被定义为一个常数,那么我似乎可以再减少 3 个字节的序列化? 另一个问题Should RSA public exponent be only in 3, 5, 17, 257 or 65537 due to security considerations? 似乎表明 $\left3, 5, 17, 257, 65537\right$ 都是指数的常见值,所以 0x101$=65537$ 似乎是合理的,如果确实,始终使用相同的常数指数并没有什么坏处。 额外的 17 个字节是信息泄漏吗? 它们是否代表密钥长度和方法等选项参数? 当我已经知道发送方和接收方都使用相同的硬编码方法时,传输选项参数信息是否是个好主意?

问题

RSACryptoServiceProvider 的行为是否值得关注,或者这些事情是否正常?

更新 1

在Should RSA public exponent be only in 3, 5, 17, 257 or 65537 due to security considerations? 中,接受的答案开始于:

对于 RSA 的任何短或长公共指数都没有已知的弱点,只要公共指数是“正确的”(即对于除模的所有素数 p 与 p-1 相对素数)。

如果是这样,那么我猜0x010001$=65537$ 的明显恒定指数就足够了,只要它与 $p-1$ 相对质数。因此,大概 RSA 的 .NET 实现会检查这种情况。

但是,如果条件不满足,RSACryptoServiceProvider 会做什么?如果它选择了不同的指数,那么每当指数不是0x010001 时,它似乎就会泄露有关 $p$ 的信息。或者,如果选择了不同的键,那么我们似乎可以假设指数始终为 0x010001 并从序列化中省略它。

【问题讨论】:

【参考方案1】:

报告的一切都是正常的,并不令人担忧。

公共指数 e 短且非随机是完全可以的。 e = 216+1 = 65537 = 0x010001 是常见且安全的。一些当局要求它(或包括它的某些范围)。使用它(或/和显着大于公共模数位大小的东西)可以防止一些最差的 RSA 填充。

不,公钥中的 17 个额外字节不太可能是信息泄漏;它们更有可能是您使用的软件为 RSA 公钥选择的数据格式的标头部分。我的猜测是您遇到了answer 中详述的特定于 MS 的格式(可能在字节序内),它还使用 276 字节的 RSA 公钥和 2048 位公共模数。在这种情况下,您应该会发现额外的字节总是相同的(因此它们显然不会泄漏任何内容)。还有无数更微妙的方式可以泄露关于私钥的信息,比如在公共模数本身中。

实践中使用的很多RSA密钥生成器,包括我猜RSACryptoServiceProvider,首先选择e,然后稍微避免生成素数p这样gcd(e , p-1) ≠ 1. 因为 e = 65537 是素数,所以 ( p % e ) ≠ 1,这很容易检查,或者由生成 p 的过程保证。

【讨论】:

以上是关于RSACryptoServiceProvider 工作正常吗?的主要内容,如果未能解决你的问题,请参考以下文章

RSACryptoServiceProvider 工作正常吗?

如何使用先前使用 RSACryptoServiceProvider 加密的 RSACng 解密数据

如何提取 RSACryptoServiceProvider 生成的素数?

C# - RSACryptoServiceProvider - 错误:错误数据

从公钥正确创建 RSACryptoServiceProvider

这个 C# RSACryptoServiceProvider 方法的红宝石等价物是啥