我基本上有和this question一样的问题,但是我无法填补被接受的答案中遗漏的显而易见的小部分。我正在用Mono在C#中做这个。RSA模数和公开密钥的指数
我有一个CA根证书,从那我可以得到一个字节[]持有公钥。然后我得到一个我需要验证的不受信任的证书。据我所知,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);
}
或者我应该使用certificateData(证书的返回值。 VerifyData调用中的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,如果我认为它不应该。应用程序从服务器获得的证书具有trustedRootCertificate作为其根证书,我应该可以这样做,对吗?根的公钥应该能够验证服务器的证书?
这是非常有可能的,我只是从一开始就有错误的证书验证的基础知识。如果情况并非如此,那么我的问题是如何获得这些值
// The value of the second TLV in your Public Key
..
// The value of the first TLV in your Public Key
从我所拥有的可信根证书的公共密钥。
编辑:我也证实,从文件加载的根证书和应用程序从服务器获取的证书是他们应该通过打印出他们的信息,所以问题不是至少在证书是错误的。我只是不知道如何正确使用它们。
我不知道我是否说清楚了解你的问题,但仍然有你通过这个:: http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/4282dda1-4803-435a-b63a-65e2d5ac9941 – Abhineet
是的,这正是我得到trustedRootCertificate.PublicKey.Key作为RSACryptoServiceProvider的途径。至于理解这个问题,这个帖子现在几乎认为第一句中链接的问题也被读取了。我会编辑我的问题,使之更独立。 – riksteri