I'm attempting to enable SSL communication from a web service client (Axis2) using the certificate on the user's CAC card. Works like a charm....UNTIL the web server is CAC enabled. At that point the SSL connection is rejected with the error message that the other certificates in the chain were not included.
I have ensured that the provider is available, either by adding it to the security.properties file or creating it programatically.
My current approach is to simply set the system properties:
System.setProperty("javax.net.ssl.keyStore", "NONE");
System.setProperty("javax.net.ssl.keyStoreType", "PKCS11");
I understand from this question/answer that this approach only sends the "end entity" certificate. Apparently I need to implement my own X509KeyManager. This is new ground for me, can anyone suggest a good reference or provide samples of how to do so?
Appreciate the assistance.
The best key manager implementation depends on the issuer of the certificates you expect to be using.
If the certificate on the user's CAC will always be issued by a specific CA, simply store that issuer's certificate and any intermediate certificates further up the chain in a PKCS #7 file. In the getCertificateChain() method, this collection can be appended blindly to the user's certificate and returned.
If things aren't quite that simple, but a complete list of possible issuers can be enumerated, obtain all of their certificates, and their issuer's certificates, and so on, up to the root certificates.
Add all of the root certificates to a key store as trusted entries. Bundle the intermediate certificates in a PKCS-#7–format file.
Implement X509KeyManager (or extend X509ExtendedKeyManager if you're working with SSLEngine). Specifically, in the getCertificateChain() method, you'll use a CertPathBuilder to create a valid chain from the user's certificate to a trusted root. The target is the certificate that you load from the user's CAC with the alias parameter. The trusted roots are the certificates in trust store that you created; the intermediate certificates can be loaded from the PKCS #7 file and added to the builder parameters. Once the chain is built, get the certificate path and convert it to an array. This is the result of the getCertificateChain() method.
If you can't predict who will be issuing the user's certificate, you might be able to obtain the intermediate certificates at runtime from an LDAP directory or other repository. That's a whole new level of difficulty.
Related
When using Azure API Management Gateway its possible to implement client certification authentication to secure access to APIs. You can validate incoming request certs using policy expressions such as thumb checks etc.
When using client cert authentication method, what's the recommended process for certificate generation/management?
Cert responsibility?
Should I/gateway owner be generating the .pfx file (either self signed or by trusted CA), importing it to the gateway service and providing external clients with the .cer to install locally and auth with?
Should I/gateway owner be generating the .pfx file (either self signed or by trusted CA), importing the .pfx to the API Management gateway service (normally I'd imagine importing the .cer on a server/gateway but doesn't seem possible in Azure) and providing external clients with the .pfx to install locally and auth with?
Should the external client be responsible for generating their public/private key pair in their Org, signing it with a CA, installing it locally and providing me/gateway owner with a .cer file to import to the gateway (as above, not sure its possible to import .cer, I read only .pfx accepted in import process) or provide thumb for me to store/validate in policy?
Does anyone have any advice whether to issue clients requiring access to the same API the same (shared) cert or generate a new cert per client? They would all be using the cert to access the same API (+ additional auth methods, cert is just an extra step).
I've ready online tutorials describing all above bullets and where client-specific or single cert-per-API have been implemented so a little confused which is recommended approach?
The easiest way would be to have a single issuing CA certificate, you'd only need to upload its public key to APIM as that is all that's needed for APIM to validate incoming certificate. Then you'll be responsible to generate client certificates and distribute them to clients. In APIM you can setup a policy that would require certificate, check its issuer and validate, that should be enough to ensure that certificate is valid and issued by you.
Relying on self-signed certificates will be a hassle as you'd have to somehow let APIM know of each new certificate, having common issuing CA frees you of that worry.
Same goes for allowing remote clients to generate certificate - they would have to let you know of certificate and you'd need to list it in APIM one way or another.
You're free to decide how exactly to distribute certificates, a few things to consider:
Likely certificate will be your main way to tell clients apart. If that is important you may want to have different clients have different certificates.
If you want to deny access to a particular client you'll "revoke" that certificate, you need to make sure that other legitimate clients won't be affected.
I have done extensive research on this topic and my knowledge is still pretty ambiguous. I'm looking to get a basic DV for a simple site, but I see every SSL online has three levels, Root->Intermidiate (that acts as a proxy for the Root ) and a regular certificate i guess?
Here is Googles:
I see their Root is issued from GeoTrust but their intermediate is one of their own, so do you purchase the root separately or does it come with the purchase of an SSL? and Does the root create the intermediate thus signing the purchased SSL or? Some clarity would be nice..
It is very simple, when you order SSL certificate from vendor or Certificate Authority. CA will provide a zip file that contains root, intermediate and primary certificate. The reason behind to install root certificate is to avoid the browser warnings generally occurred while visiting website. You don’t need to order above mentioned certificate individually as it comes altogether.
The reason behind intermediate certificate is to create a chain of trust between browser of visitors and the web server. All three certificates should be copy and paste in a simple text file (check below example) and to be placed on server that will be used while installing the SSL later on. Hope this will clear your doubts.
Example:
—–BEGIN CERTIFICATE—–
(Primary certificate: yourdomain.crt)
—–END CERTIFICATE—–
—–BEGIN CERTIFICATE—–
(Intermediate certificate: ca.crt)
—–END CERTIFICATE—–
—–BEGIN CERTIFICATE—–
(Root certificate: root.crt)
—–END CERTIFICATE—–
A certificate serves two purposes:
Encrypt connection
Prove that the site owner is who claims to be
If we were just going to encrypt data any certificate would do (even a self-signed) but that's not enough in real life because we also need to ensure that we aren't connecting to a fake site (there's no point in keeping information secure and then deliver it to the bad guys) and that's where the trust chain concept comes in. In your example:
You have a certificate for www.google.com, but you can't really say whether it's genuine. After all, anyone can generate a cert for www.google.com.
Someone who claims to be Google guarantees that the above certificate is genuine, but you can't really say whether they are the real Google.
Someone who claims to be GeoTrust guarantees that the above certificate has been really issued to the real Google. But this time you trust GeoTrust because it is configured as root authority in your browser. Either it comes with the browser (and you trust your browser) or you installed the CA yourself (that's typical in Spain when you need to access government sites).
It's also worth noting that we could have an arbitrary number of levels, not necessarily three.
To sum up:
You don't own any certificate in the trust chain except the last one you've paid for.
The company you get the cert from should have already done all the paperwork to be part of the bundled CAs in major browsers (after all, they charge for the service). Otherwise, your site visitors will get an untrusted certificate error message because they won't have the root CA.
Optionally, you might need to download and install some additional intermediate certificates (but you still don't own them).
I am trying to securing the service calls that are made from my node to other services secure. All the other services have enabled https. I tried the following methods
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
which as per my understanding ignores all error so removed from the code becuase of certificates
I am using request module. where we can configure
key - provided my private key file,
cert - provided my certificate file
ca - certificate authorty chain
then it was throwing UNABLE_TO_VERIFY_LEAF_SIGNATURE
I found out that node doesn't read ca from the system.
it has its own ca chain So I included node-ssl-root-cas
which fetched latest cas from internet.
Then using ssl-analyser, i was able to find my domain doesn't have intermediate ca certificate
I downloaded that from our ca and made a ca chain and attached it to ssl-root-cas
Then i was able to make requests successfully
But Even if I remove key and cert from my request i am able to make request and get result.
How can I check my request and response are actually encrypted?
Or node just ignoring errors,
FYI, Node will use the certificate auhtorities installed on the system if you don't provide your own with the "ca" property. When you do provide your own, the system ones are ignored. This is by design, as providing your own CA likely means that you want to only trust certificates signed by your own CA. If you aren't using your own CA, you can skip setting the "ca" property. If you are, then I'm not sure why you would need to provide the full list of commonly trusted CAs as well. That seems like a pretty odd use case.
You can use the https module to make requests without providing your own key and cert. This is expected and documented behaviour. For technical reasons, when making any https requests, more specifically opening any TLS socket, the client also needs to have a private key and certificate. In the default case, the server doesn't verify the client in any way, so browsers use what's commonly referred to as a "snakeoil" certificate - a bundled self signed certificate.
The use case for providing your own key and cert when performing https requests, is when the server has client certificate checks enabled. For example, when connecting to Apple's servers for delivering push messages to iOS, you have a client certificate issued by Apple that Apple's servers uses to verify that you have access to send push messages (the certificate was issued by Apple) and which app you are sending to (the fingerprint/checksum of the certificate).
Unless the https services you talk to require specific client certificates, you're better off not setting "key" and "cert" - there's no real reason to do that.
So, in summary, you can probably skip setting all three of key, cert and ca, as the real problem seemed to be your mis-configured server (it didn't serve the CA chain).
I've read about SSL protocol and now, I know how it encrypts data. But there is something I couldn't understand. With SSL , you're sure you're sending data to and getting data from correct server. But how?
I mean if I create a fake certificate and send it for requests of special website, how do browsers ( or other programs) detect the fake certificate?
Edit: I didn't mean to create a self-signed certificate. I meant how can someone validate my certificate if I create a certificate that its issuer and subject ,etc are something to real certificate! (the only things that are not real is Public key & signature)
TL;DR summary:
Validity of a server certificate is established by:
Host name verification
Verifying the signatures of the entire certificate chain
Performing additional checks on meta data for each certificate
Checking the revocation status of each of the certificates involved
Checking whether the self-signed root certificate of the chain is among the certificates that one trusts by default
Explanation
Let's assume you want to connect to https://mail.google.com (you can try this out in your browser!).
The (real) server will respond with a certificate that is issued to mail.google.com, i.e. in the 'Subject' field of the certificate you will find the Common Name (CN) 'mail.google.com' - cf. RFC 5280 for details on the fields of certificates. The fact that the subject is linked to the site URL is very important for the security of the whole model, and it is actively checked by your TLS implementation ("host name verification"), because otherwise there would be room for Man-In-The-Middle attacks. I.e. somebody could acquire an otherwise valid certificate and impersonate mail.google.com without you taking any notice of it.
In addition to the host name verification, your TLS implementation will also check the "validity" of the certificate. The whole procedure is rather complex and does include checking the trustworthiness of the certificate, but additionally a lot of other things will be checked, more on that in a minute.
If you view Google Mail's certificate in your browser, you will notice that there are actually three certificates shown:
mail.google.com
Thawte SGC CA
Class 3 Public Primary Certification Authority (VeriSign)
The model is that there are a few (well, unfortunately not so few anymore) trusted root certificate authorities ("root CAs") that either you could choose on your own or (more likely) that come preconfigued with your software (e.g. browser) that are blindly trusted. These trusted authorities form the anchors of the entire trust model of "PKI" (Public Key Infrastructure). The basic idea is that the trusted entities may issue certificates to other authorities and grant them permission to again issue certificates (these authorities are called intermediate certificate authorities). The intermediate CAs may again recursively apply this procedure up to a certain point, the number of intermediate CAs between an actual end entity certificate and a root CA certificate is generally limited.
At one point, an intermediate CA will issue certificates to an "end entity" ("mail.google.com" in our example). Now the process of issuing a certificate actually means that the party requesting a certificate will create a public/private key pair first, and use them to authenticate a certificate request that is sent to the certificate authority. The issuing authority creates a certificate for the subordinate entity (either intermediate CA or end entity) by "signing" that certificate using its own private key using an asymmetric algorithm such as RSA and by additionally including the public key of the requesting party within the newly generated certificate. The root CA possesses a so called self-signed certificate, i.e. the root CA is the only authority that may sign their own certificate and include their own public key. The private key remains hidden at all times, of course.
The recursive nature of the certificate issuing process implies that for each end entity certificate there is a unique way of establishing a "chain" of certificates that leads up to a root certificate authority. Now when you are presented with an end entity certificate while trying to connect to a TLS-secured site, the following procedure will be applied recursively until you end up with a root CA certificate:
Find the certificate of the authority that issued the certificate to be validated (see RFC 5280 for details). If none is found: exit with error.
Take the public key of the issuing certificate and verify the signature of the to-be-validated certificate using this public key.
Check a lot of additional things such as whether the certificate has neither expired nor is it not valid yet, "policy constraints", "key usages", "extended key usages"... (again, the gory details are in the RFC).
Certificate revocation status (more on that later)
If all checks were positive, you will ultimately end up with a certificate being self-signed, i.e. where the subject is also the issuer (such as the VeriSign certificate in our example). Now the last thing you have to verify is whether this certificate is among those that you blindly trust: if it is, all is well and the connection will succeed, if it is not, the connection attempt will be rejected.
As if this were not complicated enough already, the checks described so far do not handle cases where once valid certificates suddenly become rogue, examples being cases where a certificate is stolen or private keys are compromised (think of Comodo and DigiNotar). In these cases, the normal procedure is to "revoke" those certificates gone bad, that is you want to mark them as being invalid starting from a distinct point in time (they will expire at some point anyway, but for the remainder of that period they shall already be marked as invalid). For these cases, CAs have the possibility to issue CRLs (a catalog of certificates declared as invalid) or OCSP responses (information for one or in rare cases a set of certificates) that provides clients with information whether a given certificate has been marked as invalid or not. The revocation status needs to be checked for all certificates in a chain, should one of them be marked as invalid then the end entity certificate cannot be trusted and the connection must be rejected as well.
SSL certificates are signed by a certificate authority (CA), which is someone the user already trusts (or more likely, the people who designed their operating system trusts).
The CA digitally signs the certificate using public key encryption. The basic explanation is that the CA has a "private key", and a "public key" that everyone knows. Via some math I don't understand, the CA can create a signature using its private key which can easily be verified with its public key (but the public key can't be used to create a new signature).
When you get an SSL certificate from a server, you get the server's public key, and a signature from a CA saying that it's valid (along with some other info). If you know and trust that CA, you can check the signature and determine if it's valid. You can also use a certificate revocation list to make sure it wasn't revoked.
So basically, you can recognize a bad SSL certificate because it isn't signed by a certificate authority that you trust.
Any fake certificate you create will be a self-signed certificate.
The browser will display big scary warnings when connecting to a site with a self-signed certificate which the user will promptly ignore.
In order to avoid warnings, you need a certificate signed by a certificate authority that the browser trusts, such as VeriSign.
These companies will hopefully make sure that you actually own the domain for the certificate they're signing.
Re: Edit: You can only create a non-self-signed certificate if you get it signed from a trusted CA.
They will refuse to sign a certificate for a different subject.
Process from my understanding:
server sends servers public key
server sends certificate (all information encrypted by trusted CA with their private key)
Your PC decrypts certificate with public key (built into OS from trusted CA)
Your PC hashes (with sha1 and sha256) the servers public key
Your PC compares the hashes of servers public key with certificate stored hash, if not same browser will block site
Your PC compares allowed domains from certificate and the domain, if not allowed, if not same browser will block site
Your PC compares valid date from certificate and your date, if not valid browser will block site.
To fake this you would either need to:
obtain a CA private key (extremely hard to get),
be a CA,
be part of the 5 eyes (Government intelligence agency alliance) and ask a CA for their private key
So if you see a padlock in the address bar you are almost always safe.
Certificates work because they follow a chain of trust. Certificates have a chain of one or more issuers that are trusted; this chain is the backbone of why it works at all. Browsers and nearly all SSL certificate libraries do this chain check, or at least provide the option to.
Self-signed certificates (or those issued by chains that end in a self-signed certificate) would fail this check.
I have a question regarding validation of digital signatures using a self-signed certificate:
The following tutorial works for me:
http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html
However, when a X.509 certificate is self-signed, how can a receiver trust certificate data attached to an XML message? Any one can generate a self-signed cert and claim to be the same sender. The validation in the above tutorial always returns true. Sender’s cert must be loaded to receiver’s truststore, so receiver can use whatever in the truststore to validate signed doc. I cannot find any reference for such a scenario.
Your understanding is correct - with self-signed certificates anyone can create a certificate and signature validation will be ok. The reason is that signature validation performs first of all cryptographic operation, which is completed successfully. The second step is to validate the certificate itself AND also it's origins. When the CA-signed certificate is used, the certificate is validated using CA certificate(s) up to trusted CA (or known root CA). With self-signed certificate validation is not possible. In the above tutorial the procedure of certificate validation was skipped for simplicity as it's quite complex and beyond the scope of tutorial.
The problem you're describing is usually addressed by Public Key Infrastructures (PKI).
This is the traditional model for verifying certificates for HTTPS sites, for example. It starts with a set of trusted Certification Authorities (CAs) from which you import the CA certificates as "trusted". The entity certificates that you get are then verified against this set of trusted anchors by building a certification path between the certificate to verify and a CA certificate you know (linking the certificate to a trusted issuer, perhaps via intermediate CA certificates).
The various rules to do this are described in RFC 5280. The PKI system doesn't apply only to web servers, but to any entity (there are additional rules for web servers to verify that they're the one you want to talk to, on top of having a valid certificate).
(In particular because the choice of which CA certificates to trust is often done on behalf of the user, at least by default, by the OS or browser vendor, this model isn't perfect, but it's the most common in use.)
Alternatively, there's nothing wrong with establishing a list of self-signed certificates you would trust in advance.
Either way, you need to pre-set what you trust by mechanisms out of bands (e.g. by meeting someone you trust and using the certificate they give you in person).
This PKI model goes hand-in-hand with the X.509 format thanks to the notion of Issuer DN and Subject DN. You could have other models, for example relying on PGP certificates, where you would build a web of trust; you would still need an initial set of trusted anchors.
For XML-DSig in Java, you should implement a X509KeySelector that only returns a key that you trust. In a simple scenario, where you have a pre-defined set of self-signed certificates you trust, you can iterate over a keystore containing those trusted certificates. Otherwise, use the Java PKI Programmer Guide (as linked from the tutorial you've used).