I'm currently developing an application for Android thay will allow users to back up their data on a server, which I am also developing in Java. I've pretty much completed the development of the features such as file transfer, registering and logging in and so on (mysql database keeping records of users and passwords) and so on. I've come to a halt in my development when trying to implement security features. I want to use asymmetric cryptography for authentication and symmetric cryptography for encrypting communication between client and server. So here is the deal:
The communication between client and server will be doing using AES. This relies on a Preshared key between both parties. This Preshared key will be generated on the client side each time a session is initiated and will be sent to the server, encrypted using the servers public key. That way, only the server that posses the private key will be able to decrypt the Preshared key and read the communication. Where I am a bit confused is the sharing of the servers public key. Now I know the best way to do this is to use a digital certificate containing the servers public key. I also know this certificate should come from a trusted CA.
My question is, how do I go about getting a digital certificate for my server? Will my android application request for this certificate from the server or the CA? My initial thought is that it has to receive this certificate from a CA, as if it receives it from the server, it may be fraudulent. What is the process and the correct way of going about this? Anywhere I read, it just talks about https connection from client to Web server. I am writing a server in java that will communicate over sockets with my android application. How do I go about creating, receiving and verifying certificates in relation to trusted CAs?
Thanks
Related
I have a Java app (deployed as a JAR file) that allows file sharing through SLLSockets. If all users use the same certificate, file transfers are not secure, since it violates the core concept of asymmetric encrypted communication. Therefore, I understand that each user needs to have its own certificate. This brings up my first question:
How can you generate a certificate programmatically, and where would you store it ? I don't want users to have to generate their own certificate with keytool, then have to tell the app where it is located.
Now, let's say my first question is answered and each user has its own certificate. Prior to opening the SSL connection between two hosts, you need to add each other's certificate to the trustStore. The only way I know to achieve this is by exchanging them through Sockets (note that I am using JGroups to exchange Socket connection info). This brings up my next two questions:
How do you guarantee authentication and integrity when exchanging the certificates ?
How do you programmatically add the received certificate to the trustStore ?
Finally, this whole post brings up my fourth question:
Are the steps described above the correct way to send data securely between two hosts, using SSLSocket asymmetric encrypted communication ?
You don't need client certificates necessarily.
Could you not use username/password authentication?
You can still secure the transfer just by using a server certificate.
Client certs are also kind of a pain, and not entirely secure. They tie you to a machine, and evil processes can read them. Smart cards mitigate this, but aren't free.
I have a server application and a client application created with java that will communicate with the server application. But, since i haven't put emphasis on security in the server side it is really easy to hack the server application if a hacker creates his own client to connect with my server. I want to make sure the client application that is communicating with my server is the authentic client that i created. I upload client to a specific host like www.abcd.com. Now, can i make sure when a client that connects to my server came from that host. I am knowledgeable about signing it with trusted signer but i am looking for a cheap option.
No, this isn't possible. If it were, DRM would work, but everyone knows it's hopelessly broken.
To be truly secure, the client has to be a machine with a "trusted platform module," TPM, that supports something called remote attestation. This allows the server to verify the client is authentic and unaltered. But I've never heard of a real world application of this, and though TPMs are common, I'm not sure if the remote attestation feature is.
I want to make sure the client application that is communicating with my server is the authentic client that i created.
You have two options. One is a password or shared secret, and the other is client certificates. All three are supported in SSL/TLS. Look for TLS-SRP (password based authenticated key exchange), TLS_PSK (preshared key based on a block cipher), and the traditional SSLTLS ciphers with client side certificates.
You can even set up the tunnel with Server Authentication only, and then perform the client authentication at the application level. This is what usually happens in web apps. But this has some non-trivial defects because it does not provide mutual authentication and lacks channel binding. You are better off with TLS-SRP, TLS-PSK, or client certificates.
EDIT: I focused on SSL/TLS because you cited a hostname, but you can do it at other layers, too. For example, you can use shared secrets and certificates at the VPN level. #erickson provides one method using TPMs that could be used at the application level.
Now, can i make sure when a client that connects to my server came from that host.... host like www.abcd.com
This will work if DNS is configured and trustworthy. That is, you will have to extract the host's name, perform a reverse lookup, and then authenticate the IP address. I believe this is called network based authentication.
If an attacker controls DNS or is on the same LAN segment as the server, then I believe network based authentication has some non-trivial security defects.
In any case, HSMs and TPMs are not the answer. To understand why, see Peter Gutmann's Engineering Security, and the section on Unattended Key Storage. From his book:
TPMs don’t work because all that they can do is store the fixed key
that’s required to decrypt the other keys (TPMs are just repurposed
smart cards and don’t have the horsepower to perform anything more
than lightweight crypto themselves so you can’t offload the overall
encryption processing to them), and since for unattended operation
they have to release their secrets without a PIN being entered they’re
just providing plaintext key storage with one level of indirection.
I saw that there were a few other Java and CAC posts on stackoverflow. I am a beginner with all of this stuff and I am still trying to a framework of what to do and where to go in my mind.
I am doing work for a big org that is using CACs with Windows 7 boxes to authenticate users who want to get into their PCs. They stick the CAC in their keyboard and type in a PIN.
My boss would like to alter our Java Webap such that it will not make the users authenticate if they have their CAC in their computer. If not, they will go through the traditional LDAP login.
We are using WebLogic 11g and Java 6.
From Googling around it seems like there are two approaches:
Implement an applet to read the user's CAC and send an SSL certificate to the webapp.
Implement "mutually SSL authentication" in the web server, which will cause the browser to send the SSL certificate on the CAC to the webapp
Do I have a correct appraisal of my options?
Which solution is easier?
Which will be less hassle, more robust in the long run?
I know next to nothing about SSL, which seems to be common in both solutions. I've found a few SSL tutorials that go on at length about abstract concepts. Can anyone recommend a good tutorial for what I want to do?
Thanks much in advance for any information or tips
Steve
Implement an applet to read the user's CAC and send an SSL certificate to the webapp.
Implement "mutually SSL authentication" in the web server, which will cause the browser to send the SSL certificate on the CAC to the webapp
You will want to do #2. You don't really want to have to mess with smart card hardware / software. Let the OS do all that work.
I've done this on IIS, but generically, to implement this, you will need to configure your web server to require client certificates and to trust the DoD CAs. You may need to configure your web server to advertise to clients which CAs it trusts. If the Win7 clients have a client cert that is signed by a CA you trust, the client will attempt to use it. If it's a smartcard certificate, Windows will automatically prompt the user for the pin; you don't have to worry about that. If the user types the correct pin, the cert will be sent to your web server which should then be able to validate the certificate with the CA. If it's a valid certificate, your software can then parse the fields in the certificate and use the values to help authenticate the user (ie whether, despite having a valid certificate, the user is actually allowed to login based on their name / email address/ etc). It's up to you how to handle it from there.
You will have a much easier time figuring this out and finding information if you forget that the users are using a smartcard or a CAC, and just start with the idea that you're going to use client certificates for authentication. Start by creating a self-signed CA test cert. Then create a server cert for your webserver and a client-certificate signed by your test CA. Add the test CA cert as trusted root cert on the client and the server. Then attempt to write a small test app that uses the client cert to authenticate to your webserver. Once you have that working, you can add the DoD CA and try to pull the info out of a CaC certificate.
good luck!
I am writing an application that should ensure secured connection between two parties (call them Client and Server).
Server should restrict which clients can connect using https. For this purpose, server will issue a certain number of certificates that will be checked when a client tries to connect. If the certificate that the client is using is not in trusted list, connection would not be established.
This certificate should be distributed using some kind of usb device. So when Client using my application tries to get something from server using https, application should read that certificate from usb device and USE IT to establish https connection. Private key should be kept secret on the device at all times.
So far I managed to create local keystores on client and server (JKS), add them to each other trusted list and use them to achieve proper connection.
My question is: can client certificates be issued by a server and transported to clients, all together with private key required for https connection? I dont want any data or keystore to be created on the client machine, everything required for establishing https connection should be on that device. Device could have some procedures and api to help this process and ensure secrecy of private key.
Any help will be greatly appreciated :)
can client certificates be issued by a server and transported to
clients, all together with private key required for https connection?
Technically, they can, but you're going to have to authenticate that connection by some other means if you want to make sure that private key only gets to its intended user. As far as your overall scheme is concerned, this doesn't really help. In addition by sending the private key as data to the client, they may be able to extract it one way or another.
If you can physically send a USB device, you can use a hardware cryptographic token that supports PKCS#11. Such tokens tend to have options to store a private key in a way in can't be extracted (it can only be used with the device). They tend to come in to forms: as a smart card (in which case you need a reader) or as a USB token (it looks like a memory stick, but it's not). Depending on the model, the USB token can in fact be a smart card with an embedded reader.
Java supports PKCS#11 keystores, so if this token comes with a PKCS#11 driver/library, it could be used from Java.
The normal client certificate approach to authentication doesn't work well if you don't trust the client to protect their credentials - which seems to be your scenario.
Putting the certificate on the USB device keeps it off the client machine's disk, but doesn't stop the client user from accessing it and distributing it to others. On the other hand, it reduces the risk of 3rd parties stealing the certificate from the client machine "at rest" - but only if the client protects the USB key properly. So you need to be clear about what threats you are trying to defend against, and who you trust.
The only way to make the certificate at all 'private' from the client user is to put it on some kind of tamper-resistant device, and use an approach that does not transmit the certificate to the client machine during authentication.
Compare your approach with those used for internet banking, where the customer is issued a device that can do challenge-response, using their bank card and PIN (two-factor authentication). The card details are protected from casual attack by the card's chip; but the system assumes that the client looks after their card and PIN, and reports thefts promptly (because it's their money at risk!). If the client is not motivated to look after the credentials, then this approach does not make sense.
If you just want to ensure that the client has an unsharable token, you could consider using SecurID devices, or similar, which are an off-the-shelf solution to your problem.
I'm interested if Google App Engine provides a way to use a X.509 Certificate to create a HTTPS connection (the server where I have to connect provides the public certificate - to encrypt data that I send and the private key to decrypt the data received from that server).
According to this post https://groups.google.com/forum/?fromgroups#!topic/google-appengine-python/C9RSDGeIraE it's not possible but 3 years passed since this answer was posted.
SSL client certificates are not currently supported. The feature request is here.
AppEngine has the ability to work with SSL certificate on your custom domain, that means the you can assign a certificate to a domain that is running on the AppEngine.
You cannot AFAIK make a request and provide a custom certificate per request.
Documentation on AppEngine SSL.