c# - 如何在C#上读取.Key文件?

标签 c# file pem file-read der

我阅读.der文件如下。

byte[] byteKey = File.ReadAllBytes(openFileDialog1.FileName);
X509Certificate2 cert = new X509Certificate2(byteKey);


但它没有私钥。它只有公共密钥。

cert.HasPrivateKey返回false。

当我搜索它时,我发现“ .der文件没有私钥,私钥位于.key文件中”。

我使用记事本++在与.der文件相同的路径中打开.key文件,将打印出损坏的文本。

第一个问题,如何从C#的.key文件中读取私钥?

第二,如何在C#上将.key文件转换为.pem文件?
只是使用openssl吗?

谢谢您的教your。

最佳答案

.NET的当前版本在这里没有很好的故事。 .NET Core 3.0有一个更好的故事。而且,如果您愿意使用带有“ Experimental”名称的NuGet软件包,那么情况会更好。

注意:在整个答案中,我不会考虑诸如BouncyCastle之类的第三方库。它可能会完美地满足您的要求,但这不是我的专业领域。当我知道它们时,我将考虑由与开发.NET收件箱库相同的一组人员开发的NuGet软件包。

解释1:“我要调用哪种方法从文件中加载私钥?”

当前版本

没有解决方案。

.NET Core 3.0

没有一个答案,您需要知道您拥有哪种文件(或尝试所有答案)。


RSA


ImportRSAPrivateKey


用于数据何时为PKCS#1 RSAPrivateKey格式(PEM打开头:BEGIN RSA PRIVATE KEY)

ImportPkcs8PrivateKey


用于数据何时为PKCS#8 PrivateKeyInfo格式(PEM打开头:BEGIN PRIVATE KEY)

ImportEncryptedPkcs8PrivateKey


用于数据何时为PKCS#8 EncryptedPrivateKeyInfo格式(PEM打开头:BEGIN ENCRYPTED PRIVATE KEY)


ECDSA


ImportECPrivateKey


用于数据何时采用RFC 5915 ECPrivateKey格式(PEM开放头:BEGIN EC PRIVATE KEY)

ImportPkcs8PrivateKey
ImportEncryptedPkcs8PrivateKey

ECDiffieHellman


ImportECPrivateKey
ImportPkcs8PrivateKey
ImportEncryptedPkcs8PrivateKey

DSA


ImportPkcs8PrivateKey
ImportEncryptedPkcs8PrivateKey



这些方法的警告是它们仅了解BER / DER数据,而不了解PEM数据。因此,如果您的文件采用PEM格式(这样最容易识别有效载荷应该是什么),则首先需要将其转换为BER / DER。

对于大多数PEM文件而言,这很容易:您只需在BEGIN和END标记之间找到内容,即可通过Convert.FromBase64String和voila运行它。从技术上讲,PEM支持属性,并且处理属性更加困难(并且超出了此答案的范围)。

因此,您可能最终会遇到类似

RSA rsa = RSA.Create();

try
{
    rsa.ImportRSAPrivateKey(data, out _);
    return rsa;
}
catch (CryptographicException)
{
}

try
{
    rsa.ImportPkcs8PrivateKey(data, out _);
    return rsa;
}
catch (CryptographicException)
{
}

try
{
    // prompt for password, then
    rsa.ImportEncryptedPkcs8PrivateKey(password, data, out _);
    return rsa;
}
catch (CryptographicException)
{
}

rsa.Dispose();
ECDsa ecdsa = ECDsa.Create();
...


被忽略的out值是从输入字节使用的字节数。它主要仅在从文件中间读取时才有意义。

System.Security.Cryptography.Asn1.experimental

没有解决方案,此库的级别比该级别低得多。

解释2:“我如何在实践中理解这些文件?”

好的,这实际上不是问题的解释方式,而是一种猜测。

加密密钥文件(根据我的经验)始终是DER-(尽管偶尔会放宽到BER-)编码的ASN.1数据结构。要完全理解它们,您需要阅读和理解


