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);
Related
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.
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());
I am getting certificates from the keystore based on alias name using the below code,
KeyStore keyStore = KeyStore.getInstance("Windows-MY");
Enumeration aliasesEnum = keyStore.aliases();
while(aliasesEnum.hasMoreElements())
{
aAliasName = (String)aliasesEnum.nextElement();
X509Certificate certificate = (X509Certificate)keyStore.getCertificate(aAliasName);
}
Is there any way to get aliases from the current token instead of getting from keystore?.
Thanks in advance.
It is not possible to get a particular certificate other than knowing the alias.
The best practice would be to have unique alias in your use case, so you will know which certificate you are getting.
If you are storing the Certificate through the KeyStore api, you can do a containsAlias(alias) to see if the alias already exists before you save.
Normally alias names are unique. This is a problem specific to MSCAPI keystore. There are several bug reports (some of them very old) regarding this issue:
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=2162058
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6483657
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8058544
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6672015
Follow the last link, it contains a workaround. You basically have to modify the alias names via reflection API into something unique (see code in link). Not exactly a clean solution, but unfortunately the only way.
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
This question is in the specific context of the Java class java.security.KeyStore and its load(InputStream stream, char[] password) method which can accept null values for password to bypass integrity checking.
What are the risks involved with loading and querying a keystore without checking its integrity? The keystore will be queried for the user's private key which will be used to sign a document for non-repudiation. The certificate queried will be further validated against a copy stored in a database at the time the user registered himself and the (supposedly exact same) cert.
Well the main risk is that anyone who can read the file can also modify it. So someone could replace the file you read with a different keystore that has the same names for the keys but contains a different private key, so you end up signing documents with the wrong private key and none of them will pass verification.
Also, anyone with access to the file gains access to the private key and can sign documents as if they came from your app.