Certificate chaining while signing a jar file - ssl

How to introduce one level of certificate chain while signing a jar file? What I am trying to do is,
Sign a jar with generated private key.
Generate a CSR (Certificate Signing Request)
Generate a CA signed certificate where CA is self sign CA
import CA in jcontrol and browser and run the java web start application.
but unfortunately it didn't work and gave security warning.
Please suggest some good approach.

TLDR: get the cert first
Java codesigning uses the PKCS7/CMS signature format, wbich is based on X.509/PKIX public-key certificates. The sequence you posted uses the privatekey as it if magically appeared, but that is impossible. I'm going to bet your sequence actually was:
‍0. keytool -genkeypair
Although the name focusses attention on 'generate keypair', this single command actually does three things: generate a keypair; create a dummy, self-signed certificate for the public half of that keypair; and store both the private half of the keypair and the dummy certificate together in a keystore (usually a file). Note the java.security.KeyStore API does not support storing a privatekey -- or a publickey or raw keypair -- by itself, only a privatekey combined with a certificate chain. (The dummy cert, by itself, constitutes a trivial chain.) For concreteness I will call this dummy cert A.
‍1. Sign a jar with generated private key = jarsigner
You specify to jarsigner a privatekey entry in a keystore, but as above that entry actually contains the cert chain as well, in this case the dummy cert. The PKCS7/CMS signature contains a raw PKC signature (RSA, DSA, or ECDSA) computed using the privatekey, plus the cert which matches that privatekey and thus can be used to verify the signature, plus any chain cert(s) needed to validate the signing certificate. You can see this if you look at the contents of the META-INF/<alias>.{RSA,DSA,EC} entry in the resulting jar.
‍2. Generate a CSR (Certificate Signing Request) = keytool -certreq
‍3. Generate a CA signed certificate where CA is self sign CA
How you did this depends on your CA, but doesn't matter here. To be exact, a CA may have a self-signed cert for the public half of the CA keypair, but as above it actually signs certs it issues using the private half. For concreteness I will call the cert issued by the CA for the signing key B, and the CA's own self-signed cert C.
‍4. import CA in jcontrol and browser and run the java web start application.
I'm not sure if you mean B or C here. But neither will help in verifying the signature done in step 1, because that signature contains and specifies A as the 'signer' cert, i.e. the cert to be used to verify the signature. B is a cert fort for the same publickey, and could be used to verify the signature if the signature specified cert B, but it doesn't, and can't because B didn't even exist when the signature was created.
The correct sequence is:
-genkeypair
-certreq
use CSR to get cert B from CA. You don't actually need C here, although you might get it for convenicnce or reference.
-importcert cert B into the privatekey entry. (If you defaulted the -genkeypair alias to mykey you can default -importcert also, otherwise you must specify the same one.) This replaces the dummy cert A with the 'real' cert B in the privatekey entry. (Be careful not to import cert B to a different alias, or different keystore; this often doesn't give an error. but the result won't work correctly.)
If the 'real' cert B needs one or more chain cert(s) to validate, as is (always?) true for certs from real public CAs like Digicert, GoDaddy, LetsEncrypt, etc, such chain cert(s) must be either included in step 4 (as a combined file, often a 'p7b' or 'p7c' file), or separately imported prior to step 4 into a separate trustedcert entry or entries. However, your in-house CA does not need any chain cert(s).
now jarsigner -- so the signature includes cert B (and its chain certs if any)
    A. separately, cert C must be included in the truststore(s) used by the client system(s); this can be done anytime: after, during or before steps 1-5. For webstart, I believe putting it in Java Control Panel should be sufficient; AFAIK webstart isn't validated by the browser. Applets may have been, but applets haven't worked in browsers for several years or in Oracle Java higher than 8.

Related

How does keytool work: privateKeyEntry and trustedCertEntry?

