Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何以编程方式创建X509存储密钥以用于加密?_C#_Encryption_X509_Encryption Symmetric - Fatal编程技术网

C# 如何以编程方式创建X509存储密钥以用于加密?

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

我有一个需要加密和解密连接文本的服务。我不想硬编码密码,所以我决定使用证书,但我希望在第一次打开设置UI(一个单独的配置应用程序)时能够将其添加到存储中

我有检查现有证书的代码,如果找不到证书,我会添加一个新的

    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#示例代码中找到很多关于如何做到这一点的信息,我通过你的回答非常有帮助。