title: Java: SSL Clientside Authentication with self-signed certificates
body: <p>I'm trying to secure a connection from a Java Client/Server application that communicates over the Internet. My idea was to use SSL sockets with self-signed certificates and client authentication. I did the following:</p>
  
  <ul>
  <li>Server: Keystore containing new self-signed certificate. <code>keytool -genkey -kelalg RSA ...</code></li>
  <li>Client: Keystore containing new self-signed certificate. <code>keytool -genkey -kelalg RSA ...</code></li>
  <li>Server: Truststore containing exported client certificate (from bullet point above). <code>keytool -export</code> to export client certificate and <code>keytool -import -v -trustcacerts</code> to import it into the server's truststore</li>
  <li>Client: Truststore containing exported server certificate (from first bullet point). <code>keytool -export</code> to export server certificate and <code>keytool -import -v -trustcacerts</code> to import it into the client's truststore</li>
  </ul>
  
  <p>Trust- and keystores are attached correctly to the server/client. I can see the certificates being loaded (SSL debug information). But the whole thing doesn't work. During the SSL handshake, I get the following error (SSL debug information):</p>
  
  <pre><code>main, WRITE: TLSv1 Handshake, length = 897
  main, READ: TLSv1 Handshake, length = 141
  *** Certificate chain
  ***
  main, SEND TLSv1 ALERT:  fatal, description = bad_certificate
  main, WRITE: TLSv1 Alert, length = 2
  main, called closeSocket()
  main, handling exception: javax.net.ssl.SSLHandshakeException: null cert chain
  main, IOException in getSession():  javax.net.ssl.SSLHandshakeException: null cert chain
  javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
      at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificateChain(Unknown Source)
      at sslsocket.Server.getClientDistinguishedName(Server.java:86)
      at sslsocket.Server.main(Server.java:37)
  </code></pre>
  
  <p>When I disable client side authentication, it works flawlessly. </p>
  
  <p>I'd really appreciate some help. Thank you very much!</p>
  
  <p>Below you find the full, but anonymized output from the server:</p>
  
  <pre><code>Initializing SSL
  ***
  found key for : server
  chain [0] = [
  [
    Version: V3
    Subject: CN=xxxxxx Server, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH
    Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
  
    Key:  Sun RSA public key, 1024 bits
    modulus: 9487726xxxxxx15617628447913191
    public exponent: 65537
    Validity: [From: Thu Dec 09 17:04:05 CET 2010,
                 To: Wed Jul 03 18:04:05 CEST 2109]
    Issuer: CN=xxxxxx Server, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH
    SerialNumber: [    4dxxxxxx5]
  
  ]
    Algorithm: [SHA1withRSA]
    Signature:
  0000: 6F 06 1D EA E9 DC 5B 5D   EC EB 33 D4 47 01 94 1A  o.....[]..3.G...
  xxxxxx
  0070: 99 78 C4 31 5F 84 8F 7B   C1 2F 10 A1 9F 50 72 A1  .x.1_..../...Pr.
  
  ]
  ***
  adding as trusted cert:
    Subject: CN=xxxxxx Client, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH
    Issuer:  CN=xxxxxx Client, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH
    Algorithm: RSA; Serial number: 0x4xxxxxx0
    Valid from Thu Dec 09 17:06:56 CET 2010 until Wed Jul 03 18:06:56 CEST 2109
  
  trigger seeding of SecureRandom
  done seeding SecureRandom
  Opening socket
  Waiting for clients...
  Allow unsafe renegotiation: false
  Allow legacy hello messages: true
  Is initial handshake: true
  Is secure renegotiation: false
  matching alias: server
  main, called closeSocket()
  Allow unsafe renegotiation: false
  Allow legacy hello messages: true
  Is initial handshake: true
  Is secure renegotiation: false
  [read] MD5 and SHA1 hashes:  len = 3
  0000: 01 03 01                                           ...
  [read] MD5 and SHA1 hashes:  len = 98
  0000: 00 3C 00 00 00 20 00 00   04 01 00 80 00 00 05 00  .&lt;... ..........
  xxxxxx
  0060: 26 51                                              &amp;Q
  main, READ:  SSL v2, contentType = Handshake, translated length = 75
  *** ClientHello, TLSv1
  RandomCookie:  GMT: 1292088238 bytes = { 223,xxxxxx, 81 }
  Session ID:  {}
  Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
  Compression Methods:  { 0 }
  ***
  %% Created:  [Session-1, SSL_RSA_WITH_RC4_128_MD5]
  *** ServerHello, TLSv1
  RandomCookie:  GMT: 1292088238 bytes = { 222,xxxxxx, 241 }
  Session ID:  {77,xxxxxx, 235}
  Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
  Compression Method: 0
  Extension renegotiation_info, renegotiated_connection: &lt;empty&gt;
  ***
  Cipher suite:  SSL_RSA_WITH_RC4_128_MD5
  *** Certificate chain
  chain [0] = [
  [
    Version: V3
    Subject: CN=xxxxxx Server, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH
    Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
  
    Key:  Sun RSA public key, 1024 bits
    modulus: 948772xxxxxx17628447913191
    public exponent: 65537
    Validity: [From: Thu Dec 09 17:04:05 CET 2010,
                 To: Wed Jul 03 18:04:05 CEST 2109]
    Issuer: CN=xxxxxx Server, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH
    SerialNumber: [    4d00fdf5]
  
  ]
    Algorithm: [SHA1withRSA]
    Signature:
  0000: 6F 06 1D EA E9 DC 5B 5D   EC EB 33 D4 47 01 94 1A  o.....[]..3.G...
  xxxxxx
  0070: 99 78 C4 31 5F 84 8F 7B   C1 2F 10 A1 9F 50 72 A1  .x.1_..../...Pr.
  
  ]
  ***
  *** CertificateRequest
  Cert Types: RSA, DSS
  Cert Authorities:
  &lt;CN=xxxxxx Client, OU=communication, O=xxxxxx, L=Zuerich, ST=ZH, C=CH&gt;
  *** ServerHelloDone
  [write] MD5 and SHA1 hashes:  len = 897
  0000: 02 00 00 4D 03 01 4D 04   B4 AE DE E4 AF 62 FA 48  ...M..M......b.H
  0xxxxxx
  0380: 00                                                 .
  main, WRITE: TLSv1 Handshake, length = 897
  main, READ: TLSv1 Handshake, length = 141
  *** Certificate chain
  ***
  main, SEND TLSv1 ALERT:  fatal, description = bad_certificate
  main, WRITE: TLSv1 Alert, length = 2
  main, called closeSocket()
  main, handling exception: javax.net.ssl.SSLHandshakeException: null cert chain
  main, IOException in getSession():  javax.net.ssl.SSLHandshakeException: null cert chain
  javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
      at com.sun.net.ssl.internal.ssl.SSLSessionImpl.getPeerCertificateChain(Unknown Source)
      at sslsocket.Server.getClientDistinguishedName(Server.java:86)
      at sslsocket.Server.main(Server.java:37)
  </code></pre>