End certs signed by intermediate certs are accepted by browsers as long as the root is in the trusted certs store. My understanding is that an end-entity cert cannot itself sign other certs (or in any case a browser will not accept such certs). If this is the case, then the browser must be able to distinguish an intermediate cert from an end-entity cert. How does it do this? Is there a message in the intermediate cert saying "This is an intermediate cert" (which has been signed by the root cert for validity)?
Browsers & OS's only store root certificates, not intermediate certs.
Your question is valid, if I have a cert that is signed by Let's Encrypt, what's to stop me using that cert to sign other certs??!!
There is a flag on the cert that specifies whether it's a CA or End Entity.
For StackExchange today, the server presents 3 certs.
- DigiCert SHA2 High Assurance
If you analyze each cert, under the Basic Constraint->Subject Type, the value will be CA for (1) & (2) but it will be "EndEntity" for (3). Browsers and Applications are expected to not accept certs that aren't signed by a CA cert, if the Basic Constraint->Subject Type extension is missing from the cert, the cert is considered a End Entity by default.
There is also a Basic Constraint->Path Length Constraint , that specifies how long a certificate chain for this root certificate can be. This prevents a intermediate CA, from issuing separate CA certs.
There are several "flags" in certificates. one of them is for example "I am a CA" flag, another is the "Maximum Certificate chain length". This last one limits how long a certificate chain may be.
The certificate tools such as openssl will reject signing a certificate with a certificate that does not have the CA flag.
Browsers will stop validating a chain once a non CA certificate is found.
There is no "I am an intermediate" flag, but that status can be infered by being a CA certificate that is signed by someone else.
Each certificate has a subject which describes who the certificate is for and an issuer which means who issued (and thus signed) the certificate. For root certificate subject and issuer are the same, i.e. the certificate is signed by itself ("self-signed"). For intermediate certificates subject and issuer are different. Both root and intermediate certificate need to be CA certificates, i.e. have CA:true in basic constraints.
Based on the subject and issuer one can construct the certificate chain. At the start of the chain is the server certificate, which is issued by CA certificate #1. This CA certificate #1 might be self-signed (issuer equals subject) in which case it is the end of the trust chain and thus the root certificate. Or it might be signed by yet another CA certificate which means that it is somewhere inside the trust chain (and not the end) and it is thus an intermediate certificate.