Ok first I'll say what I know about how SSL works.
Most of all I need to understand how the client certificate works, because I was setting up mTls istio gateway and had trouble with it.
So, firstly I need key-pair, private and public. If I understood correctly, i create them next with the following command:
keytool -genkey -alias myKeyPair -keyalg RSA -keysize 2048 store.jks
If I look in the keystore there will be one PrivateKeyEntry. Next I create request for certificate:
keytool -certreq -keyalg RSA -alias myKeyPair -file request.csr -keystore store.jks
After a while, I received a signed client certificate client.cer and certificate trusted CA ca.cer.
Now there are questions:
First, i tried to send request from curl. But curl needs private key which stored in jks. I dont have openssl and cant get it, so i extract private key using java code. But the result was always the same: istio gateway: peer did not return a certificate
Second, I tried using java.net.http.HttpClient with SSLContext setting containing my jks. And it worked. But firstly I had to put ca.cer and client.cer in my jks. And this I cannot understand: why do I need to put ca.cer? Because without ca.cer stored in store.jks i have error certificate validation.
Also when I put client.cer in jks, keytool displays a warning: Certificate already exists in keystore under alias <myKeyPair>. Do you still want to add it? Why does it think privateKeyEntry and trustedCertEntry are the same?
Meta: a poor answer due to the vagueness of the question, but much too long for comments.
First, i tried to send request from curl. But curl needs private key which stored in jks. I dont have openssl and cant get it, so i extract private key using java code. But the result was always the same: istio gateway: peer did not return a certificate
Either your 'extract' was wrong or the way you provided it to curl was wrong, or both, and you described neither. First, to be clear, like any client doing client auth, curl actually needs the privatekey and certificate, and usually any applicable chain certificate(s). What file format(s) you must use, and whether a single combined file or separate files (added:) or none at all as it turns out, depends on the curl build you are using: curl supports seven SSL/TLS implementations, and the ways to provide client-key-and-cert vary among them. Use curl -V (uppercase) to see how it was built, then look at the portions of the man page, on your system or on the web, that apply to that implementation.
Second, I tried using java.net.http.HttpClient with SSLContext setting containing my jks. And it worked. But firstly I had to put ca.cer and client.cer in my jks. And this I cannot understand: why do I need to put ca.cer? Because without ca.cer stored in store.jks i have error certificate validation.
Possibly it is a 'chain' or intermediate CA cert. An SSL/TLS client (like a server) is required by the standard to send any chain cert(s) needed to connect the end-entity (client or server) cert to normally a 'root' in the receiver's truststore. (Since RFC5280, and confirmed by RFC8446, it is actually possible to use an anchor that isn't a root, but it is rare to do so.) Possibly it is even a combination of chain cert(s) and root (or anchor). (Some reliers sometimes can still build the chain to validate a cert when it wasn't correctly sent; browsers especially tend to do this, but most servers not.)
Look at it and see. If it is PEM format you can see with any text display or edit program how many certs it contains. If it is a single cert you can display the details with keytool -printcert -file $file -- or since you already imported it, keytool -list -v -alias name -keystore $ks [-storepass $pw]. If it is multiple certs in PEM format you can break it apart with an editor and display each one separately. If it is multiple certs in DER format you won't be able to handle that easily, but fortunately that format is rarely used. openssl x509 [-inform pem|der] -text -noout is also commonly used to display cert file details, but you say you can't use it.
Also when I put client.cer in jks, keytool displays a warning: Certificate already exists in keystore under alias . Do you still want to add it? Why does it think privateKeyEntry and trustedCertEntry are the same?
If you only did this once, and correctly, it shouldn't. Given separate cert
files, you should keytool -importcert the client cert to the alias of the privatekey entry you created, and used to create the -certreq, which in your example is myKeyPair, after you keytool -importcert any needed chain cert(s), and optionally the root or anchor, (each) to a different alias. (It is often convenient, but not required, to use simple words like root, imed, imed2 etc. as aliases.) Alternatively, if you have the whole chain as a single file, either PEM sequence or DER sequence, or 'p7b' (a dummy PKCS7 SignedData with no data and no signature, commonly used as a container for one or more certs, such as a chain) either PEM or DER, you should import that chain in a single operation.

Does a non-self-signed certificate, imported into root store, require a (self-signed) issuer to also be imported into the root store?

Does a non-self-signed certificate, imported into root store, require a (self-signed) issuer to also be imported into the root store?
Suppose I've a certificate A that is signed by another certificate B. Is it then sufficient to only import A into the root store, i.e. certificate validation stops at A, or should B also be imported into the root store for proper certificate validation?
The reason I'm asking this question, is that I've encountered different results with different products (e.g. web browser or system), and so I want to know the right way.
You should include Cert B in truststore. As mentioned in the comments, your mileage may vary as clients, as well as servers, implement RFC differently.
In terms of rules, spec for x.509 certs is in IETF RFC 5280. The key information is that for SSL handshake to happen client should do a full cert chain validation, which ends up with a self-signed certificate that is in your trust store.
Your Cert is not self-signed, it is issued by a different CA (cert B). If you do not have B in your truststore, then trust chain is broken. However, again as mentioned above, it is possible that client will not validate the full cert chain.
Think of it this way. Your client is presented with Cert A, which is signed by "B". Client should verify that signature on A is fine, which means it needs (certificate of) "B". If B is a "root" CA or self-signed, its "issuer" and "subject" fields will match. And if that Cert B is in your TrustStore, you are golden.
It's the job of the server to send you a certificate list for TLS.
This is a sequence (chain) of certificates. The sender's
certificate MUST come first in the list. Each following
certificate MUST directly certify the one preceding it.
There is a visual representation of certificate chain verification here. Hope it helps.

In SSL trust hierarchies, what is used to sign an intermediate certificate and how does this relate to the root certificate?

I'm completing an assignment on SSL and I feel I understand the basics of how certs are used with asymmetric and symmetric encryption. But I'm having difficulty understanding some details of how exactly trust hierarchies work.
Specifically, what is used to sign an intermediate certificate? All the guides I've looked at state that the CA root cert is used to sign the intermediate cert. But what exactly does "sign" mean here? In other words, how does a server prove that its intermediate certificate is authenticated by the CA root cert?
My guess is that the public key or signature of the root cert are used when generating the signature of intermediate cert the but I'm not sure if this is accurate.
I would really appreciate any info to improve my understanding.
If there is exactly one intermediate, which is often but not always the case, the intermediate cert is signed by the root in exactly the same way an end-entity cert (for SSL/TLS mostly a server cert) is signed by the intermediate. In both cases this is a shorthand; signing is actually done using the private key of an asymmetric keypair, and the cert contains the public key of the same keypair which is used to verify signatures made with the private key. Since the private keys are private and all of us who use the CAs see only their public keys, we focus on that. Thus:
the server cert is signed using the private key belonging to the intermediate CA; the intermediate cert contains the matching public key. As part of verifying the server cert, the relier (e.g. browser) finds or confirms the intermediate cert using the Isssuer name in the server cert, and uses the public key from the intermediate cert to verify the signature on the server cert; this assures that the server cert was actually issued by the intermediate CA and has not been tampered with.
According to SSL/TLS standards the server should always send the intermediate cert (or certs, in order) following the server cert in the handshake, although if it fails to do so, some clients may use AIA from the certificate or other heuristic means to obtain the cert, or may have it already cached or even configured.
the intermediate cert is signed using the private key belonging to the root CA; the root cert contains the matching public key. As part of verifying the intermediate cert, the relier finds the root cert using the Issuer name in the intermediate cert, and uses the public key from the root cert to verify the signature on the intermediate cert; this assures that the intermediate cert was actually issued by the root CA and has not been tampered with.
The root cert normally must (already) be in the relier's local 'trust store' and the server does not need to send it; normally the trust store is provided either by the browser developer (Firefox) or by the OS/platform developer (IE/Edge, Chrome, Safari).
Notice the close parallel between these two statements with the (notable) exception of how the relier finds the parent cert. Also note that validating a server cert chain for an SSL/TLS connection involves much more than just verifying the signatures, although verifying the signatures is a critical part and without it the other validation criteria could not be assured.
One intermediate CA, and intermediate cert, will generally be used by a large number (thousands to millions) of server certs and servers. The server isn't responsible for 'proving' anything about the intermediate cert, only passing it on to the client, which validates the entire chain.
Cross-stack see also
https://security.stackexchange.com/questions/56389/ssl-certificate-framework-101-how-does-the-browser-actually-verify-the-validity
which has a nice graphic of this relationship.

Use .p12 to create CA?

I have generate .p12 file from my server. But righ now we are developing IOS app which requires CA to implement it.
We are using Amazon EC load balancer server, so i have not idea where I can get CA, also is it possible that .p12 can generate CA?
A CA is a Certificate Authority. It is an organization that generates a public/private key pair for you. A PKCS#12 is a standard that explains how to store public/private key pairs in a file. Your .p12 file is such a file. It is a keystore that contains digital certificates (a public and a private key pair) as defined in PKCS#12.
If you have a .p12, there are two options:
Either your certificates are self-signed. In this case, you have created your own public and private key pair and you've stored it inside a .p12 file. As no CA is involved, there is no way to check if you created those certificates, or if somebody else impersonating you created those certificates.
Or you obtained that .p12 file from a CA. In this case, the CA signed your certificate and there is a certificate chain that eventually leads to the root certificate of your CA. A CA doesn't hand out such certificate to just anybody. A CA will first check that you are who you say you are. This way, whichever party gets confronted with your certificate (for instance because you used your private key to sign your code), knows that you are who you say you are, provided that your CA is a trusted party (there are CAs and then there are CAs).
This image shows how it works:
You are Bob, Apple is Alice, Trent is your CA. Apple wants you to work with a CA because Apple doesn't know you, but Apple knows CA. Once you make yourself known to the CA and once the CA trusts you, Apple will trust you.
See https://en.wikipedia.org/wiki/Alice_and_Bob to find out how the names in this image were chosen.
So the real question is: can you extract your public key from your .p12 file and show it to us so that we can see if your certificate is self-signed or if it's signed by a CA? Without that info, I don't think anyone can help you.

Difference between self-signed CA and self-signed certificate [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
I'm not clear on the difference between a CA key and a certificate. Isn't a CA key simply a certificate? Let me try and clarify with an example.
I have a client and a server. I'm only trying to validate my connection to my server and not trying to establish trust to others so I don't care about signing with a real CA.
Option 1: Generate a self-signed CA (ssCA) and use that to sign a certificate (C). I then install ssCA into the root keystore on my client and setup my server to use certificate C.
Option 2: Generate a self-signed certificate (SSC). Install SSC into the root keystore on my client. Setup my server to use certificate SSC.
The second option seems like a much simpler process. Should that still work?
First, about the distinction between key and certificate (regarding "CA key"), there are 3 pieces used when talking about public-key certificates (typically X.509): the public key, the private key and the certificate.
The public key and the private key form a pair. You can sign and decrypt with the private key, you can verify (a signature) and encrypt with the public key. The public key is intended to be distributed, whereas the private key is meant to be kept private.
A public-key certificate is the combination between a public key and various pieces of information (mostly regarding the identity of the owner of the key pair, whoever controls the private key), this combination being signed using the private key of the issuer of the certificate.
An X.509 certificate has a subject distinguished name and an issuer distinguished name. The issuer name is the subject name of the certificate of the entity issuing the certificate. Self-signed certificates are a special case where the issuer and the subject are the same.
By signing the content of a certificate (i.e. issuing the certificate), the issuer asserts its content, in particular, the binding between the key, the identity (the subject) and the various attributes (which may indicate intent or scope of usage for the certificate).
On top of this, the PKIX specification defines an extension (part of a given certificate) which indicates whether a certificate may be used as a CA certificate, that is, whether it can be used as an issuer for another certificate.
From this, you build a chain of certificates between the end-entity certificate (which is the one you want to verify, for a user or a server) and a CA certificate you trust. There may be intermediate CA certificates (issued by other CA certificates) between the end-entity certificate of your service and the CA certificate you trust. You don't strictly need a root CA at the top (a self-signed CA certificate), but it's often the case (you may choose to trust an intermediate CA certificate directly if you wish).
For your use case, if you generate a self-signed certificate for a specific service, whether it has the CA flag (basic constraints extension) doesn't really matter. You would need it to be a CA certificate to be able to issue other certificates (if you want to build your own PKI). If the certificate you generate for this service is a CA certificate, it shouldn't do any harm. What matters more is the way you can configure your client to trust that certificate for this particular server (browsers should let you make an explicit exception quite easily for example). If the configuration mechanism follows a PKI model (without using specific exceptions), since there won't be a need to build a chain (with just one certificate), you should be able to import the certificate directly as part of the trust anchors of your client, whether it's a CA certificate or not (but this may depend on the configuration mechanism of the client).
Both options are valid, option 2 is simpler.
Option 1 (setting up your own CA) is preferable when you need multiple certificates. In a company you might set up your own CA and install that CA's certificate in the root keystore of all clients. Those clients will then accept all certificates signed by your CA.
Option 2 (self-signing a certificate without a CA) is easier. If you just need a single certificate, then this is sufficient. Install it in the keystores of your clients and you are done. But when you need a second certificate, you need to install that again on all clients.
Here is a link with further information: Creating Certificate Authorities and self-signed SSL certificates
You can openssl x509 -noout -text -in $YOUR_CERT to see the differences between files contents:
In your self-signed CA, you can see:
X509v3 extensions:
X509v3 Basic Constraints:
CA:TRUE, pathlen:0
And in your self-signed certificate, it's:
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
If you need more certificates (C), you need to create a self-signed CA (ssCA).
If you need a single certificate, you can just create a self-signed certificate (SSC).
To trust the single certificate (SSC), you need to install SSC into the root keystore on your client.
To trust many certificates at once, you need to create a self-signed CA (ssCA), then install ssCA into the root keystore on your client.
You must always have a root CA, the CA has a key that can be used to sign a lower level certificate and a root certificate that can be embedded in the accepted root certificates on the client and is used to verify the lower certificates to check they are valid. Self signed just means you are your own CA. Whenever creating a self signed certificate you create a ca, then sign a site cert with that CA.