在 .Net Core 上使用非对称密钥
Posted
技术标签:
【中文标题】在 .Net Core 上使用非对称密钥【英文标题】:Using Asymmetric Key on .Net Core 【发布时间】:2018-07-25 06:43:17 【问题描述】:我正在尝试运行此示例中的代码
https://docs.microsoft.com/en-us/dotnet/standard/security/how-to-store-asymmetric-keys-in-a-key-container
.NetCore 2.0(网络应用)下。
但是,当我尝试使用
执行任何行时CspParameters
我收到以下错误
'CspParameters' requires Windows Cryptographic API (CAPI), which is not available on this platform.
请就我如何解决此问题提出建议。 谢谢。
【问题讨论】:
【参考方案1】:.NET 不存储加密密钥,这最终是它所构建的加密平台提供(或不提供)的一项功能。
要将 CspParameters 与 .NET Core 一起使用,您必须在 Windows 上运行;因为这是对(旧)Windows Cryptographic API 的一个非常薄的包装器。您不能在 UAP 中使用它,因为 UAP 只允许更新的 Cryptography: Next Generation (CNG) API。
macOS 可以将密钥存储在 Keychain 中,但 .NET Core 不提供读取它们的 API。
Linux (OpenSSL) 除了“将其保存到文件并再次加载”之外没有任何密钥存储机制,但 .NET Core 不支持从文件加载非对称密钥。
在跨平台机制中实现目标的唯一方法是将非对称密钥与 X.509 证书相关联。如果您构建 HasPrivateKey
返回 true 的 X509Certificate2 对象,您可以将其保存到 PFX/PKCS#12 文件,然后从该文件加载;或者您可以将其添加到 X509Store 实例(CurrentUser 的“我的”存储是跨平台效果最好的存储),然后从 X509Store 实例中读取它。
尽管您引用的页面声称是 2017 年编写的,但其真正含义是该内容已从该日期在 msdn.microsoft.com 上的先前位置移动。原始页面写于 2008 年(至少,这是 web.archive.org 上的第一次点击),所以它早于 .NET Core。
【讨论】:
【参考方案2】:您现在可以跨平台执行此操作,只要您使用 .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
);
【讨论】:
【参考方案3】:所以只是想提供另一个我们在遇到此错误时发现的选项。该 CSP 参数错误与 RSACryptoServiceProvider 有关。这与跨平台 .NET Core 存在一些问题。我们找到了一个 Github issue,它提到要使用 RSA.Create() 方法。我正在使用仍然使用 RSACryptoServiceProvider 的 Bouncy Castle library。在撰写此答案时,它看起来像这样。
public static RSA ToRSA(RsaPrivateCrtKeyParameters privKey)
RSAParameters rp = ToRSAParameters(privKey);
RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider();
rsaCsp.ImportParameters(rp);
return rsaCsp;
所以我们只是用类中的私有方法替换它,看起来像这样。
private RSA ToRSA(RsaPrivateCrtKeyParameters parameters)
RSAParameters rp = DotNetUtilities.ToRSAParameters(parameters);
return RSA.Create(rp);
这在 linux 中运行,没有错误。 Bouncy 可能只需要更新他们的库。
【讨论】:
【参考方案4】:使用此方法从密钥字符串导入公钥确保安装 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;
【讨论】:
我已经尝试过这个解决方案,但这会在这一行产生异常: var encryptedData = rsa.Encrypt(testData, false); Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException:“错误长度” 增加密钥长度大小可能使用密钥大小超过 4096 的公钥以上是关于在 .Net Core 上使用非对称密钥的主要内容,如果未能解决你的问题,请参考以下文章