C# 如何以编程方式创建X509存储密钥以用于加密?
我有一个需要加密和解密连接文本的服务。我不想硬编码密码,所以我决定使用证书,但我希望在第一次打开设置UI(一个单独的配置应用程序)时能够将其添加到存储中 我有检查现有证书的代码,如果找不到证书,我会添加一个新的C# 如何以编程方式创建X509存储密钥以用于加密?,c#,encryption,x509,encryption-symmetric,C#,Encryption,X509,Encryption Symmetric,我有一个需要加密和解密连接文本的服务。我不想硬编码密码,所以我决定使用证书,但我希望在第一次打开设置UI(一个单独的配置应用程序)时能够将其添加到存储中 我有检查现有证书的代码,如果找不到证书,我会添加一个新的 private static void GenerateNewSecurityCertificate() { var ecdsa = ECDsa.Create(); // generate asymmetric key pair var r
private static void GenerateNewSecurityCertificate()
{
var ecdsa = ECDsa.Create(); // generate asymmetric key pair
var request = new CertificateRequest($"cn={CertificateName}", ecdsa, HashAlgorithmName.SHA512);
var cert = request.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(50));
File.WriteAllBytes("c:\\temp\\EncryptionCert.pfx", cert.Export(X509ContentType.Pfx, _certificatePassword));
}
private static void AddCertificateToStore()
{
using (var store = new X509Store(StoreName.TrustedPublisher, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadWrite);
using (var cert = new X509Certificate2("c:\\temp\\EncryptionCert.pfx", _certificatePassword,
X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet))
{
store.Add(cert);
}
}
}
我在尝试检索公钥时遇到了这个问题
using (var store = new X509Store(StoreName.TrustedPublisher, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadOnly);
using (var cert = store.Certificates.Find(X509FindType.FindBySubjectName, CertificateName, false)[0])
{
var publicKey = cert.GetRSAPublicKey();
encryptedKey = publicKey.Encrypt(aesKey.Key, RSAEncryptionPadding.OaepSHA512);
}
}
调用cert.GetRSAPublicKey()
时返回空值。有人知道我可能做错了什么吗
更新:
我将GenerateNewSecurityCertificate
更新为
var rsa = RSA.Create();
var request = new CertificateRequest($"cn={CertificateName}", rsa, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
我现在可以获取公钥,但读取时出现异常
“参数不正确”
在System.Security.Cryptography.NCryptNative.EncryptData[T](安全加密密钥句柄,字节[]数据,T&paddingInfo,不对称加密模式paddingMode,NCryptEncryptor`1加密机)
在我调用publicKey.Encrypt时,由于您显然加密了AES密钥,因此可以假定数据的(最大)长度为32字节(AES-256)。例如,如果信息对于所使用的钥匙来说太大,则可以复制错误信息 对于RSA,消息的长度不得超过密钥长度。事实上,它甚至更小,因为允许长度的一部分是为填充保留的。对于OAEP,该部分取决于使用的摘要。对于SHA512,保留部分(130字节)太大,以至于1024位(128字节)密钥不够,对于2048位(256字节)密钥,消息可能仍然是126字节大,请参阅 您可以使用创建RSA密钥
var rsa = RSA.Create();
它使用密钥长度的默认值s。此默认值还取决于.NET版本。在.NET Framework 4.8下,在我的机器上创建1024位的密钥(现在太短了),在.NET Core 3.1下创建2048位的密钥。您可以使用rsa.KeySize检查密钥长度
可能是在您的环境中生成了一个太短的密钥。最好不要依赖默认值,而是显式指定值。Create
方法有一个重载,使之成为可能,请参阅。您应该使用此重载并创建一个密钥(至少2048位)
或者,理论上可以通过另一个摘要(例如SHA256)消除该缺陷。与此无关,出于安全原因,目前(2020年12月)不应使用1024位的密钥,其长度应至少为2048位(请参阅)。您可以在
GenerateNewSecurityCertificate
中创建ECDSA密钥对,但最后导出(公共)RSA密钥。使用RSA或EC。对于EC密钥,还有其他检索方法,例如,GetPublicKey
/GetPublicKeyString
以二进制/十六进制编码格式返回(未压缩的)原始EC公钥。使用GetRSAPublicKey
将检索到一个公钥。@Topaco-感谢您的回复。我将GenerateNewSecurityCertificate更新为var rsa=rsa.Create();var请求=新证书请求($“cn={CertificateName}”、rsa、HashAlgorithmName.SHA512、RSASignaturePadding.Pkcs1);我现在可以获取公钥,但在调用publicKey.Encrypt时出现异常,显示“参数不正确”。在System.Security.Cryptography.NCryptNative.EncryptData[T](SafeCryptKeyHandle密钥,Byte[]数据,T&paddingInfo,AsymmetricPaddingMode paddingMode,NCryptEncryptor`1 encryptor)中,这可能是由于选择的密钥参数,请查看我的答案。您需要增加RSA密钥大小(@Topaco的答案)或减少OAEP填充大小(例如,使用OAEP-SHA256)。您可能正在尝试存储32个字节,请将其与@bartonjs中的图表进行比较。我在回答中提到了较小摘要的替代方案。但是,由于OP使用1024位密钥(并且只有使用此密钥大小,在加密AES密钥的上下文中才会出现问题),在我看来,这似乎是错误的做法,因为1024位密钥现在太小了。谢谢你的详细回答;我从中学到了很多。我不使用加密,所以这对我来说是全新的。虽然我可以了解很多理论,但我无法在C#示例代码中找到很多关于如何做到这一点的信息,我通过你的回答非常有帮助。