I try to establish a SSL Client authentication with a PKCS#11 Card under Android. I can read the Certificate fine, but sadly i can't extract the private key, so i can't use it to create my KeyStore. Since i don't get any Lib from the vendor and can't use the SUN implementation of PKCS11, since that is not supported by android, i guess i have to override the SSLContext to change the way it handles the signing process, so i can encrypt and decrypt the Handshake via the card?
Also i can't use the full PKCS11 API i got following methods:
CK_RV C_GenerateKeyPair
CK_RV C_GenerateRandom
CK_RV C_Decrypt
CK_RV C_Sign
CK_RV C_Encrypt
The login to the Card is handled beforehand by a different Software, so i already have access.
So basically two questions:
Is there an easy way to handle the authentification without access
to the private key?
What or Where do i have to override to handle the SSL signing via the card?
Is there an easy way to handle the authentification without access to the private key?
There is no way to handle the authentication without access to the private key.
What or Where do i have to override to handle the SSL signing via the card?
Android must provide some form of PKCS#11 handler surely? If not, there is a free one by IAIK you can build yourself, I did it years ago for AIX.
Related
I read a little about Android keystore. What's interesting for me that such keystore allows using cryptographic opeations (like content signing and ciphering) without direct access to private key stored in a keystore. The doc says:
Android Keystore system protects key material from unauthorized use. Firstly, Android Keystore mitigates unauthorized use of key material outside of the Android device by preventing extraction of the key material from application processes and from the Android device as a whole
I would like to have similar solution in backend web application. The most important for me is to have forbidden direct access to private key from java process. In fact my application process doesn't need it because it only needs to sign content when sending back to the user.
I was looking in KeyStore java api but found nothing or missed something important.
Is such approach possible using standard java KeyStore?
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 SSL working between two Android devices running the same app using a self-signed cert and key generated using openssl and stored in keystores.
The problem is that the private keystore must be embedded in the app package somehow, and therefore becomes available to any attacker. I believe this would allow an attacker to snoop on the session and decrypt the data between the two phones.
I'm not using or requiring any of the other features of PKI, I'm just providing two keystores because the SSL connection setup requires them.
Is there a secure SSL cipher that does not need predefined PKI and generates its own keys on the fly at runtime?
I have investigated generating my own keys at runtime - creating the keys is easily done in Java but the KeyStore.setEntry() requires an an X509 certificate chain not just the public key, and Android does not contain the JCE code to generate the X509. I can do that by including the BouncyCastle (Android compatible version is called SpongyCastle) library but that adds quite an overhead to my app package size.
There is no access to a third-party trust server on the internet, the two phones could be on a private WLAN with no internet access.
As a nice-to-have bonus I'd like to be able to trust that the app is communicating with itself, not someone sniffing the protocol from a PC, but I don't think that's going to be possible as the app package contents will always be available.
To ensure you are talking to something/someone you trust, you need a mechanism of authenticating the other party. I'm not aware of a way to achieve this without a piece of data remaining secret:
Asymmetric authentication (i.e. your current implementation) requires the private key data to remain private.
Symmetric authentication requires that the shared secret remains private.
In the future, TrustZone will allow applications to store secret data in the secure element of the handset. Until that time, however, you are always at risk of malware on your devices. Adding a password to your keystore (that the user knows, not the app) might add an additional hurdle to an attacker, however once the phone is infected then the password can be snooped.
To minimise your risk profile you should produce per-device keys, rather than a single cert/key-pair combo that you incorporate into your application. This will, of course, increase the effort required to add new users as some form of registration will be required (e.g. certifying their key). Alternatively you can push the problem out to your users and have them decide who to trust, PGP-style.
I'm writing a server application that identifies it's clients by SSL-Client-Auth. Every Client should create it's own KeyPair and Certificate to connect to this server. Any unknown client (identified by a new public key) will be thread as a new client and registered with this public key. I don't want to sign client certs serverside (since this is would not increase security).
But it seems (after studing hundreds of pages) that I can't create the necessary files (or objects) programatically in plain Java, since the KeyStore would need at least self-signed client-certificates (which I can't create without BouncyCastle lib).
Am i wrong or is there really no way to do this?
And please provide me with a link or code. Java SSL semms to be VERY overcomplicated and has a bad documentation.
As far as I know, there is nothing in the JSSE API (including JSSE and JCE) to issue an X.509 certificate indeed. Dealing with the X.509 structures manually is actually quite complex, and you'd certainly need to read a lot more if you want to replicate what BouncyCastle does, without using BouncyCastle.
BouncyCastle is by far the most convenient way to achieve what you want. You could also use the sun.* packages (since keytool uses them to produce self-signed certificates), but using these packages is usually bad practice, since they're not part of the public JSSE API. They are not documented, rely on a specific implementation of the JSSE, and are subject to change. In contrast, BouncyCastle is meant to be used as a library.
I don't want to sign client certs serverside (since this is would not
increase security).
Since your server will only use the public key (and not the certificate) to perform the authentication (based on whatever mapping between public key and user you choose to implement), issuing the certificate on the server side or the client side doesn't matter in terms of security. The client could self-sign anything it wants, to the server can only rely on the public key anyway, not the rest of the certificate. The reason you'd need to "bundle" the public key into an X.509 certificate is because it's the only kind of client certificate supported (for example, the JSSE doesn't support OpenPGP certificates).
Having a service on your server that receives a public key and sends an X.509 certificate (with any dummy attributes, signed by any private key) might be the easiest option. In addition, if you use a mini CA internal to that server, this would simplify the way you'd need to tweak the trust managers to get the self-signed certificates through. (You'd still need to check the actual public key with your internal mapping, if you want to design such a security scheme.)
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.