Question

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# connect code

public static void connect(string server, Int32 port)
{
  try
  {
    client = new TcpClient(server, port);
    stream = new SslStream(client.GetStream(), false);
    stream.AuthenticateAsClient("MyCNfield");
...
...

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.

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

it gets called:

sslsocket = (SSLSocket) sslserversocket.accept();

and continues on, even though the connection was not fully authenticated.

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?

Was it helpful?

Solution

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.

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

And here is how you would use it with 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
    );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top