我正在尝试更多地了解RSA如何在.NET中运行并遇到这个有用的帖子,这表明默认情况下密钥存储在Windows中:https://stackoverflow.com/a/5845191/1181412
我的问题参考了下面的示例代码。假设意图是仅在应用程序会话的生命周期中生成一次性密钥。
问题1:在下面的结构中,每次在类中的任何地方创建RSACryptoServiceProvider时,是否需要将PersistKeyInCsp标志设置为false,即使它正在访问相同的CspParameters对象?
问题2:在CspParameters对象上设置CreateEphemeralKey标志是否取代了在此示例中使用PersistKeyInCsp的需要?
Public Class RSACrypto
Private RSAKey As CspParameters
Public Sub New(KeySize As Integer)
MyBase.New()
RSAKey = New CspParameters
Using RSA As New RSACryptoServiceProvider(KeySize, RSAKey)
RSA.PersistKeyInCsp = False
End Using
End Sub
Public Function PublicKey() As Byte()
Using RSA As New RSACryptoServiceProvider(RSAKey)
RSA.PersistKeyInCsp = False
Return RSA.ExportCspBlob(False)
End Using
End Function
End Class
如果您将密钥容器名称保留为CspParameters结构中的CreateEphemeralKey
(并且您没有断言null
),则会为您声明UseDefaultKeyContainer
标志。
对于使用CreateEphemeralKey
创建的密钥(或通过null
名称隐式创建),PersistKeyInCsp
属性没有任何意义或影响。对于命名(持久)密钥,它会在对象获得Disposed或Finalized时从磁盘中删除密钥。 (请注意,异常终止意味着密钥永远不会被删除)
问题1:在下面的结构中,每次在类中的任何地方创建RSACryptoServiceProvider时,是否需要将PersistKeyInCsp标志设置为false,即使它正在访问相同的CspParameters对象?
如果密钥是持久的,那么第一次设置PersistKeyInCsp=false
并调用Dispose()
(直接或通过using
语句),或者让密钥被垃圾收集并最终确定,那么后续访问将失败,或者创建一个不同的密钥(取决于是否声称UseExistingKey
旗帜。所以,说“不,你不应该这样做”是最正确的。
问题2:在CspParameters对象上设置CreateEphemeralKey标志是否取代了在此示例中使用PersistKeyInCsp的需要?
是。
隐含问题3:为什么我的代码不起作用?
在构造函数中,您有三种行为之一,具体取决于CspParameters.KeyContainerName
和系统状态的值:
KeyContainerName == null
:
你创建了一个大小为KeySize
的短暂密钥。然后丢弃它。没有人会知道你的钥匙是什么。KeySize
的密钥对,将其保存到磁盘并删除它。没有人会知道你的钥匙是什么。KeySize
被忽略了)。然后你把它从磁盘上删除了。希望你不需要它。在PublicKey
方法中,您可以创建1024位短暂密钥(如果RSAKey.KeyContainerName == null
)或打开现有密钥,或者生成1024位密钥并将其保留到磁盘。然后导出公钥的CAPI blob,并且(如果是短暂的)丢弃密钥或(如果持久)将其从系统中删除。 (1024位是因为您使用了没有密钥值的CspParameters ctor,因此来自ctor的KeySize
值无关紧要)
您可能想要的是不保存CspParameters,而是保存实际的RSA / RSACryptoServiceProvider对象。