RSA模数和公钥的指数

时间:2013-06-13 11:01:13

标签: c# rsa x509

我基本上遇到与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代表类型长度值。因此,如果我将其更正,则包含公钥的字节数组的第一位具有关于模数据的位数的信息。使用该信息我应该将公钥中的位数复制到另一个数组中,并将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);

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

而不是所有这些TLV业务,我也尝试过简单

RSACryptoServiceProvider publicKey = trustedRootCertificate.PublicKey.Key as RSACryptoServiceProvider;

作为我上面链接的问题中的人,但使用此VerifyData调用然后在我认为不应该返回false时返回false。应用程序从服务器获取的证书具有trustedRootCertificate作为其根证书,我应该可以使用它,对吗? root的公钥应该能够验证服务器的证书吗?

我很可能从一开始就错误地证明了证书验证的基础知识。如果情况并非如此,那么我的问题是如何获得这些值

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

来自我所拥有的受信任根证书的公钥。

编辑:我还验证了从文件加载的根证书和应用程序从服务器获取的证书是他们应该打印出来的信息,所以问题至少在于证书错了。我只是不知道如何正确使用它们。

1 个答案:

答案 0 :(得分:2)

假设您遇到了包含以下长度的BIT STRING类型 - Value ::

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