Checking pfx file type with struts - java

Is there any way to check the uploaded certificate is really a pfx certificate? I tried with the following code:
LazyValidatorForm lazyForm = (LazyValidatorForm) actionForm;
FormFile cerFile = (FormFile) lazyForm.get("cerFile");
if (!cerFile.getContentType().equals("application/x-pkcs12")) {
/** return error code **/
}
However, most of the time, the content type is application/octet-stream, which is no use

You could try loading the uploaded file into a KeyStore:
LazyValidatorForm lazyForm = (LazyValidatorForm) actionForm;
FormFile cerFile = (FormFile) lazyForm.get("cerFile");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(cerFile.getInputStream(), null);
Even if the .pfx contains a password protected private key, the .pfx should still be loaded (it's basically useless without the password but it should load).
If you get no exception and the keyStore.size() equals 1 after the load, then it must be a .pfx file.

Related

KeyStore.load not working but KeyStore.getkey is working with same password

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).

Not able to access Private key from PKCS12 file using java

I have created a pkcs12 file having a private key entry without any password.
I am able to access the p12 file using keytool utility without providing any password.
The same I am not able to to programmatically.
When I am trying like below
if( keyStore.isKeyEntry(KEYSTORE_ALIAS)) {
key = (PrivateKey) keyStore.getKey(KEYSTORE_ALIAS,new char[0]);
}
I am getting the below exception
Caused by: javax.crypto.BadPaddingException: Given final block not
properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.PKCS12PBECipherCore.implDoFinal(PKCS12PBECipherCore.java:355)
at com.sun.crypto.provider.PKCS12PBECipherCore$PBEWithSHA1AndDESede.engineDoFinal(PKCS12PBECipherCore.java:387)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at sun.security.pkcs12.PKCS12KeyStore.engineGetKey(PKCS12KeyStore.java:266)
... 2 more
key = (PrivateKey) keyStore.getKey(KEYSTORE_ALIAS,new char[0]);
That's not the correct way to specify no key. Here you are specifying a zero-length key. It isn't the same thing. Try this:
key = (PrivateKey) keyStore.getKey(KEYSTORE_ALIAS, null);

Reading PEM public key into iOS

I have a base64 public key that was generated by java using this code:
RSAPublicKeySpec rsaKS = new RSAPublicKeySpec(modulus, pubExponent);
RSAPublicKey rsaPubKey = (RSAPublicKey) kf.generatePublic(rsaKS);
byte[] encoded = rsaPubKey.getEncoded();
String base64 = Base64.encodeToString(encoded, Base64.DEFAULT);
Log.e(null, "base64: " + base64);
This results in a Base64 string.
In OSX I can get a SecKeyRef using this code:
// Create the SecKeyRef using the key data
CFErrorRef error = NULL;
CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
CFDictionarySetValue(parameters, kSecAttrKeyType, kSecAttrKeyTypeRSA);
CFDictionarySetValue(parameters, kSecAttrKeyClass, kSecAttrKeyClassPublic);
SecKeyRef keyRef = SecKeyCreateFromData(parameters, (__bridge CFDataRef)[pubKey base64DecodedData], &error);
However in iOS there is no SecKeyCreateFromData method.
I can use the Base64 string in iOS using this code which adds it to the keychain, then retrieves it again as a SecKeyRef however i'd much rather not have to add the cert to the keychain just to be able to retrieve it to use it once.
Doing some research, it seems I should be able to use SecCertificateCreateWithData to create a certificate to use in iOS from the Base64 string I have, however I always get back a NULL cert when using this code:
NSString* pespublicKey = #"MIGfMA0GCSqGSIb3....DCUdz/y4B2sf+q5n+QIDAQAB";
NSData* certData = [pespublicKey dataUsingEncoding:NSUTF8StringEncoding];
SecCertificateRef cert;
if ([certData length]) {
cert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certData);
if (cert != NULL) {
CFStringRef certSummary = SecCertificateCopySubjectSummary(cert);
NSString* summaryString = [[NSString alloc] initWithString:(__bridge NSString*)certSummary];
NSLog(#"CERT SUMMARY: %#", summaryString);
CFRelease(certSummary);
} else {
NSLog(#" *** ERROR *** trying to create the SSL certificate from data located at %#, but failed", pespublicKey);
}
}
You are not base64-decoding your key data first. You are passing base64-encoded data to SecCertificateCreateWithData(), and that function expects the raw, decoded data. Try something like this instead:
NSData *certData = [[NSData alloc] initWithBase64EncodedString:pespublicKey options:0];
cert = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certData);
Update:
What you are sending to your iOS code is the base64 DER-encoded key, not a DER- or PEM-encoded certificate. As such, the result you're seeing is expected -- you give it a DER-encoded data blob which doesn't contain a certificate and it gives you back a null certificate reference representing the non-existent certificate data.
You have two options:
Use the code you have already found to add the key to the keychain and then fetch it out. That seems to be the "iOS way" to import keys for use on iOS.
Use the public key and its associated private key to sign a certificate and import that into your app, create a temporary trust relationship with that certificate, then pull the public key out of the certificate's information (example: iOS SecKeyRef from NSString)
For the second option to work, your Java code is not only going to have to have the public key, it will also need the associated private key to generate a signed certificate.
Depending on what you plan to do with the SecKeyRef, you may run into problems. SecKeyRef values can be cast straight to SecKeychainItemRef values for use in Keychain Services functions. If the SecKeyRef value doesn't come from the keychain, your code will get errors. Read the docs for more info

How to access certificates and private key from etoken using java

I am working with digital certificate and digital signature. We got pfx file from the vendor. We convert this pfx file to java key store and used it to create the digital signature using java program. Now the vendor has etoken hardware. They give me cer file in place pf pfx. I converted cer to jks java key store and used it in my program... My program told me that private key is not there. I have found that there is no private key with cer file. I have talked to vendor about this he told me private key can not be extracted from the etoken.. you must directly access the etoken through program to get the private key. Can anybody tell me how do i access etoken programetically. Is there any java api which is used to access etoken directly. Help me....
Private key can be extracted using PKCS11.
To extract Private key from eToken in java, you need to pass config file to sun.security.pkcs11.SunPKCS11 instance.
Config file must have following properties:
name=<Name of Etoken>
slot=<slot number for etoken>
library=<path of the pckcs11 library(dll) for that etoken>
Following is sample code to extract private key using eToken
PrivateKey privateKey = null;
char password[] = "1234".toCharArray();
Provider userProvider = new sun.security.pkcs11.SunPKCS11("D:\\config.cfg");
ks = KeyStore.getInstance("PKCS11", userProvider);
ks.load(null, password);
Enumeration e = ks.aliases();
String alias=null;
while (e.hasMoreElements())
{
alias = (String) e.nextElement();
privateKey = (PrivateKey) ks.getKey(alias, password);
}

How to export multiple public certificate in one crt file

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();

Categories

Resources