smartcard and p12 file creation - java

I'm trying to create a p12 file (pkcs12).
I know that i need a certificate and a private key to create it. I read the certificate from smart card, but i have problems with private key.
I know that in smart card there is a private key, but i cannot extract it...is it true?
There is another way to use the private key stored in smart card and use it to create the p12 file?
I want to use this code:
KeyStore store = KeyStore.getInstance("PKCS12");
store.load(null, null);
store.setKeyEntry("Eric's Key", privKey, null, certificate);
FileOutputStream fOut = new FileOutputStream("id.p12");
store.store(fOut, passwd);
Any suggestion please?
Thanks

No, you generally cannot extract the private key from a Smart Card. Sometimes there are backup or key wrapping functions available, but you would require special access for that. PKCS#12 is a binary format for storing keys and certificate, so you do require access to the private key to create one.

Related

Is there any way to get the plain text from signed data using private key?

The plain text is signed using java.security.Signature. Below is the code used to sign the plain text
public String getSignature(String plainText) throws Exception
{
KeyStore keyStore = loadKeyStore(); // A local method to read the keystore file from file system.
PrivateKey privateKey = (PrivateKey) keyStore.getKey(KEY_ALIAS_IN_KEYSTORE, KEYSTORE_PASSWORD.toCharArray());
Signature privateSignature = Signature.getInstance(SIGNATUREALGO);
privateSignature.initSign(privateKey);
privateSignature.update(plainText.getBytes("UTF-8"));
byte[] signature = privateSignature.sign();
return String.valueOf(signature);
// KEY_ALIAS_IN_KEYSTORE, KEYSTORE_PASSWORD and SIGNATUREALGO are all constant Strings
}
Note 1: I found online a way to verify the signature using the public key Java Code Examples for java.security.Signature#verify(). But this is not what I require.
Note 2: I also found a ways to encrypt and decrypt as mentioned here RSA Signing and Encryption in Java. But the use case I have in hand is to get the original plain text from a signed data. Is that possible?
No, you can't retrieve the original content from just the signature.
The signature alone does not contain enough information to restore the original clear text, no matter what keys you have access to.
The basic idea of a signature is to send it together with the clear text. That means the clear text will be visible, but the signature can be used to verify that the message was written (or at least signed) by who claims to have done so and has not been tampered with since then.
Signing something is different from encrypting it. The two often uses the same or related technologies and both fall under cryptography.

Is there a way to decrypt S/MIME public key data?

