Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在c中使用带有文件和密钥的X509Certificate#_C#_Java_Ssl Certificate_X509certificate - Fatal编程技术网

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

C# 在c中使用带有文件和密钥的X509Certificate#,c#,java,ssl-certificate,x509certificate,C#,Java,Ssl Certificate,X509certificate,我已将证书和密码提供给接受ssl连接的服务器。我试图连接到此服务器,但身份验证失败,主要是因为我不知道如何使用提供给我的文件和密码 这是我的密码: X509Certificate certificate = new X509Certificate( @"c:\mySrvKeystore", KEY_PASSWORD); public static bool ValidateCertificate( object sender, X

我已将证书和密码提供给接受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;
        }
    }
如您所见,我的代码中没有任何代码以某种方式告诉服务器(TcpClient或SSLStream)我确实拥有此文件和密钥

我有一个连接到服务器的Java代码,没有问题,但我还没有将其转换为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!
更新

根据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!
        }

另外,当我使用
SSlProtocols.Default
时,错误是:
RemoteCertificateNameMismatch,RemoteCertificateChainErrors
您应该使用AuthenticateTasClient和证书列表:

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

sslStream.AuthenticateAsClient(address, certsCollection, SslProtocols.Default, false);
要避免证书错误,请执行以下操作: 改变

公共静态bool ValidateCertificate(
对象发送器,
X509证书,
X509链条,
SslPolicyErrors(错误)
{
if(errors==SslPolicyErrors.None)
返回true;
如果(证书!=null)
{
字符串SendingCertificateName=“”;
//List Subject=CommaText(certificate.Subject);//解码commalist
//SendingCertificateName=ExtractNameValue(主题“CN”);//获取CN=value
report=string.Format(CultureInfo.InvariantCulture,“certificatename:{0},SerialNumber:{1},{2},{3}”,certificate.Subject,certificate.GetSerialNumberString(),SendingCertificateName,ServerName);
控制台。写入线(报告);
}
WriteLine(“证书错误:{0}”,错误);

int allow=allowpolicycerrors这个答案可能不会让你一直走到那里,但它应该会让你接近

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

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

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

keytool -importkeystore -srckeystore mySrvKeystore -destkeystore mySrvKeystore.p12 -srcstoretype JKS -deststoretype PKCS12
现在,您可以将PKCS12文件导入Windows密钥库,这将使其易于从C#访问。或者,您可以使用以下代码将其导入对象:

X509Certificate2 cert = X509Certificate2("C:\Path\mySrvKeystore.p12", "123456");

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

从您的Java代码中,您拥有的文件是JKS密钥库。您知道它是否只包含证书,还是也包含私钥?这是单向SSL还是双向SSL(客户端身份验证)连接?@gtrig我不是很确定,但我猜它只有证书,私钥只是我代码中的密码。而且我认为它是单向连接,因为我知道服务器流数据,我不应该向服务器发送任何东西。但是从java代码判断,它可能还包括密钥,因为在Java代码。请在JKS密钥库文件上运行此命令:
keytool-list-v-keystore mySrvKeystore
。查看输出是否显示“PrivateKeyEntry”或者,如果只有证书条目。代码中的密码是打开JKS密钥库文件的密码。错误来自从服务器收到的证书。指定的地址与服务器证书中的名称不匹配。您有时会在IE中收到该消息。您可以通过在ValidateCer中允许它来始终接受该消息t函数(因此始终返回true).Beter可能是为了确保证书正常。或者记录您允许的有关错误的证书。在de validatecert中放置断点时,您可以检查服务器返回的证书。在java代码中,您也只信任每个证书:trustAllCerts。您尝试过在validatecert()中将false更改为True吗?谢谢,我认为这是一个很好的步骤,至少我在转换之前尝试使用密钥时没有得到
加密异常
。没有。问题是当我尝试作为客户端进行身份验证时出现了新的异常。请检查我上面的更新:而不是SslProtocols.Ssl2,尝试SslProtocols.Tls、SslProtocols.Tls11或SslProtocols.Tls12。Ssl2与客户端证书不兼容。不是真的,我希望我能以某种方式将文件发送给您:p当您执行
keytool-list…
命令时,是“所有者”还是“颁发者”PrivateKeyEntry的值相同或不同?密钥库中是否列出了其他条目?感谢您提醒我不接受所有证书的问题,这就是问题所在,当我在validate方法中返回true时,它工作正常!
X509Certificate2 cert = X509Certificate2("C:\Path\mySrvKeystore.p12", "123456");