• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

TLS certificate validation

 
Ranch Hand
Posts: 218
5
MS IE Notepad Suse
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ok, so as I'm currently on to my road to implement Monopoly - I already thought about its network-layer and came up with something unusual - but straight forward: TLS and it's feature for client authentication. So, instead of username and password a user generates an RSA keypair - generates an CSR - receives an client-certificate and uses this as auth-token (all done in the background with a ton of bouncycastle-magic). As Monopoly isn't the typical game to cheat - any network-connection is - at least in terms of sniffing and modifying it.

What? Yea - imagine this: someone wants to somehow take advantage by manipulation of the data exchanged between client an server (would make any sense as I plan to check every action happens on server-side). But if someone really tries to find some bug - I'm sure one will find one. So I looked for an easy way to block of such "users" - TLS client certificate and a list wich prevents those to get a new certificate.

To make this happen - a correct validation is needed - and here it starts where Java itself has at least something built-in - but BC lacks all of it and one has to do anything itself. There's just implementations to check if a presented server-certificate is signed by a trusted root-certificate - but there's no validation (neither CRL nor OCSP) - and if you set up a server with client auth - well, there's simply no checks at all - not even if the certificate replied by the client matches with any root-certificate requested from the server.

So I dived deep into all those magic crypto stuff - and tried to build some validation code - but as nobody ever did this on the net - there're no resources google could deliver. Here's a small stub:

The last sysout for the BuilderResult shows somewhere the let's encrypt root-cert gets correctly identified - but the resulting CertPath is empty:

So, if you try to run the validation part - it fails cause the CertPath is empty and therefore no validation can happen. And if this doesn't work on the client side for server certs - how ever should it work on the server side for client-certs?
Using BC and write all validators myself may be an option (as BC is really not useable at all when not using the BC-provider but the lightweight-api) - but this could be as error-prone as the few lines I was able to put together with standard SE api.

Is it really that un-common to use Java for such things? If so - it has to be done in other languages as I guess client-auth is used in many applications. Can't imagine to be to that hard to port it to Java. Or is Java itself just not capable of such tasks and one has to write its own stub with libs like BC (let alone implement all this crypto-stuff by hand - wich WILL lead to security holes)?
 
Matt Wong
Ranch Hand
Posts: 218
5
MS IE Notepad Suse
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ok, problem solved - it all starts way earlier than I thought - right at init of SSLContext:



So the main difference is the initialization of the TrustManagerFactory: instead of using init(KeyStore) one uses init(ManagerFactoryParameters) to simply wrap a PKIXBuilderParameters, wich, as a subclass of PKIXParameters, one can add a PKIXCertPathChecker.
Also: the setRevocationEnabled(boolean) method is only for provider-internal checker - and is ommited when a custom checker is set/added, and, as noted in the docs, should be set to false when using a custom checker to prevent issues with provider-internal checker.
To disable revocation checking set the flag to false and don't add a custom checker. To use default OCSP one doesn't need to do at all as it's enabled by default in JSSE. To use CRL use code above.

Strangly: as I tested this with my server I could verify with wireshark that java was loading the CRL - but somehow couldn't verify it. When I tested with google, it worked fine. So either something's wrong with Let's Encrypt - or my server. Will test it with custom CA.
 
Matt Wong
Ranch Hand
Posts: 218
5
MS IE Notepad Suse
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ok, so it took me a week to get a full CA up with some bouncycastle-magic - but it works now.

On top of my CA there's my root.key, a self-signed root.crt, and a root.crl to revoke the following intermediate certs.
On 2nd level are the intermediate certs with intermediate keys and crls, namely server-intermediate.key/.crt/.crl and client-intermediate.key/.crt/.crl.
On the lowest level are on one side the server cert with its key - and on the other side are the client certs with thier keys.

So now what happens on connection? Apart from some client-cert-stuff not much else than normal server-side-only TLS connections. The special key here is that the server is set to require the client to awnser with a certificate signed by the root-ca. As certificates are in a chain, the server only sends the root-ca wich it trusts - in my case only my own root. Then the client itself sends either a certificate directly signed by the root-cert - or a chain of certs wich ends up on the root-ca.
Both sides are setup to validate with CRL. So when a client connects and receives server cert chain (root is loaded as a trusted ca-cert on client) it follows the chain from top down - so firstly the server-intermediate cert is checked agains root-crl, if this passes then the server cert is checked agains server-intermediate-crl. Then the client receives the client-cert-requirement from server and responds with a chain itself. The server then does the same - and only if all certs and crls are valid by the root-cert - the connection is established.
So, to exclude someone to connect - I can decide to either no issue a client-cert in the first place (wich will be an automated process during registering) - or, if a certificate is already issued - I add its serial-number to the client-intermediate.crl - and the connection is terminated during handshake.

In the end - here's the code - if someone wants to know how to setup a CA with BC in Java - just let me know.





Oh, and I also discovered why one can't validate let's encrypt certificates with CRL - cause client-certs are not issued with CRL but only OCSP, that's why CRL check fails.
 
Saloon Keeper
Posts: 15524
364
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This isn't done regularly because there's no need. You just pick a secure transport protocol to communicate between the client and the server. You're reinventing the wheel.

As for blocking clients, what are you gonna block them by? Do they have accounts?

Lastly, if you think a dedicated cheater will find a bug in your game, they won't find a bug in your hand-rolled security? Just focus on making it impossible to cheat on the first place. Let the server roll the dice, and perform all the game logic. All that the client has to do is decide whether they want to buy the current property, or perform other actions like buying hotels for properties they already own, or initiating trade. All of these can be verified by the server.

If you just want to get experience with TLS, it's better to use it in a project where you design your own transport protocol, not at the application layer.
 
Saloon Keeper
Posts: 27807
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Is this a webapp or a stand-alone server? If it's a webapp, then no application code is required to implement SSL/TLS. Everything is already there, whether you're dealing with the more common server-side certs or authenticating with a client-side cert. It's all a matter of setting the webapp server (e.g., Tomcat) security options as desired.

In fact, the stock https transport mechanisms for Java incoporate all that, including negotiation between client and server to find a mutually-agreeable encryption scheme.

Only if you are doing raw socket communications do you need to get personally involved at that level, and I suspect that in many cases, not even then.

Although considering firewall limitations on a lot of networks, you're best not using custom protocols and ports anyway.
reply
    Bookmark Topic Watch Topic
  • New Topic