ITU-T REC X.680:ASN.1语言
ITU-T REC X.690 ASN.1数据的基本编码规则(BER)字节布局(以及很少使用的约束规范编码规则(CER)和常用的约束可分辨编码规则(DER))。
无论什么描述了特定的格式,可能还有它们引用的东西。


RSAPrivateKey:公钥加密标准#1(PKCS#1)或RFC 8017
ECPrivateKey:RFC 5915
PKCS#8 PrivateKeyInfo:PKCS#8 / RFC 5208
PKCS#8 EncryptedPrivateKeyInfo:PKCS#8 / RFC 5208(至少是PKCS#5,作为依赖项)



然后有时会使用“隐私增强邮件”(PEM)语法将这些结构转换为文本表示形式,


5个连字符减号
大写字母BEGIN后跟一个空格
格式标识符,不以空格结尾
5个连字符减号
换行符(CRLF或LF)
BER / DER数据的base64编码版本,每行64个字符
base64数据最后一部分末尾的换行符(CRLF或LF)
5个连字符减号
大写字母END后跟一个空格
与BEGIN中使用的格式标识符相同
5个连字符减号
(理想情况下是换行符或只是文件结尾)


有关更多信息,请参见RFC 7468

解释3:“如何在代码中读取这些文件的部分?”

当前版本

没有解决方案。

.NET Core 3.0

没有解决方案。

System.Security.Cryptography.Asn1.Experimental

此NuGet软件包是.NET Core 2.1 / 3.0公开的ASN.1读取器(其想法是在收到一些可用性反馈后从.NET Core公开)。

例如,要读取RSAPrivateKey:

// PKCS#1 doesn't say that this structure is always DER encoded, so read it as BER
AsnReader reader = new AsnReader(data, AsnEncodingRules.BER);

// RSAPrivateKey ::= SEQUENCE {
AsnReader contents = reader.ReadSequence();

// version Version (0 for two-prime RSA)
if (!contents.TryReadInt32(out int version) || version != 0)
{
    throw new CryptographicException();
}

// modulus INTEGER,
BigInteger modulus = contents.ReadInteger();
// publicExponent INTEGER,
BigInteger publicExponent = contents.ReadInteger();
// privateExponent INTEGER,
BigInteger privateExponent = contents.ReadInteger();
// prime1 INTEGER,
BigInteger prime1 = contents.ReadInteger();
// prime2 INTEGER,
BigInteger prime2 = contents.ReadInteger();
// exponent1 INTEGER,
BigInteger exponent1 = contents.ReadInteger();
// exponent2 INTEGER,
BigInteger exponent2 = contents.ReadInteger();
// coefficient INTEGER,
BigInteger coefficient = contents.ReadInteger();
// otherPrimeInfos OtherPrimeInfos OPTIONAL,
// we don't support this, we limited to version 0.
// good thing the next token is:
// }
contents.ThrowIfNotEmpty();
// All done.
// If you expected no trailing data:
reader.ThrowIfNotEmpty();


其他格式也一样。

关于c# - 如何在C#上读取.Key文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55962625/

相关文章:

python - 使用 MultipartPostHandler 通过 Python 发布表单数据

ssl - 与 PEM 和 DER 证书混淆

paypal - 活跃的商家 Paypal 反复出现 PEM 错误既不是 Pub 也不是 Priv key

c# - 串联使用 Visual Basic 和 C++/C#

c# - 在 C# 中卸载时,如何检查 <service>.exe 上的锁是否已释放?

c# - .Net Core 解决方案中每个项目的 Automapper 不同配置文件

node.js - 如何为 https Web 服务器创建 .pem 文件

javascript - angular 2 文本输入使有意义的强制性

c++ - 在 C++ 中将 2 个文本文件合并到第三个文本文件中

java - 使用 f.delete() 方法删除现有文件