C#客户端通过SSL连接到Java服务器
作为一个团队项目,我需要从C#客户端连接到Java 6.5 SSL服务器,但是当我到达stream.AuthenticateAsClient行时,它会挂起。
As a team project I need to connect from a C# client to a Java 6.5 SSL server, however when I get to the stream.AuthenticateAsClient line it hangs.
C#连接代码
public static void connect(string server, Int32 port)
{
try
{
client = new TcpClient(server, port);
stream = new SslStream(client.GetStream(), false);
stream.AuthenticateAsClient("MyCNfield");
...
...
如果我连接到 https://mail.google.com
并将 MyCNfield
设置为 mail.google.com
,它运行正常,所以我认为它是Java方面。
If I connect to something like https://mail.google.com
and set MyCNfield
to mail.google.com
, it works fine, so I think it is the Java side.
Java Init部分是:
The Java Init section is:
public void initSSL() throws IOException, KeyStoreException, NoSuchAlgorithmException,
CertificateException, UnrecoverableKeyException, KeyManagementException {
char[] passphrase = "scared".toCharArray();
System.out.println(java.security.KeyStore.getDefaultType());
boolean handshakedone=false;
KeyStore keystore1 = KeyStore.getInstance("jks");
FileInputStream fis = new FileInputStream("C:\\\\temp\\\\work.jks");
keystore1.load(fis, passphrase);
fis.close();
KeyStore ksTrust = KeyStore.getInstance("jks");
FileInputStream fis2 = new FileInputStream("C:\\\\temp\\\\work.jks");
ksTrust.load(fis2, passphrase);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
// KeyManager's decide which key material to use.
kmf.init(keystore1, passphrase);
// TrustManager's decide whether to allow connections.
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ksTrust);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init( kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SSLServerSocketFactory sslserversocketfactory =(SSLServerSocketFactory) sslContext.getServerSocketFactory();
sslserversocket =(SSLServerSocket) sslserversocketfactory.createServerSocket(2443);
sslserversocket.setUseClientMode(false);
//Context conte
ServerSocketFactory serversocketfactory =(ServerSocketFactory) sslContext.getServerSocketFactory();
// serverSocket = new ServerSocket(2443);
System.out.println("OK we are set up");
}
它被调用:
sslsocket = (SSLSocket) sslserversocket.accept();
并继续,即使连接未经完全验证。
and continues on, even though the connection was not fully authenticated.
需要更改以解决此问题:JKS的证书 MyCNfield
由我创建的CA签名。如何在我的C#中将证书链导入我的私有CA,或者如何使用Java和C#强制使用自签名证书,并抛弃我当前的JKS?
What needs to be changed to fix this: the JKS has a cert MyCNfield
that is signed by a CA that I created. How do I either import the cert chain to my private CA in my C#, or how do I excange self-signed certs with Java and C#, and just throw out my current JKS?
您需要使用RemoteCertificateValidationCallback回调机制来提供证书身份验证。你不应该关闭这个问题,这是许多人可能有的问题。这个答案是谷歌搜索的第一次点击之一,这得益于stackoverflow的优秀搜索引擎优化,所以它可能会导致人们走错路。
You need to use the RemoteCertificateValidationCallback callback mechanism to provide certificate authentication. You shouldn't have closed the question, this is a valid question that many people may have. This answer was one of the first hits on a google search, thanks to the great SEO of stackoverflow, so it may lead people down the wrong path.
使用 RemoteCertificateValidationCallback 回调。
private readonly bool allowSsl;
// callback used to validate the certificate in an SSL conversation
private static bool ValidateRemoteCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors policyErrors
)
{
if (allowSsl)
{
// allow any certificate...
return true;
}
else
{
return policyErrors == SslPolicyErrors.None;
}
}
以下是 TCPClient :
TcpClient client = new TcpClient(machineName,443);
Console.WriteLine("Client connected.");
// Create an SSL stream, specifying the callback above.
SslStream sslStream = new SslStream(
client.GetStream(),
false,
new RemoteCertificateValidationCallback (ValidateRemoteCertificate),
null
);