I am trying to find a solution for a problem that seems too generic not to be solved by someone more capable than I am. Yet I struggle to find it.
So. I want to create a "chain of trust", which is more or less similar to the X.509 certificate chain but is built entirely on JWT (I know about the x5c, but that's against the rules in this game). The premise of the challenge is: given a chain of "authorities" a1 to a(N), where each authority trusts the next authority in the chain — i.e. a1 trusts a2, a2 trusts a3 ... a(N-1) trusts a(N), as a "consumer" that trusts authority a1, I should be able to establish trust in authority a(N).
X.509 has a concept of a "certificate", which confirms the authenticity of one authority (or, specifically, its private key) using the trust you might have in another authority. That allows you to chain the authorities together and follow the chain from the first one (which you trust) to the last one.
A JWT, however, is typically used in a "single authority" scenario, where the consumer knows its JWK and from that establishes trust in its output.
To create a chain we'd need an a(N)'s JWK to contain a public key in the form of JWT signed by a(N-1). So my question is:
Is there a standard that describes this or should I invent my own wheel?
Related
I'm new to asymmetric cryptography (public-private keys) and has a fundamental confusion:
I understand that once a person has broadcast his public key to the network, the following communications become safe using the public-private key paradigm.
However, how do you make sure the public key received is valid at the first place? For example, if Bob wants to establish a secure communication with Alice, with Eve eavesdropping in the middle, how do you make sure that Bob receives the real public key from Alice, instead of the fake public key forged by Eve?
Thanks!
Cheers,
M.
Public Key Infrastructure (PKI).
You have a third-party trusted authority that issues certificates to different people/companies. You don't only trust the people, but also the Certification Authority (CA).
The Certification Authority must ensure and validate that the people/company that is buying a certificate is in fact who it claims to be.
The verification is done by signing a the certificate using a private key (from this CA), then both peers in the connection will check that the certificate was signed by a trusted CA and validate the connection.
In you example, Bob will sign the certificate in a CA that Alice trusts.
If Eve tries to sign a certificate in this CA, claiming to be Bob, this will be rejected, because the CA will validate its authenticity. Try to buy a client certificate here to see: https://www.verisign.com/
Another example is your browser, it only shows that a trusted connection is done with StackOverflow, because it trust on Let´s Encrypt, which issued the StackOverflow.com certificate.
Every browser has some default CAs that are already trusted.
The public key would be signed by another authority. Check if this authority is genuine and renowned. If it is unknown then try to further check its signing authority and see if its a renowned one.
The concept of trusting this public key is based on basing your inherent trust in authority which signs this certificate. Signatures are mathematically verifiable so they cannot be forged unless there's an issue with implementation or mathematical algorithm itself.
So in a nutshell, try to see the signing authority of the certificate and if it is something you trust.
The certificate authorities(CA) or web of trust(WOT) model shall help you in ensuring the authenticity of public key.
The Certificate authority is a centralized entity that issues digital certificate that certifies the ownership of a public key by the named subject of the certificate. It acts as a trusted 3rd party, trusted both by the subject (owner) of the certificate and by the party relying upon the certificate.
The web of trust is a decentralized trust model to establish the authenticity of the binding between a public key and its owner . In a Web of Trust, everybody is a kind of CA. Every user signs certificates for whoever he wants. It relies on value of trust or trust relationships between regular users.
Web Of Trust model operates such that if we verify that A's certificate is actually for A and we verify that B's certificate is from B, A and B can both verify that C is in fact C. Now, when C want's to interact with us, he can provide his certificate which is trusted by both A and B. Since we trust A and B , we can conclude that it is highly probable that C is actually C. This works since we expect that A and B weren't both working together and C had to have convinced them both that he was ok.
Newbie question: some vendors propose solution like generating dynamic certificates to allow user who haven't classic certificate to sign documents. But why not just generate private/public keys alone instead of bothering with certificate format ?
The purpose of the (public key) certificate is to bind the public key to the identity of its subject (i.e. the owner/entity associated with the key pair), and possibly various attributes telling you what the certificate may be used for. (You may be interested in this question on Security.SE.)
You always sign with the private key (not the public key or the certificate), but the public key or certificate are often attached with the signed document.
If you have an explicit list of public keys you know and can link independently to a user, you don't need a certificate.
The certificate allows third parties (who have signed the certificate) to assert the binding between the identifier and the public key. Even if you don't know that identity in advance, you can link the signature to the signer's identity as long as you trust the entity that signed the certificate.
Dynamically generated certificates may not be very useful in this case, unless you trust the party that generates the certificate dynamically (I'm not sure if you meant the tool itself or perhaps a website that you would also know).
Often, X.509 certificates will be used just to attach to that signature, because the tooling requires it, whereas you may be able to match the public key against an identity you know directly in the tool with which you verify the signature. Sometimes, it's also just done in anticipation of a case where it will be useful one day.
For example, if you publish your own artifacts to the central Maven repository, you will be required to sign it with your PGP certificate (often only referred to as the PGP public key). Yet, no verification of the certificate is made at all during the process (PGP certificate with only its self-signed signature is good enough). This makes this process relatively pointless in this case, but makes it possible to be stricter in which artifacts you want to use, if you're able to verify those certificates later on.
It's the same but you need a third party to consent that private key belongs to whom ever you think it belongs to.
Signing proves first of all authorship (or approval) of the document by some person. And the key alone won't prove anything. This is what the certificate is needed for - some certificate authority signs the certificate of the user and certifies that the keypair belongs to the person (or legal entity) to which the certificate is issued. The reader of the document can ensure that the signature is valid not by just computing the signature itself, but also by validating the certificate and seeing the name of the certificate owner.
I don't quite understand what vendors can issue certificates dynamically - issuing certificate in such way that they are not self-signed (and self-signed certificates make little sense in context of document signing) requires that the private key, used for signing the certificate, should be embedded into software of those vendors, and as such it's also prone to misuse.
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 am working on a project that requires an ECDH key exchange. I am trying to understand how to protect against MITM attacks. I can sign the public key and send a signature along with the public key transfer to ensure that the key has not been tampered with but that doesn't stop a MITM attack from just doing the same thing. I understand that the key exchange must be verified somehow by a third party but I'm having a hard time understanding how it is that a third party can be the solution assuming that someone can do an MITM attack. Why couldn't they just do an MITM on the third party verification too? Is there really a fail proof way of completely eliminating all possible MITM attacks without some kind of pre-known by both parties?
You need a¹ trusted third party to sign both keys.
Without any knowledge or assertions about the identity of the intended partner, there's simply no way to distinguish him² from anyone else.
¹ one or multiple
² Bob
In a PKI system, "certifying authorities" are an important part of the infrastructure. Certifying authorities sign the public key and the identifying information, so that you know the corresponding private really belongs to the purported identity. This is true for EC keys just as it is for RSA.
By the way, I've looked for CAs that issue EC certificates, and apparently they aren't in practical use.
Most people obtain certificates for their certifying authorities as part of their operating system or security application. They trust these certificates implicitly. There are several dangers here, though.
First, most users don't have an effective way to verify the integrity of these certificates. This is a pretty hard problem, because, at the root of it, you have to have a 100% trustworthy channel for the verification—channel between the authority and the user with which an attacker cannot tamper. When a user downloads a new browser with an collection of root certificates, he can't know that the software wasn't tampered with in transit, or even built with a bogus CA certificate in the collection.
Even if the certificate collection is received intact as the provider intended, there have been questions raised about the integrity of many certifying authorities included by default in popular software. For example, some have pointed out that telecommunications companies in states that have been linked to terror sponsorship have their certificates included in popular browsers. Any trusted authority can issue a certificate for any domain name, and a browser will accept it without question.
In short, no, there is no way to establish a secure channel without first sharing some information on a secure channel. The benefit of PKI and asymmetric cryptography is that one exchange on a secure channel (the receipt of a trusted authority's certificate) permits the establishment of secure channels with many parties. But you have to bootstrap the system somehow.
It sounds like you are heading down a path of rolling your own crypto protocol. Don't do that. It's a bad idea. It leads to insecure systems.
Instead, use SSL or TLS. That is designed to take care of the subtle issues in designing this kind of crypto protocol -- and it has been well-vetted. You'll need a way to verify the other endpoint's certificate. You could use a certification authority, or in some cases it might be feasible to hardcode the public key of the entity you expect to talk to.
You may get better answers if you ask on the Crypto stack exchange.
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).