Note: this question was sort of asked here, but not answered.
I need to communicate securely between two Tomcat servers running in two different environments. I have control of both servers.
I would like to do this through a simple REST call from Server-B to Server-A.
On the server I am communicating to, Server-A, I can easily set up HTTPS with a self-signed certificate. If I import this certificate into the Java Keystore on Server-B, I can make a trusted HTTPS Rest call from my Java code on Server-B.
Good instructions for doing this can be found here:
https://blog.10pines.com/2017/09/25/how-to-communicate-via-https-between-two-tomcat-servers-using-a-self-signed-certificate/
I would also like to add a confirmation that the Rest call to Server-A is certainly coming from Server-B and the message has integrity.
My plan is to generate a self-signed certificate on Server-B and import this certificate into the Java Keystore on Server-A. Then for any REST call from Server-B I will first generate an SHA-512 hash of the message and sign the hash with the private key associated with the Server-B certificate. When Server-A receives the message, the SHA-512 hash will be recalculated and checked for accuracy of the hash (no message tampering). I will then check the signature of the Hash against the public key of the certificate from Server-B.
For a little bit of extra paranoia I may encrypt the REST message with the public key of the certificate from Server-A; for short messages this should be fine (no need for Symmetric encryption).
Does this seem like a good plan? Does Tomcat have a simpler mechanism for doing this?
The Java Messaging API seems a little "heavy" for this use case.
Related
I have a java client which communicates with python server. Both run within out company intranet. None are exposed to Internet. How I am supposed to ensure that communication happens over SSL?
I have read a lot online and I have come up with following conclusions:
I will generate primary key and certificate to be used by clients and server using java keytool. (creating keystore, private key, certificate and truststore,extracting private key from keystore)
Using private key and certificate inside my python server using SSLSocket class as explained here
Using certificate in truststore inside java client as explained here
I have some doubts:
Are above steps ok?
Above seems to be one way SSL. Should I be doing two way SSL?
Should I be creating shared secret key and communicating using it?
I know this is something related to requirements. But I am in doubt as I am doing SSL first time.
SSL certificates requires validation via (HTTP/HTTPS), I suggest you enable HTTP/HTTPS for the location IP on the router/firewall to allow the validation to go through the internet.
If that is not possible, then you might have to do some local-server SSL validation. By generating a "SELF SIGNED" certificate and registering it manually in both locations.
My plan to make my server harder to emulate goes as follows;
The client creates a random string, String random;
This string is then encrypted and sent to the server. The server then decrypts it and sends it back, if the one sent back is the same as random, then they are connected to the right server (and not a fake one with a diff private key).
How can I make it so that each client has the public key and the server holds the private key? Not a clue.
EDIT -
Because I do not want the clients to have to have extra files for the public key, can I allow them to download the public key on runtime? If I hold it on the server and like serialize it? How?
Is it sensible to use a public and private key encryption between a
client server model?
In a word? No. At least not the way you describe it.
You could get this to work as described, but you will have created security theater rather than effective security.
If you use public/private key pairs that are not bound to certificates, you have a key exchange problem. As noted in the comments, if the app just downloads the key from the server to which it connects, and that key is not in a certificate, there's no way to tell it's authentic to the intended server.
If you use public-/private keys bound to certificates it solves your key exchange problem since you can download the cert from the target server and inspect the Subject Distinguished Name and Issuer Distinguished Name to discover whether the public key you have is authentic. But once you have gone to the trouble of deploying certificates, just use TLS. It's there, it's reliable, and most importantly it's been thoroughly hammered at and known bugs fixed so its as trustworthy as we have available. Your home-grown protocol is not.
What you are describing can be achieved with other standard protocols such as Challenge-Handshake Authentication Protocol (CHAP). If TLS doesn't meet your requirement, use a standard protocol. Even an old deprecated one would be better than writing your own because, like TLS, it's been hammered on extensively in the real world.
Assuming that you did implement the protocol proposed, then what? Authenticate then communicate in plaintext? Why expend more effort than implementing TLS, to deploy something far less secure than TLS, that doesn't even provide privacy or integrity of transmitted data?
Because I do not want the clients to have to have extra files for the
public key, can I allow them to download the public key on runtime? If
I hold it on the server and like serialize it? How?
If you use CA signed certificates (from an internal or external CA) you can dynamically fetch the certificates from the target server. The only thing you need to store is the signer chain in your Trust Store and the acceptable values for Subject Distinguished Name and Issuer Distinguished Name. The remote cert won't validate if the signer certs are not in the Trust Store so a man in the middle can't just swap out any cert with the right distinguished names. Once it validates to your Trust Store, your inspection of the distinguished names determines if you have the right cert and server.
Finally, the question doesn't mention revocation at all. If you use CA-signed certs from a commercial CA or from an internal CA that is at least somewhat robust, you can check at run time against a Certificate Revocation List or use Online Certificate Status Protocol. Again, these are built into the TLS protocol as implemented in any JSSE standard provider.
I am working on a chat application, made in Java for android. I have a server created in python, using twisted, and of course, in my android app I have the client implemented.
It's working very well, but I want to make it secure. I was looking at RSA encryption and found this link: http://javadigest.wordpress.com/2012/08/26/rsa-encryption-example/
The problem is that, I can make a pair of keys, a private key that will be on the server to decrypt the messages and the public key will hard-coded (or somewhere online), in the android application. The problem would be, when the server sends the message back to the client, how will he be able to get it ? That one needs to be send encrypted as well, otherwise, there's no point in doing it. I was thinking about creating a pair of keys for each client, but ... I think it's not the best approach.
All suggestions are welcome
The solution to this is usually to create a form of Public Key Infrastructure (PKI), where the public keys of the clients can be verified when needed. You can do this by putting them into a certificate and sign it by some kind of certificate authority (CA) that you control. That way you don't need to store all the certificates, and you can also revoke certificates of clients that have their key compromised. This is what is normally used by (browser) TLS, especially if client authentication is deployed.
Key management however is a large topic that cannot be handled within one answer.
I'm trying to improve some code that enables logging in to our application using digital certificates, probably certificates stored on PKCS11 tokens.
It's a Java client server application, with the server on JBoss [Wildfly], and a rich Java thick client. We also have a GWT/Javascript based web client, but this doesn't yet support certificate auth.
The current implementation uses 2-way SSL authentication if certificate authentication is configured, i.e. the server will require a client certificate when the connection is opened. This causes some problems, and in trying to find ways to address them I've been searching madly to see if there is a standard, 'Right Way To Do PKI Auth To A JBoss Application'.
However just about everything I have found on the subject seems also to revolve around using two-way SSL, which kind of implies that is the Right Way to Do It.
It seems undesirable to me, in that the network transport is quite a low-level concern, heavily separated from the application logic and stuff like authentication and user management.
In order to prove the client is a valid user of the system (as opposed to merely someone with credentials endorsed by a CA in the server trust store), the server application logic has to rummage around looking to find the certificate that was used on the incoming connection in order to scrape the Common Name off it. I've discovered that javax.servlet.request.X509Certificate is a standard-ish parameter one can query on the servlet, so it ought at least to be possible.
The other architectural problem this causes is that our app requires reauthentication for the lifetime of certain sensitive operations. If one is using the SSL connection to prove the user has the private key, then logically that would require opening a whole separate connection.
Logically, authenticating with a certificate would seem to require
The server generating a nonce
The client encrypting the nonce using the client's private key
The client sending that encrypted value to the server with the accompanying public certificate [or certificate chain].
Now, that is exactly what happens during an SSL handshake, but obviously a whole load of other baggage comes with it that is irrelevant to the application-level concern of authenticating the user.
I thought about implementing the steps directly myself, but this would seem to violate the first rule of crypto (Don't implement your own crypto).
If the server generates random nonces then that introduces a level of chattiness and statefulness to the process, which is doable but a pain when you are striving for a stateless and clusterable server.
Time-based One-Time Password implementations circumvent this, and seem to be a standardized mechanism for 2-factor authentication that is getting support from Google+ and the like.
However I can't find anything in the way of out-of-the-box libraries that will let me build an implementation using certificates directly from an imposed PKI.
I'm new to SSL connections so here goes my question.
I have a desktop Java program in a JAR file. This JAR sends sensitive information over the internet to a remote Tomcat server. Of course I need to encrypt the data.
If I purchase an SSL cerfiticate say from Verisign, will the data sent over SSL be automatically encrypted?
I mean in my JAR, will I still need to do extra work like use Java encryption extensions API to manually encrypt my data over the SSL connection?
Thank you.
I mean in my JAR, will I still need to do extra work like use Java encryption extensions API to manually encrypt my data over the SSL connection?
Encryption will be done for you (with the Java Secure Socket Extension). Just establish your connection using https://. Maybe have a look at HTTP Client for a higher level API.
By the way, the certificate goes on the server side (unless you want to do client-authentication too in which case, well, you'll need a client certificate too).
And yes, you could use a self-signed certificate but one of the benefits of using a certificate signed by a well known Certificate Authority (CA) like Verisign, Thawte, etc is that you won't have to add it to the trust store of the client VM (unless you disable the verification mechanism).
Follow the SSL Configuration HOW-TO on how to setup https.
If your goal is just to get the encryptian, you don't need to buy a certificate. You can make your own. Buying a certificate just creates the verification chain back to verisign (or whomever) to give users a warm fuzzy that you're really who you say you are.
SSLSocket should handle most of the work for you.
All data sent over SSL is by definition encrypted, you do not need to worry about encryption at all. Also, you do not need to by a certificate to achieve that: you can issue one on your own.
If you'll set up the SSL on Tomcat and send your data over HTTPS then the encryption will be done for you. But you don't actually need to purchase a certificate if you only need encryption for your data channel, you could generate a self-signed certificate. Have a look at this page http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html on how to configure SSL for Tomcat. But note that HTTPS can be configured not to use encryption at all (at least on Apache httpd).
To answer your question, SSL implementations automatically encrypt the data. You don't need to worry about using additional encryption routines.
It might be easiest to purchase an SSL certificate because SSL implementations provide easy certification authentication using common root certificates and provide a verification service. However, you could save some money by using a self-signed certificate.
Even with a self-signed certificate, it's important to validate the signature on the server certificate from the desktop application when you connect to the server. This will prevent man in the middle attacks.
You won't have to add your self signed certificate to the store because you should be able to disable the automatic verification mechanism and use your own.