Using keystore with javax.crypto for file encryption/decryption - java

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

Related

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

Programmatically compute "SHA-256-Digest-Manifest-Main-Attributes" in jar file?

Because of using HSM hardware we need to sign a jar file w/o actually using Jarsigner. It's all pretty obvious, to the exception of the SHA256 digest of the manifest's main attributes, the attribute "SHA-256-Digest-Manifest-Main-Attributes" in the .SF file.
The main attributes are defined in the manifest specification.
However, I can not seem to find the proper order and/or values to hash. I've been scanning the source code of Jarsigner, but neither can I not find the class reading the attributes.
Does somebody knows how this works ?
[UPDATE: PKCS11 Sun provider]
Using Java PKCS11 provider works, but it yields an empty keystore
name = OpenSC
description = SunPKCS11 w/ OpenSC Smart card Framework
library = /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
slotListIndex = 0
Code sample
final InputStream inputStream = Signer.class.getClassLoader().getResourceAsStream("opensc-java.cfg");
final SunPKCS11 pkcs11 = new SunPKCS11(inputStream);
final KeyStore ks = KeyStore.getInstance("PKCS11", pkcs11);
ks.load(null, "*****".toCharArray());

Error while decrypting HSM keys using nCipherKM

I am trying to decrypt Database password stored in a Securestorage file. I am using the nCipherKM HSM security provider and the Key Encryption Keys used for decryption is stored in a key store (folder). While I try to load the HSM Key Store by passing the keystore password , it fails to load the key store with the following Exception. Not sure what is the root cause of this error.
Code Snippet:
java.security.provider hsm_provider = (java.security.provider)Class.forName("com.ncipher.provider.km.nCipherKM").newInstance();
java.security.Security.addProvider(hsm_provider);
myKeyStore = KeyStore.getInstance(KeyStore.getDefaulttype,"nCipherKM");
myKeyStore .load(new FileInputStream(KeyStorePath),pwdOfKeyStore);
Exception:
java.io.IOException: A password was supplied but all keys are
module protected. at
com.ncipher.provider.km.KMKeyStore.engineLoad()
Note: Posting this answer to an old question in the hopes of helping others who encounter this same problem.
The root cause could be that the keystore was created with the option to protect the keys with the module. This doesn't mean that a passphrase is optional, it means it is prohibited.
To fix, use the code below
java.security.provider hsm_provider = (java.security.provider)Class.forName("com.ncipher.provider.km.nCipherKM").newInstance();
java.security.Security.addProvider(hsm_provider);
myKeyStore = KeyStore.getInstance(KeyStore.getDefaulttype,"nCipherKM");
myKeyStore .load(new FileInputStream(KeyStorePath),null);
Note: if you attempt to extract the private key from the keystore, you should pass in a null too, like the following:
PrivateKey privateKey = (PrivateKey)keystore.getKey(KEYSTORE_ALIAS, null);

How to encode and decode SecretKey in JAVA?

KeyStore ks = KeyStore.getInstance("JCEKS");
ks.load(null, null);
SecretKey skInput = new SecretKeySpec("input".getBytes(), "DESede");
SecretKeyEntry skeInput = new KeyStore.SecretKeyEntry(skInput);
ks.setEntry("input_key", skeInput, new KeyStore.PasswordProtection("banana".toCharArray()));
FileOutputStream fos = new FileOutputStream("my.keystore");
pambks.store(fos, "password".toCharArray());
fos.flush();
fos.close();
The code shown above is trying to encode the input into a SecretKey and store into keystore. The code shown below is how I retrieve the key from keystore. But I do not know how to decode it back to original value?
FileInputStream fin = new FileInputStream("my.keystore");
KeyStore ks = KeyStore.getInstance("JCEKS");
ks.load(fin, "password".toCharArray());
SecretKeyEntry ske = (SecretKeyEntry) readks.getEntry("input_key", new KeyStore.PasswordProtection("banana".toCharArray()));
SecretKey sk = ske.getSecretKey();
I wasn't sure whether this is the correct way of doing encryption and decryption to SecretKey, please correct me if I'm wrong.
Reading back this Q/A I think I've misread the question.
You can get the byte representation of the key back by calling the getEncoded method on you key. After that it is possible to use one of the String constructors to revert it back to text. As said, you should not use a string as key. Note that DES keys are contain parity in the last bit, so this may change the result. To use strings for keys it is more advisable to use hexadecimals. Note that keys should have enough entropy, and a string is not likely to provide that.
There are several things not entirely correct in the code above:
You should not (ever) use "input".getBytes(). First of all, getBytes() uses a platform specific default character encoding. If you want to use a DES key as a String, decode it with a decoder of hexadecimals (e.g. in Apache Commons codec or Bouncy Castle).
You should use 24 bytes for DESede keys. "input".getBytes() does not return enough bytes.
For DES keys it pays to put the key specification through a KeyFactory if only to make sure that the parity bits are set. They you will be sure that the key is valid.
To get a good amount of key data, use PBKDF2 for passwords or use randomly generated keys.
If an encrypted key store is good enough storage for an encrypted key depends on the use case and the other security measures.

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.

Categories