【发布时间】:2018-02-28 07:51:58
【问题描述】:
我编写了一个 .NET 应用程序,它尝试使用 ECC 客户端证书进行相互身份验证(曲线是 BrainpoolP384r1)。 该证书由 PKI 签名,当我在 ASN1 查看器中查看它时,它似乎完全有效。 我通过以下方式获取证书字节数据:
Console.WriteLine($"Certificate:{BitConverter.ToString(cert.RawData).Replace("-","")}");
在 MMC 控制台中查看证书似乎也是有效的。
但是,当我尝试使用它作为客户端进行身份验证时,它会以CRYPT_E_ASN1_BADTAG 失败。
我尝试验证的代码-sn-p:
TcpClient client = new TcpClient(serverName, 9909);
Console.WriteLine("Client connected.");
SslStream sslStream = new SslStream(
client.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
try
{
var certificates = new X509CertificateCollection();
certificates.Add(cert);
sslStream.AuthenticateAsClient(serverName, certificates, SslProtocols.Tls12, false);
}
catch (Exception e)
{
Console.WriteLine("Exception: {0} \n{1}", e.Message, e.StackTrace);
if (e.InnerException != null)
{
Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
}
Console.WriteLine("Authentication failed - closing the connection.");
client.Close();
return;
}
例外:
例外:ASN1 Ungültiger Kennzeichenwert 在 System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPI 接口 secModule、字符串包、CredentialUse 意图、SCHANNEL_CRED scc) 在 System.Net.Security.SslStreamPal.AcquireCredentialsHandle(CredentialUse credUsage,SCHANNEL_CRED 安全凭证) 在 System.Net.Security.SslStreamPal.AcquireCredentialsHandle(X509Certificate 证书、SslProtocols 协议、EncryptionPolicy 策略、布尔值 是服务器) 在 System.Net.Security.SecureChannel.AcquireClientCredentials(字节 []& 拇指印) 在 System.Net.Security.SecureChannel.GenerateToken(Byte[] 输入,Int32 偏移量,Int32 计数,Byte[]& 输出) 在 System.Net.Security.SecureChannel.NextMessage(字节 [] 传入,Int32 偏移量,Int32 计数) 在 System.Net.Security.SslState.StartSendBlob(字节 [] 传入,Int32 计数,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.ProcessReceivedBlob(字节 [] 缓冲区,Int32 计数,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartReadFrame(字节 [] 缓冲区,Int32 读取字节,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartReceiveBlob(字节 [] 缓冲区,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken 消息,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.StartSendBlob(字节 [] 传入,Int32 计数,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.ForceAuthentication(布尔接收第一,字节 [] 缓冲区,AsyncProtocolRequest asyncRequest) 在 System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult 懒惰的结果) 在 System.Net.Security.SslStream.AuthenticateAsClient(字符串 targetHost,X509CertificateCollection clientCertificates,SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation)
与 MS 一样,失败的原因不够详细,无法解决问题。有什么办法可以查出证书中大约 70 个标签中的哪一个是无效的?
还有一条信息:密钥对和 csr 是使用 bouncycastle 创建的,因为我没有找到仅使用 .NET 进行 cmp 请求的方法。这可能是原因吗?但是为什么证书在 mmc 控制台中显示为有效呢?
很抱歉没有提供完整的可验证示例,但即使是用于创建 csr、发送它、将私钥附加到证书并将其存储在 MYStore 中的精简代码也太长了,而且没有 PKI 绝对没用。
更新
从商店加载证书的代码如下:
static X509Certificate2 LoadFromStore(string commonName)
{
var distinguishedName = "CN=" + commonName;
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2 result = null;
foreach (var cert in store.Certificates)
{
if (cert.SubjectName.Name != null && cert.SubjectName.Name.Equals(distinguishedName))
{
Console.WriteLine("Found certificate in local store: " + cert.SubjectName.Name);
result = cert;
break;
}
}
store.Close();
return result;
}
【问题讨论】:
-
如何获得证书?
-
@pepo 更新了我的问题以包含我如何从商店加载证书的信息。
-
你确定证书已经找到了吗?当你运行X509Certificate2.Verify 时会发生什么?您正在打开 CurrentUser 商店。您确定证书在正确的用户存储(您的存储)中吗?
-
@pepo 这很有趣。
cert.Verify()返回 false,但如果我按照问题开头所述将证书字节写入控制台并将输出粘贴到 ASN1 查看器,一切看起来都不错。 -
好的,在命令行中尝试
certutil -user -store my。 Certutil 将检查 CurrentUser\My 商店中的所有证书及其私钥。它给你的证书带来什么结果?加密/签名通过?
标签: c# .net bouncycastle x509certificate2 ecdsa