如何从 .Net Core 中包含私有/Public 密钥的 PEM 文件导入 PKCS1 密钥

How to import PKCS1 keys from a PEM file containing Private / Public keys in .Net Core

我正在尝试使用 .Net Core 从 PEM 文件加载私有密钥和 Public 密钥。 我的代码如下所示:

var localPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
var path = Path.Combine(localPath, this._configManager.JwtPem);
var rsaCryptoServiceProvider = new RSACryptoServiceProvider();

var linesList = File.ReadAllLines(path).ToList();
var line = string.Concat(linesList.GetRange(1, linesList.Count - 2));

rsaCryptoServiceProvider.ImportCspBlob(Convert.FromBase64String(line));

我遇到的异常是:

Internal.Cryptography.CryptoThrowHelper+WindowsCryptographicException : Bad Version of provider
   at Internal.NativeCrypto.CapiHelper.ImportKeyBlob(SafeProvHandle saveProvHandle, CspProviderFlags flags, Boolean addNoSaltFlag, Byte[] keyBlob, SafeKeyHandle& safeKeyHandle)
   at System.Security.Cryptography.RSACryptoServiceProvider.ImportCspBlob(Byte[] keyBlob)
   at StepNexusCA.ServiceLayer.Authorization.TokenService.GenerateToken(List`1 claims)

包含我开发的 Private/Public 密钥的 PKCS1 格式的 PEM 文件在这里:

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAwgs8kmIwk+4geRO7dGZjzYpgD2OiaUrnOOIk+ObXt/CcjhwX
lSst+jBmfMF1Wp/mF4aUQsePxN59MYV2BsqPLEkzVdq/fb/7V2wbZcooJAQKkJwT
emtYHrBN00KBBeu9uQZlFOw365ij4GrbP7mcr4tNFZ3TPnRFUUFqhvB6mEG1aZsb
lOn1lgL34tAycQHNxttXz/aGfPyTefQ+yISvSY2n8288OVlyfu6wKDONQYS+/stC
tCV+a+/dDUSUjaZsXM1+BMSflsINqIcCTCMvPa6fb5Z+USfPDcDNwzUyX20LBzH5
wFwPLIvuoqJeeczcaHaT+dS2ZZREj6kgUsdC+QIBAwKCAQEAgVzTDEF1t/QVpg0n
ou7tM7GVX5fBm4dE0JbDUJnlJUsTCWgPuMdz/CBEUyujkb/uulm4LIUKgz7+IQOk
BIcKHYYiOTx/qSqnj51nmTFwGAKxtb1iUZzlacrejNcArp0pJgRDY0glR7sX6vHn
f9ETH7IzY76M1E2Di4Dxr0r8ZX/3ozsrSXp+GMJLeN9sCjKSyxoE5Y71eDBTCX2N
tShJJjhqUDz61bhKlX9j5c3jWvTXx46dE8wjoJ/BW1XJo5J1gzHQ/OLYeOXIdxlj
jVSlEuU69UT588B7UEEK9N9xK5K/c0Yw5gd02RUv/o7qdpYQICeGtQMMaFkm75xy
nUOxwwKBgQD/orUvgNJfFKyvGY8XJTuek5q8IcFD8AFO3b7pNnPynw8llyEpACAv
Onf9aJSPZvtrabSqrpO8k8Ijyhe2Ino39GuRV8RURl46GmFN31RoYV1wHI4K7Emh
68cdKbCEBudog+kImImldBAfo+QmBtqhS+u4B5qQwwnFa8DriQoiYwKBgQDCUg0r
Jd/ZXDLXk/H5PHpTApmUVd7SWLLIDfkBAlRO8Sni4/Ka+KTTZDec5uoo0hoP6cCs
Z9+MZz4XOiwv9dCEI5czMawGmwsm23+fGM/PP/lW4yD8dz10KZggKjWElymDVl+n
zsc6ctwHAOfYwREi7E+R4rWTBgTEvH2I3deV8wKBgQCqbHjKVeGUuHMfZl9kw30U
YmcoFoDX9VY0k9SbeaKhv19uZMDGABV00aVTmw2071JHm83HHw0oYoFtMWUkFvwl
TZ0Lj9g4Lul8EZYz6jhFlj5KvbQHSDEWnS9oxnWtWe+bAptbEFvDorVqbULEBJHA
3UfQBRG111vY8oCdBgbBlwKBgQCBjAjHbpU7ksyPt/amKFGMrGZi4+nhkHcwCVCr
VuLfS3FB7UxnUG3iQs+970bF4Wa1RoBy7+pdmilk0XLKo+BYF7oiIR1ZvLIZ56pq
EIqKKqY57MCoT35NcRAVcXkDD3ECOZUaidom9z1aAJqQgLYXSDUL7HkMrq3YfakF
6Tpj9wKBgEPCSW7EMFjK2NzmB+4b+skxXcfCZ0ldNtwoUDijuAMFg8ueC3j2qFUX
bAXSApi3mQMow1/JwQxiZ+b+GDLdTcE/PrBVBRkL/5RkmnVagbjBrdZhVjpC+dUo
eEkCChClGGpRyPJ+DYYRyX1Fk9Und8Xbd49Vv+/6RL76ys3gGQl8
-----END RSA PRIVATE KEY-----

为什么我不能使用 ImportCspBlob(...) 导入密钥?我没有在网上找到太多关于异常的信息,但我的代码哪里错了?我知道 BouncyCastle,但我正在尝试使用 .Net Core 本机执行此操作。

ImportCspBlob 的格式是 ExportCspBlob 的格式,这是 CryptImportKey 要求的 PRIVATEKEY blob 格式。由于 .NET 只是透明地将其传递给 Windows CAPI,ImportCspBlob 方法会在非 Windows 平台上抛出。

我过去为导入私钥(包括 PKCS#1 RSAPrivateKey)给出的另一个答案有点像元答案,其中包含使事情正常运行的链接:Digital signature in c# without using BouncyCastle

.NET Core 3.0 的每日构建版本内置了该功能。大多。 PEM 格式在实践中很容易,但在规范中有些烦人,因此这些方法将其留给调用者 "un-PEM" 数据...对于没有属性的单值有效负载的默认格式(如你在你的例子中)你可以通过

每天构建
private static RSA ReadKeyFromFile(string filename)
{
    string pemContents = System.IO.File.ReadAllText(filename);
    const string RsaPrivateKeyHeader = "-----BEGIN RSA PRIVATE KEY-----";
    const string RsaPrivateKeyFooter = "-----END RSA PRIVATE KEY-----";

    if (pemContents.StartsWith(RsaPrivateKeyHeader))
    {
        int endIdx = pemContents.IndexOf(
            RsaPrivateKeyFooter,
            RsaPrivateKeyHeader.Length,
            StringComparison.Ordinal);

        string base64 = pemContents.Substring(
            RsaPrivateKeyHeader.Length,
            endIdx - RsaPrivateKeyHeader.Length);

        byte[] der = Convert.FromBase64String(base64);
        RSA rsa = RSA.Create();
        rsa.ImportRSAPrivateKey(der, out _);
        return rsa;
    }

    // "BEGIN PRIVATE KEY" (ImportPkcs8PrivateKey),
    // "BEGIN ENCRYPTED PRIVATE KEY" (ImportEncryptedPkcs8PrivateKey),
    // "BEGIN PUBLIC KEY" (ImportSubjectPublicKeyInfo),
    // "BEGIN RSA PUBLIC KEY" (ImportRSAPublicKey)
    // could any/all be handled here.
    throw new InvalidOperationException();
}

可以从 https://github.com/dotnet/core-sdk/#installers-and-binaries

获取 .NET Core SDK 的每日构建

如果代码中不需要PEM转DER,可以使用openssl获取DER编码的私钥文件:

openssl rsa -in key.pem -out key.der -outform der

.Net Cryptographic API 不支持业界广泛使用的 PEM 文件,因此我们需要将其转换为 Microsoft 推出的 XML 格式。基本上,解决方案是在 C# Extract public key from RSA PEM private key.

的另一个类似问题中找到的

有很多将 PEM 转换为 XML 的在线工具,只需将您的 pem 转换为 xml,然后

RSA.FromXmlString(string xmlString)