C cliente # conectando a um servidor Java sobre SSL
-
23-08-2019 - |
Pergunta
Como um projeto de equipe que eu preciso para se conectar de um cliente C # para um servidor SSL Java 6.5, no entanto, quando eu chegar à linha de stream.AuthenticateAsClient ele trava.
C # código de conexão
public static void connect(string server, Int32 port)
{
try
{
client = new TcpClient(server, port);
stream = new SslStream(client.GetStream(), false);
stream.AuthenticateAsClient("MyCNfield");
...
...
Se eu ligar para algo como https://mail.google.com
e conjunto MyCNfield
para mail.google.com
, ele funciona muito bem, então eu acho que é o lado do Java.
A seção Java Init é:
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");
}
que é chamado:
sslsocket = (SSLSocket) sslserversocket.accept();
e continua, mesmo que a conexão não foi totalmente autenticado.
O que precisa ser alterado para corrigir isso: o JKS tem um MyCNfield
cert que é assinado por um CA que eu criei. Como quer importar a cadeia cert à minha CA privada no meu C #, ou como faço para excange certificados auto-assinados com Java e C #, e apenas jogar fora meus JKS atuais?
Solução
Você precisa usar o mecanismo RemoteCertificateValidationCallback callback para fornecer autenticação de certificado. Você não deve ter fechado a questão, esta é uma pergunta válida que muitas pessoas podem ter. Esta resposta foi uma das primeiras visitas em uma pesquisa no Google, graças à grande SEO de stackoverflow, por isso pode levar as pessoas para o caminho errado.
Use o RemoteCertificateValidationCallback callback.
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;
}
}
E aqui está como você usá-lo com 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
);