I have a basic question about signing a jar file with a provided certificate. I have a certificate(.pem file) that I wish to use to sign a jar. I do not have its private key.
The command that I used till now is: jarsigner -keystore /working/mystore -storepass <keystore password> -keypass <private key password> -signedjar sbundle.jar bundle.jar test. Is there a way to sign the jar without the private key?
No, by definition you need the private key to sign, that's the whole idea. You cannot sign with just the public certificate containing the public key, you can only verify with it.
Related
I'm facing a problem right now and I can't understand why I can't read a KeyStore on Java 6. The piece code is like this:
KeyStore ks = KeyStore.getInstance("jks");
FileInputStream file = new FileInputStream(<path to file>);
ks.load(file, <password>);
String alias = (String)ks.aliases().nextElement();
PrivateKey key = (PrivateKey)ks.getKey(alias, ConstantsUtils.CERT_PASS.toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);
I'm using this certificate to sign a PDF from Java code, but variables key and chain stay null, so the keystore can't retreive my private key.
The Keystore was created by keytool importing a certificate with the next line (Windows 7):
C:\Program Files\Java\jdk1.6.0_37\bin>keytool -importcert -file "<path to cert>" -keystore <path to keystore -alias "<alias>" -keypass <password> -storepass <password>
Imported certificate is from a third party, and should work properly. I don't know if is something wrong importing the certificate or if I'm coding something in a bad way.
You're importing a certificate. Unless it corresponds to a private key already in the KeyStore, and you don't agree to the 'trust CA certs?' prompt, this will create a trusted certificate, and looking for it via a PrivateKey will fail.
And if you're importing a certificate from a third party, you won't have their private key, unless they are spectacularly incompetent.
In short what you're doing doesn't make sense.
Well, finally I found the ultimate solution.
My problem was that I had 2 files, one a certificate (we'll call it certificate.crt) and the other one was the private key (we'll call it private_key.pem). As EJP said previously the problem was around the private key import process. I had 2 different files so I was importing just certificate.crt file into a .jks file, and private_key.pem gave me an error when I tried to import (obviously). So my solution was to merge both files (certificate.crt and private_key.pem) into one PKCS#12 file with this command:
openssl pkcs12 -inkey private_key.pem -in certificate.cert -export -out certificate.pfx
Now, the new certificate.pfx is a keystore which contains public and private key, correctly formated so, with some changes in my code it was possible to obtain the private key and sign my document:
KeyStore ks = KeyStore.getInstance("PKCS12");
FileInputStream file = new FileInputStream(<path to .pfx file>);
ks.load(file, <password>);
String alias = (String)ks.aliases().nextElement();
PrivateKey key = (PrivateKey)ks.getKey(alias, ConstantsUtils.CERT_PASS.toCharArray());
Certificate[] chain = ks.getCertificateChain(alias);
So thats all. Thank you EJP, I was missunderstanding you, and you made me think in the right way. I was facing this four days so I'm pretty hyped up right now.
I am installing a wild Card SSL certificate to my keystore which will be used for Apache Tomcat web server.
Description :
My Tomcat Server is installed on windows 2012 server.
And I have certificates provided from COMODO.
The wildcard cert I'm using has already been used previously on a few servers. so I am directly installing same on my apache tomcat server .
so what I've generated a public keystore using keytool providing the same information used while purchasing the certificate using following tool command.
keytool -keysize 2048 -genkey -alias tomcat -keyalg RSA -keystore tomcat.keystore
Then I have attached my certificates to the generated keystore using following commond
For "Comodo" certificates
i.keytool -import -trustcacerts -alias root -file AddTrustExternalCARoot.crt -keystoreselfservice.keystore
And I have used correct chain of installation of certificate like root , all intermediate, primary from above command.
And while installing each certificate i received the following message
"Certificate added to keystore"
Though I have not got any error .
And when i have opened my keystore there were no certificate chain , means there is individual entry of each certificate . but there is no chain hierarchy of certificates like Root then intermediate then primary.
And in my final PI or certifcate, i am getting provider as local first name instead of Comodo .
EXAMPLE :
CN=nims.ABC.com,OU=abcCommunications,O=abc Group LLC, L=Roseville,ST=Minnesota,C=US
Provider must be
CN=COMODO RSA Organization Validation Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
So I would like to know which steps I have missed or used any extra steps .
Please provide a solution to install a wild card certificate .
Thanks in advance
You did everything correctly. The trust chain is important for another aspect. If you trust one 'certificate' of the chain, you trust the following 'certificates' of the chain too. So to trust all certs of a CA you just have to trust the root CA's cert.
What you realy need to make the wild card certificate work on you server is to import the private key part of it.
I assume you mean Tomcat using Java SSL (JSSE) not APR/Native (OpenSSL). If you want Tomcat-APR, change your question.
If the cert you want to use is already in use on other servers, and you "generated a public keystore using" the keytool command you showed on the NEW server, you generated a NEW KEY which is different from the key the other servers used and different from the key included in the certificate, thus the certificate DOES NOT MATCH that new key and cannot be used with that new key. You also implicitly generated (and have not replaced) a self-signed cert, with both subject and issuer (what you call provider) identifying you rather than a CA like Comodo. This certificate is not good for general use but can be useful for some testing, which is why keytool does it implicitly.
You need to get the certificate, the ALREADY EXISTING private key that MATCHES the certficate, and the needed chain cert(s) into your JKS as a privateKey entry. If an existing SSL server is Java (using JSSE), just copy its JKS. If you want or need to change the password(s) on the copy for your new server, see keytool -storepassword and keytool -keypasswd.
If an existing server is OpenSSL (including Apache httpd and nginx), convert the OpenSSL PEM format to PKCS#12 (preferably on the old server); depending on that server's file layout this is something like
openssl pkcs12 -export -in certfile -inkey keyfile -certfile chaincert -out xxx
and then use keytool to convert PKCS#12 to JKS (preferably on the new server)
keytool -importkeystore -srckeystore xxx -srcstoretype pkcs12 -destkeystore yyy
Note you must use a password on the PKCS#12. This does not need to be the same as the old server keyfile (if any) or the new server JKS, but it's usually more convenient if it is.
If an existing server is IIS, you should be able to export the cert WITH private key AS PFX/PKCS#12 from the Certificate snapin of mmc, and then convert the PKCS12 to JKS as just above.
If an existing server is something else, add it to the question.
I had following qustions about timestamping a jar: (exe timestamping is working fine)
Do we have to "purchase" anything for timestamping , similar to code signing certificate?
Is it mandatory to timestamp the exe/jar from the same TSA , with which it is signed? We have purchased a code signing certificate from GoDaddy.
The "http://support.godaddy.com/help/article/4833/about-code-signing-certificates" link of GoDaddy says:
Is there a limit to the amount of time stamp requests allowed for a
Code Signing certificate? No. Unlike some of our competitors, we do
not limit the number of time stamp requests which can be issued by a
single Code Signing certificate.
From above statement, I understand tha the timestamp can be done, if you have code signing certificate purchased.
using command:
jarsigner -keystore mykeys -sigfile SIG -signedjar SignedApp.jar -tsacert testalias app.jar johndoe
where testalias is the TSA's public key certificate.
Where can I get GoDaddy's TSA public key certificate ?
If I use below command to timestamp
jarsigner -verbose -keystore C:\a.pfx -storepass <password> -storetype pkcs12 C:\abc.jar -tsa http://tsa.starfieldtech.com <pfx certificate alias>
I get the following error:
jarsigner: Certificate chain not found for: -tsa. -tsa must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain.
Apart from How to validate if a signed jar contains a timestamp?, is there any easier way to check the
timestamp of a jar
No, you don't have to purchase anything else. Your certificate is enough.
It is desirable to timestamp your jars, because otherwise they will expire when your certificate expire.
It looks like you permuted the options for jarsigner. Try this order:
jarsigner -verbose -keystore C:\a.pfx -storepass <password> -storetype pkcs12 -tsa http://tsa.starfieldtech.com C:\abc.jar "<pfx certificate alias>"
I have created a public private key pair using the KeyPairGenerator class in Java. From this key pair I have generated the CSR request using the PKCS10 class which has been sent to a CA for verification. The question is how do I load this public private key pair into a keystore? I cant use KeyStore.SetKeyEntry as it requires a certificate parameter along with the private key.
I thought that I would have to wait for the CA to send back a certificate which should then be used for loading the key pair. But If I create the keystore using the keytool command -
keytool -genkey -keyalg RSA -keysize 2048 -sigalg sha1withRSA -alias aliasname -validity 365 -keystore keystorename
and then load this keystore into the Java keystore class, the keystore object contains a privatekeyentry and a CertificateEntry. How is this possible without obtaining a certificate back from the CA.
The keytool command that you used creates a self-signed certificate. When you receive the new certificate signed by the CA, you can import that certificate into the keystore, which will then replace the self-signed certificate.
About your Java question, you will either need to generate a self-signed certificate based on the public key that you created (and signed by the private key), or you will need to wait for the CA to return your signed certificate and use that with the private key in SetKeyEntry.
I have imported a certificate into a private ~/.keystore file:
keytool -list
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
mylyn-mantis, Jul 15, 2010, trustedCertEntry
and am trying to sign a jar with it, but I get a 'certificate chain not found' error.
jarsigner -verbose /home/robert/file.jar mylyn-mantis
jarsigner: Certificate chain not found for: mylyn-mantis. mylyn-mantis must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain.
How can I solve this problem?
It seems that your keystore contains only a certificate (public key) you need a complete key entry, with a private key, and the whole certificate chain to be able to sign anything
Short Answer
Use your alias key instead of key store like this:
jarsigner -verbose -keystore [Your signature storage path] -signedjar [signed filename] [unsigned filename] [Your alias key]
More Details
Here are the easiest way to solve this error:
Go to bin folder .. it may be in this path:
C:\Users[Your computer name]\jdk\bin
or this path:
C:\Program Files\Java\jre1.8.0_77\bin
To prevent issues caused by the configuration of environment variables, please copy both the empty package to be signed, and your key store [the private key for signature] to the bin directory under JDK.
Get your alias key by run this command:
keytool -keystore [your key store] -list -v
Finally run this command:
jarsigner -verbose -keystore [Your signature storage path] -signedjar [signed filename] [unsigned filename] [Your alias key]
I faced same issue. I am having .p12 file issued by CA and I was trying to sign jar file. However I was getting error:
jarsigner: Certificate chain not found for:
Basically I was copying alias name from console. It was having wrong character 'question mark' (?) causing this error. Instead I redirected output of keytool to text file and then I copied alias name from there.
Issue this command:
keytool -list -v -storetype pkcs12 -keystore "mycertificate.p12" > cert.txt
(This is very important. Always redirect to txt file. Do not copy from console output. It can contain wrong characters)
Find out alias name in certificate. Open cert.txt and copy string as it is mentioned in front of "Alias name:"
Let's say this string is "my alias name, a.p.’s my ca limited id"
Use jarsigner:
jarsigner -storetype pkcs12 -keystore "mycertificate.p12" myjarfile.jar "my alias name, a.p.’s my ca limited id"
I had this error, but it was a different issue. When you send off a CSR to a CA it comes from a particular private key with a particular alias that you generated. When you receive the cert back again you must import it using the same alias name or else the two certs will not be wired together.
If you have done it right, when you use keytool -list -v you wil see a single entry with the alias name, of type
Entry type: PrivateKeyEntry
Certificate chain length: 3
For the entry.
If you have done it wrong the you will have two entries
Entry type: PrivateKeyEntry
Certificate chain length: 1
and
Entry type: trustedCertEntry
I encountered this error because I was using a Jenkins "certificate" credential. The Jenkins credential configuration dialog has a text box called Description, whose help says it is a free comment describing the credential. In fact, the Jenkins pipeline block withCredentials uses the Description text box to populate the environment variable named in the aliasVariable property.
withCredentials([certificate(
credentialsId: my_credentials,
keystoreVariable: 'MY_KEYSTORE',
aliasVariable: 'MY_ALIAS', // Set value in Description textbox
passwordVariable: 'MY_PASSWORD')]) {
bat 'mvn clean deploy -Dmy.keystore=%MY_KEYSTORE% -Dmy.alias=%MY_ALIAS% -Dmy.password=\"%MY_PASSWORD%\"'
}
This is not mentioned in the Jenkins documentation.
mylyn-mantis should be the actual alias name you used when you generate the signing key.