Reading and writing to java KeyStore - java

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.

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

How to convert java KeyStore to PKCS7 .p7b file?

Convert X509 to PKCS7
Create PKCS7 from keystore
I have tried both the answers above but I feel these do not suit my need since Based on the below link I can summarize that PKCS7 is used for two purposes,
Creating signatures, digest etc CMS(Crytographic message syntax)
A container for certificates
Based on this I summarized
My need is more of point no.2. I just want to create a .p7b file using all the certificates that I have in a KeyStore object. Since PKCS7 cannot contain private key. The above two answers generate a signature and what not. Am I missing something? is that the way to go ahead or is there another way?
I can extract certs from a .p7b file using
FileInputStream is = new FileInputStream( "cert.pkcs7" );
CertificateFactory cf = CertificateFactory.getInstance( "X.509" );
Iterator i = cf.generateCertificates( is ).iterator();
while ( i.hasNext() )
{
Certificate c = (Certificate)i.next();
System.out.println(Base64.getEncoder.encodeToString(c.getEncoded());
}
I am asking how to do the reverse, i.e create a .p7b file from Certificate[] or Java KeyStore
Okay I found the solution:
Solution In this we can create what I exactly asked for but I still get the signed data which is generated. I don't want that. A simple .p7b package which I already have has no signerInfo will the .p7b created by this solution have it?
Is this the right way to do it?
Found the solution in this link:
code:
//Export a certificate list to PKCS#7
public static byte[] exportCertificatesAsPkcs7(X509Certificate certs[]) throws Exception {
List certList = new ArrayList();
for (X509Certificate certificate: certs){
certList.add(new X509CertificateHolder(certificate.getEncoded()));
}
Store certStore = new JcaCertStore(certList);
CMSProcessableByteArray msg = new CMSProcessableByteArray("Hello World".getBytes());
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
gen.addCertificates(certStore);
CMSSignedData data = gen.generate(msg, "BC");
return data.getEncoded();
}
Useful links related to PKCS7:
Convert X509 to PKCS7
Create PKCS7 from keystore

smartcard and p12 file creation

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.

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