如何在C#上读取.Key文件? [英] How To Read .Key file on C#?

查看:269
本文介绍了如何在C#上读取.Key文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我按如下方式读取.der文件.

I read the .der file as follows.

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

,但没有私钥.它只有公共密钥.

but it doesn't have private key. It has only public key.

cert.HasPrivateKey返回false.

cert.HasPrivateKey return false.

搜索时,我发现".der文件没有私钥,私钥位于.key文件中".

When I search it, I found that '.der file doesn't have private Key, private Key is in .key file'.

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

I use Notepad ++ to open a .key file in the same path as the .der file, the broken text will be printed.

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

first question, How to read private key from .key file on C#?

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

and second, How to convert .key file to .pem file on C#? Is it just using openssl?

感谢您的教your.

推荐答案

.NET的当前版本在这里没有一个很好的故事. .NET Core 3.0有一个更好的故事.而且,如果您愿意将NuGet包与"Experimental"包一起使用,以他们的名义,有一个更好的故事.

Current versions of .NET don't have a very good story here. .NET Core 3.0 has a better story. And if you're willing to use NuGet packages with "Experimental" in their name there's a differently better story.

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

没有解决办法.

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

There's not a single answer, you need to know what kind of file you have (or just try al the answers).

  • RSA
    • 导入RSAPrivateKey
      • 当数据采用PKCS#1 RSAPrivateKey格式(PEM打开头:BEGIN RSA PRIVATE KEY)时
      • RSA
        • ImportRSAPrivateKey
          • For when the data is in the PKCS#1 RSAPrivateKey format (PEM open header: BEGIN RSA PRIVATE KEY)
          • 当数据采用PKCS#8 PrivateKeyInfo格式(PEM打开头:BEGIN PRIVATE KEY)时
          • 用于数据采用PKCS#8 EncryptedPrivateKeyInfo格式(PEM打开标头:BEGIN加密的私钥)时
          • ImportECPrivateKey
            • 当数据采用RFC 5915 ECPrivateKey格式(PEM开放头:BEGIN EC PRIVATE KEY)时
            • ImportECPrivateKey
              • For when the data is in the RFC 5915 ECPrivateKey format (PEM open header: BEGIN EC PRIVATE KEY)
              • ImportECPrivateKey
              • ImportPkcs8PrivateKey
              • ImportEncryptedPkcs8PrivateKey
              • ImportPkcs8PrivateKey
              • ImportEncryptedPkcs8PrivateKey

              这些方法的警告是它们仅了解BER/DER数据,而不了解PEM数据.因此,如果您的文件为PEM格式(这样可以最轻松地确定有效载荷应该是什么),则首先需要将其转换为BER/DER.

              The caveat to these methods is that they only understand BER/DER data, not PEM data. So if your file is in the PEM format (which makes it easiest to identify what the payload is supposed to be) you first need to convert it to BER/DER.

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

              For most PEM files that's easy: you just find the contents between the BEGIN and END markers, run it through Convert.FromBase64String, and voila. Technically PEM supports attributes, and dealing with those is harder (and beyond the scope of this answer).

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

              So, you might end up with something like

              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值是从输入字节使用的字节数.它主要仅在从文件中间读取时才有意义.

              The ignored out values are the number of bytes that were used from the input bytes. It's mainly only relevant when reading from the middle of a file.

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

              No solution, this library is much lower level than that.

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

              Okay, this isn't really a way the question was interpreted, but a segue.

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

              Cryptographic key files are always (in my experience) DER- (though occasionally relaxed to BER-) encoded ASN.1 data structures. To fully understand them you would need to read and understand

              • 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,作为依赖项)
                • ITU-T REC X.680: The ASN.1 language
                • ITU-T REC X.690 The Basic Encoding Rules (BER) byte layout for ASN.1 data (and also the rarely-used restrictions Canonical Encoding Rules (CER) and commonly-used restrictions Distinguished Encoding Rules (DER)).
                • Whatever thing describes the particular formats, and possibly things they reference.
                  • RSAPrivateKey: Public Key Cryptography Standards #1 (PKCS#1) or RFC 8017
                  • ECPrivateKey: RFC 5915
                  • PKCS#8 PrivateKeyInfo: PKCS#8 / RFC 5208
                  • PKCS#8 EncryptedPrivateKeyInfo: PKCS#8 / RFC 5208 (and PKCS#5, at least, as dependencies)

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

                  These structures are then sometimes converted to a textual representation using the Privacy Enhanced Mail (PEM) syntax, which is essentially

                  • 5个连字符减号
                  • 大写字母BEGIN后跟一个空格
                  • 格式标识符,不以空格结尾
                  • 5个连字符减号
                  • 换行符(CRLF或LF)
                  • BER/DER数据的base64编码版本,每行64个字符包装
                  • base64数据最后一部分末尾的换行符(CRLF或LF)
                  • 5个连字符减号
                  • 大写字母END后跟一个空格
                  • 与BEGIN中使用的格式标识符相同
                  • 5个连字符减号
                  • (理想情况下是换行符或只是文件结尾)
                  • 5 hyphen-minus characters
                  • All-caps BEGIN followed by a space
                  • A format identifier, not ending in a space
                  • 5 hyphen-minus characters
                  • A newline (CRLF or LF)
                  • The base64-encoded version of the BER/DER data, wrapped at 64 characters per line
                  • A newline (CRLF or LF) at the end of the last part of the base64 data
                  • 5 hyphen-minus characters
                  • All-caps END followed by a space
                  • The same format identifier used in BEGIN
                  • 5 hyphen-minus characters
                  • (ideally a newline or just end-of-file)

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

                  See RFC 7468 for more information.

                  没有解决办法.

                  没有解决办法.

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

                  This NuGet package is the ASN.1 reader from .NET Core 2.1 / 3.0 made public (with the idea that it becomes public from .NET Core after some usability feedback).

                  例如,要读取RSAPrivateKey:

                  To read an RSAPrivateKey, for example:

                  // 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#上读取.Key文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