The doc states:
"You will always need this password in order to access the keystore entry containing that key."
http://docs.oracle.com/javase/tutorial/security/toolsign/step3.html
But whatever keypasswd I set I can export the certificate without it, and the resulting file are all binary equal.
Why don't we need to specify the keypasswd to export the certificate?
The exported certificate is a PUBLIC KEY so it doesn't require password (Is not meant to be protected) what you actually protect is a KEYSTORE (Combination of public + private keys) that's why keytool doesn't require password for export public keys...
Related
Using java Keystore class.
InputStream keystoreStream = new FileInputStream(strKeystorePath);
KeyStore keystore = KeyStore.getInstance("JCEKS");
keystore.load(keystoreStream, strTrustStorePwd.toCharArray());
Key key = keystore.getKey(strAliasName, strTrustStorePwd.toCharArray());
The load() method is throwing keytool error:
java.io.IOException: Keystore was tampered with, or password was incorrect.
But when : use
InputStream keystoreStream = new FileInputStream(strKeystorePath);
KeyStore keystore = KeyStore.getInstance("JCEKS");
keystore.load(keystoreStream, null);
Key key = keystore.getKey(strAliasName, strTrustStorePwd.toCharArray());
it is working fine. Please see that the same passwords are used by load and getKey methods.
When the load() and getKey methods are used with passwords , the load() method is throwing error, but when load() is used with null password and getKey with same password, it is working.
JCEKS, like JKS, uses the store-level password (only) for integrity-checking the entire store; if you call .load(instream,null) it does not check integrity but still loads the contents -- or tries to: if the data has in fact been tampered with or damaged the load may fail in any number of ways, or appear to succeed but cause other problems later; but if the data is correct it does load. (Note this is not necessarily true of other keystore types, like PKCS11.)
The certificates in either JCEKS or JKS are unencrypted, and can be accessed without any (further) password. The privatekeys (if any) are individually password-encrypted, and to a access a privatekey you need to supply the correct key-level password, which can be the same as the store password or different. It is usually less confusing to make the key password(s) the same as the store password, and less confusing is usually desirable, but it is not required.
You apparently have a JCEKS whose store password differs from the value you know, but containing a key whose password matches that value. If you want to change this, after .load(instream,null) re-write it with .store(outstream,desiredpassword).
I know there are already a few posts about this error, but I couldn't find an answer fitting my problem :
I created an AES key with the following command :
keytool -genseckey -alias TEST -keyalg AES -keysize 128 -storepass "a#b$c<d>"
-storetype JCEKS -keystore /usr/my/path/test.jck
I then try to access the keystore from java code :
String password = "a#b$c<d>";
char[] passwordChars= password.toCharArray();
// loading the file containing the key
InputStream inputStreamFichierCle;
try {
inputStreamFichierCle = new FileInputStream(filePath);
keyStore.load(inputStreamFichierCle, passwordChars);
}
And there I get an IOException : keystore was tampered with or password was incorrect.
Note that I tried with normal password (ex : pass) and this works perfectly, so I guess the problem here has to do with the special characters I use in my password.
What is happening, and how can I fix this?
The cause of this problem is the dollar sign in combination with bash command line.
Basically "$c" is substituted with the content of a variable with the name "c". Unfortunately there is no variable with this name, so it is replaced with an empty string.
You can avoid the variable substitution by using single quotes. See the difference:
$ echo "a#b$c<d>"
a#b<d>
$ echo 'a#b$c<d>'
a#b$c<d>
If you use the password "a#b<d>" in your java code, it will work.
I have a keystore.jks file with multiple certificate including public and private key.
now i want to know how to export all public key certificate into new file all-public-cert.crt file.
This "all-public-cert.crt" file contain only certificate (public key only) . should not contain any private key in this file.
after this i would like to ready this "all-public-cert.crt" file via java code and validate public and private key using challenge response.
kindly guide me or suggest me some reference document or url.
Note : i am able to use any tool like openssl or keytool.
Thanks & Regards,
Gaurav Paliwal
Normally a keystore i.e., your keystore.jks contains private keys and the corresponding X.509 certificates. But the X.509 certificates do NOT include a private key, as you falsely assumed:
I have a keystore.jks file with multiple certificate including public and private key
This "all-public-cert.crt" file contain only certificate (public key only) . should not contain any private key in this file.
This means that your X.509 certificates do only contain public key information, no private key information.
In order to fetch a certificate form your keystore (leaving the error handling aside):
String keystorePath = ....
InputStream is = new FileInputStream(new File(keystorePath));
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(is, "keystorePassword".toCharArray());
Enumeration e = ks.aliases();
Set<Certificate> certs = new HashSet<Certificate>();
while (e.hasMoreElements()) {
Certificate cert = ks.getCertificate((String) enumeration.nextElement());
certs.add(cert);
}
Now you have all certificates in your certs Set. But why do you need to put them all into the all-public-cert.crt.
1.) First you cannot put multiple certificates in one file, and hope that the one file can be used the "normal" way (e.g. double click to open it, import it into other applications, ..). The file will be garbage and can only be read from e.g., your application
2.) Therefore the file extension should not be .crt, it should be .myExportedCertificates or something like that.
I think you just want to store the certificates on the file system in order to use them afterwards. In this case simply use this code (error handling is your job):
String pathToStoreTheCerts = ...
File path = new File(pathToStoreTheCerts);
OutputStream os = null;
for (X509Certificate cert : certs) {
File certFile = new File(path, cert.getSubjectX500Principal().getName() + ".crt");
os = new FileOutputStream(certFile);
os.write(cert.getEncoded());
os.flush();
}
os.close();
for a PKI client I need to obtain both non-repudiation and digital signature certificates. I have implemented this code to obtain those certificates:
keyStore.load(null, null);
Enumeration<String> aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
if (keyStore.isKeyEntry(alias)) {
java.security.cert.Certificate certificate = keyStore.getCertificate(alias);
}
}
the problem is that both digital and non repudiation certificates have the same alias. so when I call keystore.getCertificate the system will always return the first result, although in the certmgr.msc window I can see that there are 2 certificates exist and the LOOP block executes two time, but the system will always return duplicate result from the first certificate. How I can solve this problem?
You cannot really have two different entries with the same alias. But this is how you can get list of all first level certificates from the key store as a list
List<Certificate> certificates = new ArrayList<Certificate>();
Enumeration<String> aliases = keyStore.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
Certificate certificate = keyStore.getCertificate(alias);
if (certificate != null) {
certificates.add(certificate);
}
}
Since you're talking about certmgr.msc and using keyStore.load(null, null), I presume you're using the WINDOWS-ROOT or WINDOWS-MY keystore, from the SunMSCAPI provider.
Unfortunately, there is an issue with this provider because it can re-used the same alias for multiple entries, thereby making it difficult or impossible to access some certificates.
The alias used by this keystore is in fact the "friendly name" of the certificate (in the MS-CAPI terminology). While the friendly name doesn't need to be unique in the Windows certificate store, the alias name needs to be.
Presumably, because you seem talking about two distinct certificates for the same entity but with different purposes, they're likely to use the same friendly name by default.
Once way to work around this problem is to identify your certificates with different friendly names in the Windows store: in certmgr.msc, select the certificate, right-click, choose "Properties" and change its "Friendly Name".
If you have two distinct certificates (for different key usages or any other reason) that have unique friendly names, they should show up with different alias names in your KeyStore then.
I'm a certificate noob. I've been trying to import certificates for the past couple of hours and the more I dig into security stuff, the more it feels impossible to understand.
Here is what I'm trying to achieve in java:
the user can upload any kind of formatted certificate with an optional passphrase
I need to convert the certificate to a non-binary PEM format
Extract the private and public keys to store in a database, throw error if missing one of the two
So far I've been able to parse some certificates using java security's x509Certificate but I can't get the private key. I've also tried bouncy castle but no success there either.
Thanks for your help
An X509Certificate only contains a public key.
Private keys are usually encoded using PKCS#8. Try KeyFactory with a PKCS8EncodedKeySpec.
Combined public key certificates with private keys are usually encoded using PKCS#12 (.pfx, .p12). Try a KeyStore of "PKCS12" type (with Bouncy Castle as provider).