在 .Net Core 上使用非对称密钥
Using Asymmetric Key on .Net Core
我正在尝试运行此示例中的代码
https://docs.microsoft.com/en-us/dotnet/standard/security/how-to-store-asymmetric-keys-in-a-key-container
在 .NetCore 2.0(Web 应用程序)下。
然而,当我尝试使用
执行任何行时
CspParameters
我收到以下错误
'CspParameters' requires Windows Cryptographic API (CAPI), which is not available on this platform.
请就我如何解决这个问题提出建议。
谢谢
.NET 不存储加密密钥,这最终是(或不)由其构建的加密平台提供的功能。
要在 .NET Core 中使用 CspParameters,您必须 运行 on Windows;因为那是(旧的)Windows 加密 API 的一个非常薄的包装器。你不能在 UAP 中使用它,因为 UAP 只允许较新的 Cryptography: Next Generation (CNG) API.
macOS 可以将密钥存储在钥匙串中,但 .NET Core 不提供 API 读取它们。
Linux(OpenSSL)除了"save this to a file and load it again"外没有任何密钥存储机制,但.NET Core不支持从文件加载非对称密钥。
在跨平台机制中实现目标的唯一方法是将非对称密钥与 X.509 证书相关联。如果您构建 HasPrivateKey
returns true 的 X509Certificate2 对象,您可以将其保存到 PFX/PKCS#12 文件,然后从该文件加载;或者您可以将它添加到 X509Store 实例(CurrentUser 的 "My" 存储是跨平台效果最好的存储),然后从 X509Store 实例读回它。
尽管您引用的页面声称是在 2017 年编写的,但它的真正含义是内容已从该日期的 msdn.microsoft.com 之前的位置移动。原始页面写于 2008 年(至少,这是 web.archive.org 上的第一篇文章),所以它早于 .NET Core。
所以只是想提供我们遇到此错误后发现的另一个选项。该 CSP 参数错误与仍在使用 RSACryptoServiceProvider 的 RSACryptoServiceProvider . This has some issues with cross platform .NET Core. We found a Github issue that mentioned to use RSA.Create() method instead. I was using a Bouncy Castle library 有关。在撰写此答案时,它看起来像这样。
public static RSA ToRSA(RsaPrivateCrtKeyParameters privKey)
{
RSAParameters rp = ToRSAParameters(privKey);
RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider();
rsaCsp.ImportParameters(rp);
return rsaCsp;
}
所以我们只是用 class 中的私有方法替换它,看起来像这样。
private RSA ToRSA(RsaPrivateCrtKeyParameters parameters)
{
RSAParameters rp = DotNetUtilities.ToRSAParameters(parameters);
return RSA.Create(rp);
}
这个运行在linux,没有错误。 Bouncy 可能只需要更新他们的库。
使用此方法从密钥字符串中导入 public 密钥确保安装 BouncyCastle.NetCore nuget 包
public static RSACryptoServiceProvider ImportPublicKey(string pem)
{
PemReader pr = new PemReader(new StringReader(pem));
AsymmetricKeyParameter publicKey = (AsymmetricKeyParameter)pr.ReadObject();
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)publicKey);
RSACryptoServiceProvider csp = new RSACryptoServiceProvider();// cspParams);
csp.ImportParameters(rsaParams);
return csp;
}
然后您可以如下所示加密您的数据
public static string Encryption(string data,string publickey)
{
var testData = Encoding.GetEncoding("iso-8859-1").GetBytes(strText);
using (var rsa = ImportPublicKey(publickey))
{
try
{
var encryptedData = rsa.Encrypt(testData, false);
var base64Encrypted = Convert.ToBase64String(encryptedData);
return base64Encrypted;
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
}
您现在可以跨平台进行,只要您使用 .netcore 3.0 或更高版本并添加最新的 System.Security.Cryptography.Cng nuget 包(注意!这仅在您的项目不是多目标时有效 - 它只能针对 netcoreapp3.0) :
using (ECDsa key = ECDsa.Create())
{
key.ImportPkcs8PrivateKey(Convert.FromBase64String(privateKey), out _);
return Jose.JWT.Encode
(
payload: payload,
key: key,
algorithm: JwsAlgorithm.ES256,
extraHeaders: extraHeader
);
}
我正在尝试运行此示例中的代码
https://docs.microsoft.com/en-us/dotnet/standard/security/how-to-store-asymmetric-keys-in-a-key-container
在 .NetCore 2.0(Web 应用程序)下。
然而,当我尝试使用
执行任何行时CspParameters
我收到以下错误
'CspParameters' requires Windows Cryptographic API (CAPI), which is not available on this platform.
请就我如何解决这个问题提出建议。 谢谢
.NET 不存储加密密钥,这最终是(或不)由其构建的加密平台提供的功能。
要在 .NET Core 中使用 CspParameters,您必须 运行 on Windows;因为那是(旧的)Windows 加密 API 的一个非常薄的包装器。你不能在 UAP 中使用它,因为 UAP 只允许较新的 Cryptography: Next Generation (CNG) API.
macOS 可以将密钥存储在钥匙串中,但 .NET Core 不提供 API 读取它们。
Linux(OpenSSL)除了"save this to a file and load it again"外没有任何密钥存储机制,但.NET Core不支持从文件加载非对称密钥。
在跨平台机制中实现目标的唯一方法是将非对称密钥与 X.509 证书相关联。如果您构建 HasPrivateKey
returns true 的 X509Certificate2 对象,您可以将其保存到 PFX/PKCS#12 文件,然后从该文件加载;或者您可以将它添加到 X509Store 实例(CurrentUser 的 "My" 存储是跨平台效果最好的存储),然后从 X509Store 实例读回它。
尽管您引用的页面声称是在 2017 年编写的,但它的真正含义是内容已从该日期的 msdn.microsoft.com 之前的位置移动。原始页面写于 2008 年(至少,这是 web.archive.org 上的第一篇文章),所以它早于 .NET Core。
所以只是想提供我们遇到此错误后发现的另一个选项。该 CSP 参数错误与仍在使用 RSACryptoServiceProvider 的 RSACryptoServiceProvider . This has some issues with cross platform .NET Core. We found a Github issue that mentioned to use RSA.Create() method instead. I was using a Bouncy Castle library 有关。在撰写此答案时,它看起来像这样。
public static RSA ToRSA(RsaPrivateCrtKeyParameters privKey)
{
RSAParameters rp = ToRSAParameters(privKey);
RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider();
rsaCsp.ImportParameters(rp);
return rsaCsp;
}
所以我们只是用 class 中的私有方法替换它,看起来像这样。
private RSA ToRSA(RsaPrivateCrtKeyParameters parameters)
{
RSAParameters rp = DotNetUtilities.ToRSAParameters(parameters);
return RSA.Create(rp);
}
这个运行在linux,没有错误。 Bouncy 可能只需要更新他们的库。
使用此方法从密钥字符串中导入 public 密钥确保安装 BouncyCastle.NetCore nuget 包
public static RSACryptoServiceProvider ImportPublicKey(string pem)
{
PemReader pr = new PemReader(new StringReader(pem));
AsymmetricKeyParameter publicKey = (AsymmetricKeyParameter)pr.ReadObject();
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaKeyParameters)publicKey);
RSACryptoServiceProvider csp = new RSACryptoServiceProvider();// cspParams);
csp.ImportParameters(rsaParams);
return csp;
}
然后您可以如下所示加密您的数据
public static string Encryption(string data,string publickey)
{
var testData = Encoding.GetEncoding("iso-8859-1").GetBytes(strText);
using (var rsa = ImportPublicKey(publickey))
{
try
{
var encryptedData = rsa.Encrypt(testData, false);
var base64Encrypted = Convert.ToBase64String(encryptedData);
return base64Encrypted;
}
finally
{
rsa.PersistKeyInCsp = false;
}
}
}
您现在可以跨平台进行,只要您使用 .netcore 3.0 或更高版本并添加最新的 System.Security.Cryptography.Cng nuget 包(注意!这仅在您的项目不是多目标时有效 - 它只能针对 netcoreapp3.0) :
using (ECDsa key = ECDsa.Create())
{
key.ImportPkcs8PrivateKey(Convert.FromBase64String(privateKey), out _);
return Jose.JWT.Encode
(
payload: payload,
key: key,
algorithm: JwsAlgorithm.ES256,
extraHeaders: extraHeader
);
}