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

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

Related

Why does the Java KeyStore fail at loading an OpenPGP key?

I am willing to spend some amount of time developing yet another license manager for desktop Java application. After some looking around I discovered JCPUID by Iakin that is free to use and should work at most operating systems with native libs that I found here.
My idea is to do two modules: main application that will show popup window with CPU ID and verification text field and key generator app. User will pass CPU ID to keygen owner, who will return verification code (generated with keygen) to user. After user submits correct verification code, license file with that code will be created at filesystem. Every time the application starts up, it will check the existence and correctness of that file and load main application screen after that.
What about code verification, I think the best option will be to use asymmetric cryptography, in particular RSA. The public key will be built-in into application and secret will be built-in into key generator. So CPUID will be passed to key generator owner and then signed with RSA. That signature will be transferred back to user, who will verify its validity with built-in public key.
I generated gpg key pairs using Kleopatra and gpg Linux command line tool itself. Then I tried to sign something using this method:
private byte[] createSignature(byte[] file) {
byte[] signature = null;
try {
java.security.KeyStore keyStoreFile = java.security.KeyStore
.getInstance("PKCS12");
keyStoreFile.load(getClass().getClassLoader().getResourceAsStream("/secret.asc"),
"******".toCharArray());
PrivateKey privateKey = (PrivateKey) keyStoreFile.getKey(
"My Name Here", "******".toCharArray());
Signature dsa = Signature.getInstance("SHA1withRSA");
dsa.initSign(privateKey);
dsa.update(file, 0, file.length);
signature = dsa.sign();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return signature;
}
But the privateKey initialization throws exception:
java.security.InvalidKeyException: Key must not be null
I guess it's because of wrong instance format here:
java.security.KeyStore keyStoreFile = java.security.KeyStore
.getInstance("PKCS12");
I would like to know:
How good is this approach at all?
What difference exists between different OpenPGP key formats and which will be the best to use at this case? How to know the format of existing OpenPGP file?
The Java crypto framework does not support OpenPGP. X.509 keys, for example in the PKCS12 format, are incompatible with OpenPGP -- although they rely on (mostly) the same cryptographic algorithms.
Either use X.509 certificates (you could also create your own CA for this purpose), or rely on an implementation of OpenPGP for Java. In terms of open source libraries, you can choose between the native Java implementation BouncyCastle (MIT license), or interface GnuPG (GPL) through the Java GPGME binding (LGPL).
BouncyCastle is probably the better way to go, as all you need to do is add another Java library, not install another software into the system.

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 can I find the implementation and configuration file of PKCS#11

I'm trying to make a program that reads and displays certificate info from the token (Safenet)
but the problem that I face is :
Exception in thread "main" java.security.ProviderException: Error parsing configuration
so I think the problem is in the Configuration file.
How can I make the configration file and also the implementation file so it works correctly.
Thanks
you can able to resolve the error by correcting nss.cfg in %AS_HOME%\domains\nssdomain\config\
you can follow the instructions in the section "Configure Glassfish to Use the NSS Stores" on this page.
Either follow this link also.
In order to work with PKCS#11 in java you need to provide a config file where you at least specify library and name parameter. In this parameters you must specify the path to native library for the token and a arbitrary identifier. Additionally you can add more parameters but they are optional, you can take a look on java pkcs#11 reference guide. I give you a code sample to instantiate a PKCS#11:
// create configuration
String pkcs11nativeLibrary = "/path_to_native_library/library.so";
String pkcs11ConfigSettings = "name = mySmartCard\n" + "library = " + pkcs11nativeLibrary;
byte[] pkcs11ConfigBytes = pkcs11ConfigSettings.getBytes();
final ByteArrayInputStream confStream = new ByteArrayInputStream(pkcs11ConfigBytes);
// instantiate the provider with your config
SunPKCS11 pkcs11Provider = new SunPKCS11(confStream);
Security.addProvider(pkcs11Provider);
// get the keystore
Char[] pkcs11Password = "your_password".toCharArray();
KeyStore myPKCS11KS = KeyStore.getInstance("PKCS11", pkcs11Provider );
myPKCS11KS.load(null, pkcs11Password);
In the sample I put the pkcs11 password directly, however when you try to load a PKCS#11 from some client you have to get the password dinamically in order to do so you can change you key store instance for something like:
// YourCallbackHandler must implements javax.security.auth.callback.CallbackHandler
KeyStore.CallbackHandlerProtection cbhp = new KeyStore.CallbackHandlerProtection(new YourCallbackHandler());
KeyStore.Builder builder = KeyStore.Builder.newInstance("PKCS11", pkcs11Provider, cbhp);
KeyStore myPKCS11KS = builder.getKeyStore();
Hope this helps,

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

Java Access Token PKCS11 Not found Provider

Hello I'm trying to access the keystore from my smartcard in Java. And I'm using the following code..
I'm using the Pkcs11 implementation of OpenSc http://www.opensc-project.org/opensc
File windows.cnf =
name=dnie
library=C:\WINDOWS\system32\opensc-pkcs11.dll
Java Code =
String configName = "windows.cnf"
String PIN = "####";
Provider p = new sun.security.pkcs11.SunPKCS11(configName);
Security.addProvider(p);
KeyStore keyStore = KeyStore.getInstance("PKCS11", "SunPKCS11-dnie"); =)(=
char[] pin = PIN.toCharArray();
keyStore.load(null, pin);
When the execution goes by the line with =)(= throws me the following exception
java.security.KeyStoreException: PKCS11 not found
at java.security.KeyStore.getInstance(KeyStore.java:635)
at ObtenerDatos.LeerDatos(ObtenerDatos.java:52)
at ObtenerDatos.obtenerNombre(ObtenerDatos.java:19)
at main.main(main.java:27)
Caused by: java.security.NoSuchAlgorithmException: no such algorithm: PKCS11 for provider SunPKCS11-dnie
at sun.security.jca.GetInstance.getService(GetInstance.java:70)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:190)
at java.security.Security.getImpl(Security.java:662)
at java.security.KeyStore.getInstance(KeyStore.java:632)
I think the problem is "SunPKCS11-dnie", but I don't know to put there. I had tried with a lot of combinations...
Anyone can help me...
I was also getting the error as below:
Caused by: java.security.NoSuchAlgorithmException: no such algorithm: PKCS11 for provider SunPKCS11
I am running the application from a jar through bat file.
I bat file I replaced the code : java - jar sign.jar
with code: java -Djava.security.debug=sunpkcs11,pkcs11 -jar SigningUtility.jar
And it solved the issue.
I am not sure the problem is the name. It looks correct. ColinD's suggestion to pass the Provider instance should rule it out as a problem.
I am guessing that the problem is with the PKCS11 support. Like, you don't have a card in your reader, or the native code cannot access the reader. Have you tried using this driver in conjunction with some "known good" software, like Firefox or Thunderbird's security modules?
Why don't you just pass the Provider directly as the second argument to KeyStore.getInstance(String, Provider). In your code you'd just do:
KeyStore keyStore = KeyStore.getInstance("PKCS11", p);
Try the below code:
// Create instance of SunPKCS11 provider
String pkcs11Config = "name=eToken\nlibrary=C:\\Windows\\System32\\eps2003csp11.dll";
java.io.ByteArrayInputStream pkcs11ConfigStream = new java.io.ByteArrayInputStream(pkcs11Config.getBytes());
sun.security.pkcs11.SunPKCS11 providerPKCS11 = new sun.security.pkcs11.SunPKCS11(pkcs11ConfigStream);
java.security.Security.addProvider(providerPKCS11);
// Get provider KeyStore and login with PIN
String pin = "12345678";
java.security.KeyStore keyStore = java.security.KeyStore.getInstance("PKCS11", providerPKCS11);
keyStore.load(null, pin.toCharArray());
it is working fine for me.

Categories