我正在尝试了解有关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结构中将密钥容器名称保留为null
(并且不断言UseDefaultKeyContainer
),则会为您断言CreateEphemeralKey
标志。
对于使用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没有keysize值,所以该ctor的KeySize
值是不相关的)
您可能想要保存的不是CspParameters,而是实际的RSA/RSACryptoServiceProvider对象。