I would like to get the email address and expire date to a S/MIME certificate based on it's public key. Is this aproach even possible? Or am I totally wrong? Can I decrypt the public key to get these kind of data via java?
I searched in google, read the wiki pages and read about an oracle s/mime project. But it doesn't seam like its possible. Are those data only availabe in the csr??
Thanks in advance
I'm amazed this isn't a dupe, but I couldn't find a good one.
Although Bouncy is fine and has many features if you want to use it, core Java can handle X.509 certificates since forever. For a cert in a file (or anything that can be accessed as a Stream) in either PEM or DER format (although the javadoc isn't clear on that) all you need is CertificateFactory:
CertificateFactory fact = CertificateFactory.getInstance("X.509");
// from a real file
InputStream is = new FileInputStream ("filename");
Certificate cert = fact.generateCertificate(is);
is.close(); // or use try-resources to do automatically
// from an alternate/custom filesystem, such as a ZIP
Path p = Paths.get("somespecification"); // or any other creation of a Path
InputStream is = Files.newInputStream(p); // add open options if needed
// same as before
// from the classpath (usually a JAR)
InputStream is = ClassLoader /*or any Class<?> object*/ .getResourceAsStream("name");
// same as before
// from a byte[] in memory
InputStream is = new ByteArrayInputStream (bytearray);
// same as before, except don't really need to close
// you get the idea
Although JCA APIs like this one are defined to allow a lot of extension, reading an X.509 cert will actually give you not just Certificate but subclass X509Certificate from which .getNotAfter() gives the expiration date-time directly. The email address if present (which isn't required by X.509 certs in general, but should always be the case in a cert used for S/MIME) will usually be an attribute in the subject name, which actually has internal structure that Java doesn't let you get at directly so you need to:
String x500name = ((X509Certificate)cert).getSubjectX500Principal()) .toString();
// simple case: no multivalue RDN, no reserved chars ,+="<>\;# or extra spaces
for( String attr : x500name.split(", ") )
if( attr.startsWith("EMAILADDRESS=") )
... use attr.substring(13) ...
// other cases require slightly more complicated parsing
Note there is no encryption at all in X.509, and thus no actual decryption, although many people use 'decrypt' to describe anything unfamiliar not an actual cipher.
File file = new File(fileName);
FileReader fileReader = new FileReader(file);
PEMParser pemParser = new PEMParser(fileReader);
X509CertificateHolder caCertificate = (X509CertificateHolder) pemParser.readObject();

Reading and writing to java KeyStore

My app needs only to read private keys(with associated public cert), no writing to KeyStore, no password changing, no changes at all - just reading.
Does anybody know for sure that for reading I can use this code:
///doing some actions
KeyStore store = KeyStore.getInstance("foo", "bar");
store.load(iaminputstream, iampwd); // I'M JUST LOADING, I'M NOT GONNA STORE IT!
PrivateKey pk = (PrivateKey) store.getKey(iamalias, iamkeypass);
Certificate cert = store.getCertificate(iamalias);
///contnuing some actions
instead of this:
///doing some actions
KeyStore store = KeyStore.getInstance("foo", "bar");
try{
store.load(iaminputstream, iampwd); //I'VE LOADED
PrivateKey pk = (PrivateKey) store.getKey(iamalias, iamkeypass);
Certificate cert = store.getCertificate(iamalias);
} finally {
store.store(iamoutputstream, iampassword); //AND I'VE SAVED!
}
///contnuing some actions
Prove link is highly appreciated!
You don't need to save it of course. Just don't forget to handle exceptions.
Take a look at javadoc - there is nothing about required saving after load() call.
If you are not storing anything, you don't have to call store.store()
But do remember to close the inputstream and handle exceptions.

Not getting same key values through keystore

I stored private key in a file using keystore
ks.setKeyEntry("kk1", pr, pass, cert1);
//ks is obj of keystore,
//kk1 is alias,
//pr-->is private key,
//pass->is the password to protect that key,
//cert1-->is the certificate chain..
I printed "pr"(private key) while storing to the file.
I another program I opened the file and read the contents using method isKeyentry and printing Private key using getkey....
I am not getting the both(private key) values same...(password is fine because if it is wrong the file will not open)..What's wrong????
Does it need to be same???
It is not possible to verify 2 key values with any parameter like hashcode,toStirng etc.
This is the method I followed:
I tried to encrypt some data using both the keys and verified if I am getting same data or not.Whle comparing use Array.equals() since we get byte array after encrypting.
I did this just to know whether I am retrieving the same key that I kept in a file using keystore.
Thank you....
How are you measuring equivalence? The simplest, safest, method I can think of would be to do the following:
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(pr.getEncoded());
System.out.println(Arrays.toString(digest));

Using keystore with javax.crypto for file encryption/decryption

I was advised to look here: http://exampledepot.com/egs/javax.crypto/DesFile.html for the source code of encryption/decryption using import javax.crypto. I have generated my key via keytool and now I don't know how to pass my generated keys into that application for encryption and decryption.
My situation is, that I have a XML file stored online (it stores configuration details) and before I parse it with a XML parser I have to decrypt it. First of all I should of course encrypt it, before it goes online.
Question is: How to pass my generated keys into code visible in link in first row?
Thanks
How to load a KeyStore is documented in the JavaDoc of the KeyStore class:
import java.io.FileInputStream;
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
// get user password and file input stream
char[] password = getPassword();
try (FileInputStream fis = new FileInputStream("C:/mykeystore.jks")) {
ks.load(fis, password);
}
Once you have loaded the key store you can load the key:
Key myKey = ks.getKey("mykeyalias", password);
The key alias is the one you have specified using keytool.
Using the myKey you can initialize the Cipher instance or use for example a CipherOutputStream / CipherInputStream

Categories