如何使用Compact Framework在C#中验证X.509证书

如何使用Compact Framework在C#中验证X.509证书,c#,.net,encryption,compact-framework,x509,C#,.net,Encryption,Compact Framework,X509,我正在尝试使用C#和.NetCF验证X.509证书。我有CA证书,如果我理解正确,我需要使用此CA证书中的公钥来解密不受信任证书的签名。这将为我提供不受信任证书的计算哈希值。然后我应该自己计算证书的散列,并确保两个值匹配 我已经玩了几天了,我没有走多远。我一直在使用X509Certificate和RSACryptServiceProvider类。首先,我尝试从X509Certificate类中获取公钥和签名。我可以得到公钥,但不能得到签名。接下来,我尝试解析组成证书的二进制数据,这允许我获得签名

我正在尝试使用C#和.NetCF验证X.509证书。我有CA证书,如果我理解正确,我需要使用此CA证书中的公钥来解密不受信任证书的签名。这将为我提供不受信任证书的计算哈希值。然后我应该自己计算证书的散列,并确保两个值匹配

我已经玩了几天了,我没有走多远。我一直在使用X509Certificate和RSACryptServiceProvider类。首先,我尝试从X509Certificate类中获取公钥和签名。我可以得到公钥,但不能得到签名。接下来,我尝试解析组成证书的二进制数据,这允许我获得签名(以及我想要的任何其他数据),但我无法使用RSACryptServiceProvider解密签名。我尝试过类似的方法,但在尝试解密时,不断出现异常,称为“坏密钥”:

RSAParameters rsaParams = new RSAParameters();
rsaParams.Exponent = exp;
rsaParams.Modulus = mod;
RSACryptoServiceProvider rsaServ = new RSACryptoServiceProvider();
rsaServ.ImportParameters(rsaParams);
byte[] decryptedSig = rsaServ.Decrypt(encryptedSig, false);
如有任何建议,将不胜感激

编辑: 我尝试了一些似乎更好的方法,但结果却很奇怪。我在这里使用X509Certificate2类,因为它更容易测试,但稍后我需要切换到X509Certificate for.NetCF。我想我需要的可能是RSACryptServiceProvider.VerifyData。我尝试了以下代码

X509Certificate2 cert = new X509Certificate2(certBytes);
X509Certificate2 certCA1 = new X509Certificate2(@"C:\certs\certCA1.cer");

byte[] encryptedSig = new byte[256];
Array.Copy(certBytes, certBytes.Length - 256, encryptedSig, 0, 256);

RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certA1.PublicKey.Key;
bool good = rsa.VerifyData(cert.RawData, "1.3.14.3.2.26", encryptedSig);
正如我所说,我能够手动解码和解释证书的二进制数据,因此我非常确定cert.RawData是证书的签名数据,最后256个字节是加密签名。该字符串是哈希算法的OID,我从证书中获得,但我不能100%确定它是否正确。VerifyData返回false,但我还不确定原因


想法

WinCE是否支持与Win32 MSCrypto.dll兼容的东西?如果是,请看一下.NET类以及它包含了许多对.NET有用的例程,这些例程位于核心OS crypto库之上。您可以下载源代码并查看它是如何为.NetCF编译的

要加载和验证X509证书,请执行以下操作(未测试):

var cert=新的X509Certificate2(“mycert.cer”);
如果(!cert.Verify())
{
}
X509Certificate2有近十几个构造函数可以从各种各样的源中构造—磁盘上的文件、内存中的字节数组、从本地证书存储加载等等

用于签署证书的根CA需要安装在本地证书存储中。如果证书不包括信任链中的中间CA,则这些中间CA也需要在本地计算机上,一直到本地计算机中受信任证书存储中的根CA


不幸的是,我无法从MSDN文档中判断X509Certificate2是否在.NetCF上可用。

它在win32中对我有效,但在Compact Framework中,我面临同样的问题,没有X509Certificate2,因此我实际上被阻止了,使用win32我们可以做到:

X509Certificate2 l__PublicKeyCertificate = new X509Certificate2("cert.cer");

RSACryptoServiceProvider l__rsaCspPublic = (RSACryptoServiceProvider)l__PublicKeyCertificate .PublicKey.Key;

//...

l__isVerified = l__rsaCspPublic.VerifyData(l__fileData, CryptoConfig.MapNameToOID("SHA1"), l__fileSignature);
这是我的密码

RSACryptoServiceProvider rsa = signingCertificate_GetPublicKey();
return rsa.VerifyData( SignedValue(), CryptoConfig.MapNameToOID( "SHA1" ), Signature() );

RSACryptoServiceProvider signingCertificate_GetPublicKey()
{
    RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();

    RSAParameters publicKeyParams = new RSAParameters();
    publicKeyParams.Modulus = GetPublicKeyModulus();
    publicKeyParams.Exponent = GetPublicKeyExponent();

    publicKey.ImportParameters( publicKeyParams );

    return publicKey;
}

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
}

我希望这对解决这个问题的任何人都有帮助。

WinCE的局限性可能很粗糙,而且我对X.509完全不熟悉,所以我实际上一直在尝试先在正常的Win32环境中工作,但我甚至无法做到这一点。我查看了您指向的CLR安全库,但没有看到任何验证X509证书的内容。您能再给我一点介绍吗?X509Certificate2在.NetCF上不可用,但这很有帮助。谢谢。我刚才想出来了,忘了贴答案了。我会看一下我的源代码,并在周一之前得到答案。
RSACryptoServiceProvider rsa = signingCertificate_GetPublicKey();
return rsa.VerifyData( SignedValue(), CryptoConfig.MapNameToOID( "SHA1" ), Signature() );

RSACryptoServiceProvider signingCertificate_GetPublicKey()
{
    RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();

    RSAParameters publicKeyParams = new RSAParameters();
    publicKeyParams.Modulus = GetPublicKeyModulus();
    publicKeyParams.Exponent = GetPublicKeyExponent();

    publicKey.ImportParameters( publicKeyParams );

    return publicKey;
}

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
}