AuthenticatAsClient fails with CRYPT_E_ASN1_BADTAG

与世无争的帅哥 提交于 2019-12-11 14:55:29

问题


I have written a .NET application that tries to do mutual authentication with an ECC client certificate (curve is brainpoolP384r1). The certificate is signed by a PKI and when I look at it in an ASN1 viewer it seems to be perfectly valid. I get the certificate byte data for this the following way:

Console.WriteLine($"Certificate:{BitConverter.ToString(cert.RawData).Replace("-","")}");

Looking at the certificate in the MMC console it also appears to be valid.

However, when I try to use it to authenticate as a client it fails with CRYPT_E_ASN1_BADTAG.

The code-snippet where I try to authenticate:

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;
}

The exception:

Exception: ASN1 Ungültiger Kennzeichenwert at System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface secModule, String package, CredentialUse intent, SCHANNEL_CRED scc) at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(CredentialUse credUsage, SCHANNEL_CRED secureCredential) at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(X509Certificate certificate, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer) at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint) at System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output) at System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count) at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest) at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult) at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation)

As usual for MS the reason for the failure is not detailed enough to fix the issue. Is there any way to find out which of the approximately 70 tags in the certificate is invalid?

One more piece of information: The keypair and the csr are created using bouncycastle as I did not find a way to do a cmp-request with .NET only. Could this be the reason? But why is the certificate displayed as valid in the mmc console?

Sorry for not providing a complete verifiable example but even the stripped down code for creating the csr, sending it, attaching the private key to the certificate and storing it in the MYStore is way to long and without a PKI absolutely useless.

UPDATE

The code to load the certificate from the store is as follows:

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;
}

回答1:


As usual when working with microsoft APIs the error has nothing to do with the real reason... :-(

The cause of all this was a wrong csr that made the received certificate have valid ASN1 structure (verified with http://lapo.it/asn1js/) with invalid content. How to do it right can be found in the answer to this SO question.

User pepo helped me a lot to get on the right track (Thank you once again!). His comment suggesting to use certutil -user -store my instead of looking at the MMC console was the hint I needed to sort this out.



来源:https://stackoverflow.com/questions/49024466/authenticatasclient-fails-with-crypt-e-asn1-badtag

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!