在c#中使用带有文件和密钥的X509Certificate

Sae*_*ani 5 c# java ssl-certificate x509certificate

我已将证书和密码提供给接受ssl连接的服务器.我试图建立与此服务器的连接,但身份验证失败,主要是因为我不知道如何使用我给出的文件和密码.

这是我的代码:

    X509Certificate certificate = new X509Certificate(
        @"c:\mySrvKeystore", KEY_PASSWORD);

    public static bool ValidateCertificate(
        object sender,
        X509Certificate certificate,
        X509Chain chain,
        SslPolicyErrors errors)
    {
        if (errors == SslPolicyErrors.None)
            return true;

        Console.WriteLine("Certificate error: {0}", errors);
        return false;
    }

    public void RunClient(string address, int port)
    {
        Console.WriteLine("Starting client...");
        var client = new TcpClient(address, port);


        Console.WriteLine("Client connected.");


        var stream = new SslStream(client.GetStream(),false,
            ValidateCertificate, null);

        try
        {
            stream.AuthenticateAsClient(address);

            Console.WriteLine(stream.IsAuthenticated ? "Client authenticated." : "Client is not authenticated.");

            //TODO constantly read from server!
        }
        catch (AuthenticationException ae)
        {
            Console.WriteLine("Exception occured: {0}", ae.Message);

            if (ae.InnerException != null)
            {
                Console.WriteLine("Inner exception: {0}", ae.InnerException.Message);
            }

            Console.WriteLine("Failed to authenticate! closing the client...");

            client.Close();

            return;
        }
        catch (Exception ex)
        {
            Console.WriteLine("General exception occured {0}", ex.Message);
            client.Close();
            return;
        }
    }
Run Code Online (Sandbox Code Playgroud)

所以你可以看到,我的代码中没有代码以某种方式告诉服务器(TcpClient或SSLStream)我有这个文件和密钥!

我有一个javacode连接到服务器没有问题,但我没有将它转换为c#.任何帮助都会很棒!

    String keyPassword = "123456";
    // String keyPassword = "importkey";

    try {
        KeyManagerFactory keyManagerFactory;

        keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
        KeyStore keyStore = KeyStore.getInstance("JKS");
        InputStream keyInput = new FileInputStream("c:\\mySrvKeystore");
        keyStore.load(keyInput, keyPassword.toCharArray());
        keyInput.close();
        keyManagerFactory.init(keyStore, keyPassword.toCharArray());

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(keyManagerFactory.getKeyManagers(), trustAllCerts, new java.security.SecureRandom());
        SSLSocketFactory sslsocketfactory = sc.getSocketFactory();
        this.sslsocket = (SSLSocket) sslsocketfactory.createSocket(host, port);

    } catch (java.security.NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (java.security.KeyManagementException e) {
        e.printStackTrace();
    } catch (java.security.KeyStoreException e) {
        e.printStackTrace();
    } catch (java.security.cert.CertificateException e) {
        e.printStackTrace();
    } catch (java.security.UnrecoverableKeyException e) {
        e.printStackTrace();
    } finally {}
}

public void run() {
    try {
        InputStream inputstream = sslsocket.getInputStream();
        InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
        BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

        OutputStream outputstream = System.out;
        OutputStreamWriter outputstreamwriter = new OutputStreamWriter(outputstream);
        BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter);

        //get text from server and stuff...no deal!
Run Code Online (Sandbox Code Playgroud)

UPDATE

根据gtrig将密钥转换为p12之后,现在的问题是AutheneticateAsClient方法中的IOException :

        try
        {
            var certificate = new X509Certificate2(@"d:\mySrvKeystore.p12", "123456");


            X509Certificate2[] X509Certificates = {certificate};
            var certsCollection = new X509CertificateCollection(X509Certificates);

            //IO EXCEPTION HERE-->
            stream.AuthenticateAsClient(address, certsCollection, SslProtocols.Ssl2, false);
            Console.WriteLine(stream.IsAuthenticated ? "Client authenticated." : "Client is not authenticated.");

            //TODO constantly read from server!
        }
Run Code Online (Sandbox Code Playgroud)

当我使用时SSlProtocols.Default,错误是:RemoteCertificateNameMismatch, RemoteCertificateChainErrors

gtr*_*rig 5

这个答案可能不会让你一路走到那里,但它应该让你接近。

您获得了一个 Java KeyStore (JKS),其中包含一个私钥和相应的证书。根据您的密码打开 JKS 的密码是“123456”。

因为 JKS 包含一个私钥,并且通过查看您的 Java 代码,我相信您需要一个 2 向(相互)SSL 连接。这基本上意味着您作为客户端对服务器进行身份验证并且服务器对您进行身份验证。此 JKS 文件是您使用服务器的凭据。

那么如何在 C# 中使用它呢?首先,让我们使用以下命令将 JKS 转换为 PKCS12 密钥库:

keytool -importkeystore -srckeystore mySrvKeystore -destkeystore mySrvKeystore.p12 -srcstoretype JKS -deststoretype PKCS12
Run Code Online (Sandbox Code Playgroud)

现在,您可以将 PKCS12 文件导入到您的 Windows 密钥库中,这样应该可以轻松地从 C# 访问它。或者,您可以使用以下代码将其导入X509Certificate2对象:

X509Certificate2 cert = X509Certificate2("C:\Path\mySrvKeystore.p12", "123456");
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用 C# 中的 Windows 密钥库或 X509Certificate2 对象来建立 SSL 连接。


Cee*_*lie 2

您应该将 AuthenticateAsClient 与证书列表一起使用:

X509Certificate[] X509Certificates = { certificate };
X509CertificateCollection certsCollection = new X509CertificateCollection(X509Certificates);

sslStream.AuthenticateAsClient(address, certsCollection, SslProtocols.Default, false);
Run Code Online (Sandbox Code Playgroud)

为了避免证书错误:更改

  public static bool ValidateCertificate(
   object sender,
   X509Certificate certificate,
   X509Chain chain,
   SslPolicyErrors errors)
   {
        if (errors == SslPolicyErrors.None)
            return true;
        if (certificate != null)
        {
            string SendingCertificateName = "";
            //List<string> Subject = CommaText(certificate.Subject); // decode commalist
            // SendingCertificateName = ExtractNameValue(Subject, "CN"); // get the CN= value
            report = string.Format(CultureInfo.InvariantCulture, "certificatename : {0}, SerialNumber: {1}, {2}, {3}", certificate.Subject, certificate.GetSerialNumberString(), SendingCertificateName, ServerName);
            Console.WriteLine(report);
         }

         Console.WriteLine("Certificate error: {0}", errors);
         int allow = AllowPolicyErrors << 1;  // AllowPolicyErrors property allowing you to pass certain errors
         return (allow & (int)sslPolicyErrors) == (int)sslPolicyErrors;  // or just True if you dont't mind.
    }
Run Code Online (Sandbox Code Playgroud)