我基本上有与this question中相同的问题,但是我在填写从接受的答案中遗漏的看似琐碎的部分时遇到了麻烦。我在C#中使用Mono进行此操作。

我有一个CA根证书,从中我可以得到一个持有公钥的byte []。然后,我得到了我需要验证的不受信任的证书。据我了解,RSACryptoServiceProvider.VerifyData应该可以解决问题,但是首先我需要使用公钥的模数和指数来设置RSAParameters。

(编辑:以下重复从我上面链接到的问题中已经显而易见的一些事情。)
应该执行我需要的代码并用我信任的根证书验证服务器证书的代码如下:

RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();
RSAParameters publicKeyParams = new RSAParameters();
publicKeyParams.Modulus = GetPublicKeyModulus();
publicKeyParams.Exponent = GetPublicKeyExponent();
publicKey.ImportParameters(publicKeyParams);
return publicKey.VerifyData(SignedValue(), CryptoConfig.MapNameToOID("SHA1"), Signature());


我的问题是GetPublicKeyModulus()和GetPublicKeyExponent()的内容。在接受的答案中,它们显然是无关紧要的,只是有一条评论说模数是我的公钥中第一个TLV的值,而指数是公钥中的第二个TLV。我不完全明白那是什么意思。

byte[] GetPublicKeyExponent()
{
  // The value of the second TLV in your Public Key
}

byte[] GetPublicKeyModulus()
{
  // The value of the first TLV in your Public Key
}
byte[] SignedValue()
{
  // The first TLV in your Ceritificate
}

byte[] Signature()
{
  // The value of the third TLV in your Certificate
}


我的问题是这些“第一个TLV” /“第二个TLV”到底是什么意思,如何从已拥有的字节数组中获取这些值?

据我了解,TLV代表type-length-value。因此,如果我正确无误,则包含公用密钥的字节数组的第一位具有有关模数数据有多少位的信息。使用该信息,我应该将一定数量的位从公共密钥复制到另一个数组,并将RSAParameters.Modulus设置为该值。在公钥中的模数达到指数之后,我应该对此进行相同的操作。但是我找不到包含的公钥数据中TLV的“ TL”部分的位数和格式的信息。

我在其他地方找到了信息,说模数是公钥中的前1024位,而指数是余数,但这在字节数组之间复制数据时给了我关于大小的错误。

目前,我根据所链接问题中的可接受答案所形成的代码基本上是这样的:

using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;

X509Certificate2 trustedRootCertificate = new X509Certificate2(X509Certificate2.CreateFromCertFile(filename));
ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;
.
.
public bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
  .
  .
  byte[] publicKeyBytes = trustedRootCertificate.GetPublicKey();
  byte[] modulusData = // The value of the first TLV in the Public Key??
  byte[] exponentData = // The value of the second TLV in the Public Key??

  RSAParameters publicKeyParams = new RSAParameters();
  publicKeyParams.Modulus = modulusData;
  publicKeyParams.Exponent = exponentData;
  RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();
  publicKey.ImportParameters(publicKeyParams);

  byte[] certificateData = certificate.GetRawCertData();
  byte[] signedValue = // The first TLV in the certificate??
  byte[] encryptedSignature = // The third TLV in the certificate??

  return publicKey.VerifyData(certificateData, HashAlgorithm.Create("SHA1"), encryptedSignature);
}


还是应该在VerifyData调用中使用certificateData(certificate.GetRawCertData()的返回值)?

在其他地方,我发现加密签名部分是certificateData中的最后256位,我不确定这是否与“证书中的第三个TLV”相同。如果没有,我会做

byte[] certificateData = certificate.GetRawCertData();
byte[] encryptedSignature = new byte[256];
System.Array.Copy(certificateData, certificateData.Length - 256, encryptedSignature, 0, 256);


然后使用crypticedSignature作为VerifyData调用中的最后一个参数。

除了尝试所有TLV业务之外,我还尝试了其他方法

RSACryptoServiceProvider publicKey = trustedRootCertificate.PublicKey.Key as RSACryptoServiceProvider;


作为我在上面链接到问题中的人,但是使用此方法,当我认为不应该使用VerifyData调用时返回false。应用程序从服务器获取的证书已将trustRootCertificate作为其根证书,我应该能够做到这一点,对吗?根的公共密钥应该能够验证服务器的证书吗?

从一开始我很有可能只是对证书验证的基础知识有误。如果不是这种情况,那么我的问题是如何获得这些价值

// The value of the second TLV in your Public Key
..
// The value of the first TLV in your Public Key


从我拥有的受信任的根证书的公钥中。

编辑:我还通过打印信息验证了文件加载的根证书和应用从服务器获取的证书,因此问题至少不在于证书有误。我只是不知道如何正确使用它们。

最佳答案

假设您遇到的BIT STRING类型包含以下“长度-值”:

03(T - BIT STRING)
82(Read next 2 Bytes for actual Length)
01 0F(Actual Length of whole BIT STRING)

---BIT STRING Value Starts Here---
00(First Byte Of BIT STRING specifies the number of bits left unused in the final byte of BIT STRING which in this case is 0)

30(T - SEQUENCE)
82(Read next 2 Bytes for actual Length)
01 0A(Actual Length of whole SEQUENCE)

---SEQUENCE Value Starts Here---
02(T - INTEGER)
82(Read next 2 Bytes for actual Length)
01 01(Actual Length of whole INTEGER)

(Value starts from here till "Actual Length of whole INTEGER above")
---INTEGER Value Starts Here---
---Exponent Starts Here---
00 A9  CA B2 A4 CC CD 20 AF 0A
7D 89 AC 87 75 F0 B4 4E  F1 DF C1 0F BF 67 61 BD
A3 64 1C DA BB F9 CA 33  AB 84 30 89 58 7E 8C DB
6B DD 36 9E 0F BF D1 EC  78 F2 77 A6 7E 6F 3C BF
93 AF 0D BA 68 F4 6C 94  CA BD 52 2D AB 48 3D F5
B6 D5 5D 5F 1B 02 9F FA  2F 6B 1E A4 F7 A3 9A A6
1A C8 02 E1 7F 4C 52 E3  0E 60 EC 40 1C 7E B9 0D
DE 3F C7 B4 DF 87 BD 5F  7A 6A 31 2E 03 99 81 13
A8 47 20 CE 31 73 0D 57  2D CD 78 34 33 95 12 99
12 B9 DE 68 2F AA E6 E3  C2 8A 8C 2A C3 8B 21 87
66 BD 83 58 57 6F 75 BF  3C AA 26 87 5D CA 10 15
3C 9F 84 EA 54 C1 0A 6E  C4 FE C5 4A DD B9 07 11
97 22 7C DB 3E 27 D1 1E  78 EC 9F 31 C9 F1 E6 22
19 DB C4 B3 47 43 9A 1A  5F A0 1E 90 E4 5E F5 EE
7C F1 7D AB 62 01 8F F5  4D 0B DE D0 22 56 A8 95
CD AE 88 76 AE EE BA 0D  F3 E4 4D D9 A0 FB 68 A0
AE 14 3B B3 87 C1 BB
-----Exponent Ends Here----
---INTEGER Value Ends Here---


02(T - INTEGER)
03(Actual Length cuz 8th Bit Not Set here, so this byte shows the actual length)

---INTEGER Value Starts Here---
----Mod Starts Here---
01 00 01
---Mod Ends Here---
---INTEGER Value Ends Here---

---SEQUENCE Value Ends Here---
---BIT STRING Value Ends Here---


您可能需要阅读ASN.1 Format

10-07 21:07