Error with BouncyCastle library 1.59 (NoSuchAlgorithmException) - java

I have updated BouncyCastle library 1.49 to version 1.59 and I am getting the following error:
exception unwrapping private key - java.security.NoSuchAlgorithmException: Cannot find any provider supporting 2.16.840.1.101.3.4.1.42
java.io.IOException: exception unwrapping private key - java.security.NoSuchAlgorithmException: Cannot find any provider supporting 2.16.840.1.101.3.4.1.42
at org.bouncycastle.jcajce.provider.keystore.pkcs12.PKCS12KeyStoreSpi.unwrapKey(Unknown Source)
at org.bouncycastle.jcajce.provider.keystore.pkcs12.PKCS12KeyStoreSpi.engineLoad(Unknown Source)
at java.security.KeyStore.load(KeyStore.java:1226)
The code implemented is as follows:
KeyStore keystore = KeyStore.getInstance("PKCS12", new BouncyCastleProvider());
keystore.load(new ByteArrayInputStream(hexStringToByteArray(privKey)), passphrase.toCharArray());
Enumeration<String> aliases = keystore.aliases();
String keyAlias = "";
while (aliases.hasMoreElements()) {
keyAlias = (String) aliases.nextElement();
}
PrivateKey key = (PrivateKey) keystore.getKey(keyAlias, passphrase.toCharArray());
final Cipher cipher = Cipher.getInstance("RSA/NONE/OAEPWithSHA256AndMGF1Padding", new BouncyCastleProvider());
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] arr = hexStringToByteArray(encriptedPin);
byte[] decryptedTextBytes = cipher.doFinal(arr);
return new String(decryptedTextBytes);
I have updated JCE Policy and it still does not work, as well as the .pk8 certificate.
Has anyone had this problem? Any additional information tell me.
Thanks in advance,
Regards.

Related

Signing file with hardware token

I'm trying to sign some files with SafeNet eToken5110. I have managed to get certificate from it but found out that i can't export PrivateKey. I developed some code to encrypt/decrypt files with common certificate, now my issue is to do the same with eToken. But i can't find any info how to do that.
Any tips? Is there any API for that? (and documentation/examples)
Ok, I've found out how to sign smtx with hardware token, and I hope someone will find it usefull. Need to use Signature class and SunPKCS11 provider
public static byte[] sign(byte[] file) throws Exception {
char password[] = "12345678".toCharArray();
Provider userProvider = new sun.security.pkcs11.SunPKCS11("C:\\ForJava\\eToken.cfg");
KeyStore ks = KeyStore.getInstance("PKCS11", userProvider);
ks.load(null, password);
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Security.addProvider(userProvider);
//Working only with the first alias on the token
String alias = (String)ks.aliases().nextElement();
Signature signature = Signature.getInstance("SHA256withRSA");
PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password);
signature.initSign(privateKey);
signature.update(file);
byte[] result = signature.sign();
//System.out.println("result coding: \n" +new BASE64Encoder().encode(result));
return result;
}
To verify signed data u can use the following code
public static void verify(byte[] sig, byte[] original) throws Exception {
Keystore keystore = initKeystore();
PublicKey key = keystore.getCertificate(getCertAlias()).getPublicKey();
Signature s = Signature.getInstance("SHA256withRSA");
s.initVerify(key);
s.update(original);
if ( ! s.verify(sig)) {
System.out.println("Signature check FAILED");
return;
}
System.out.println("Signature check PASSED");
}
Please add initKeysStore() method into it. It will be more useful then.

Reading certificate error

I am getting the following exception when running my application in a different server. The code works in two different tomcat servers, but on a specific one it doesn't work.
java.lang.NoClassDefFoundError:
org/bouncycastle/asn1/pkcs/PrivateKeyInfo
org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyFactorySpi.engineGeneratePrivate(Unknown
Source) java.security.KeyFactory.generatePrivate(KeyFactory.java:372)
The part of the code when I am getting the error is the following on this line
> pk = kf.generatePrivate(ks);
PrivateKey pk = null;
X509Certificate cert = null;
Security.addProvider(new BouncyCastleProvider());
try{
byte [] key = Base64.decodeBase64(llave.getBytes());
byte [] cer = Base64.decodeBase64(certificado.getBytes());
KeyFactory kf = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(key);
pk = kf.generatePrivate(ks);
pk.getEncoded();
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
InputStream in = new ByteArrayInputStream(cer);
cert = (X509Certificate)certFactory.generateCertificate(in);
DateTime fechaDesde = new DateTime(cert.getNotBefore());
DateTime fechaHasta = new DateTime(cert.getNotAfter());
Does somebody knows why this happens?
java.lang.NoClassDefFoundError This exception is thrown when JVM is unable to find a particular class at runtime which was available during compile time.
This link will help you

Encryption and Decryption with BouncyCastle PKCS7 - CMS in java

I want to use BouncyCastle to encrypt and decrypt with pkcs7 format. I have a hardware token. when I use Keypair in jks file in my hard drive it work fine but when i use key pair in token
its not work. this is my exception:
Exception in thread "main" org.bouncycastle.cms.CMSException: cannot create cipher: No such algorithm: 2.16.840.1.101.3.4.1.2
at org.bouncycastle.cms.jcajce.EnvelopedDataHelper.createCipher(Unknown Source)
at org.bouncycastle.cms.jcajce.EnvelopedDataHelper$1.doInJCE(Unknown Source)
at org.bouncycastle.cms.jcajce.EnvelopedDataHelper.execute(Unknown Source)
at org.bouncycastle.cms.jcajce.EnvelopedDataHelper.createContentCipher(Unknown Source)
at org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient.getRecipientOperator(Unknown Source)
at org.bouncycastle.cms.KeyTransRecipientInformation.getRecipientOperator(Unknown Source)
at org.bouncycastle.cms.RecipientInformation.getContentStream(Unknown Source)
at org.bouncycastle.cms.RecipientInformation.getContent(Unknown Source)
at pktb.PKTB.CmsDecrypt(PKTB.java:288)
at pktb.PKTB.main(PKTB.java:419)
Caused by: java.security.NoSuchAlgorithmException: No such algorithm: 2.16.840.1.101.3.4.1.2
at javax.crypto.Cipher.getInstance(DashoA13*..)
at javax.crypto.Cipher.getInstance(DashoA13*..)
at org.bouncycastle.jcajce.NamedJcaJceHelper.createCipher(Unknown Source)
... 10 more
Java Result: 1
this is my Encryption code:
public byte[] CmsEncrypt(byte[] message, KeyContainer keyContainer) throws NoSuchAlgorithmException, NoSuchProviderException, CMSException, IOException
{
Security.addProvider(new BouncyCastleProvider());
X509Certificate cert = (X509Certificate) keyContainer.certificate;
CMSEnvelopedDataGenerator gen = new CMSEnvelopedDataGenerator();
gen.addKeyTransRecipient(cert);
CMSProcessable data = new CMSProcessableByteArray(message);
CMSEnvelopedData enveloped = gen.generate(data,
CMSEnvelopedDataGenerator.AES128_CBC, "BC");
return enveloped.getEncoded();
}
and this is my decryption code:
public byte[] CmsDecrypt(byte[] cipher, KeyContainer keyContainer) throws CMSException, IOException, NoSuchProviderException
{
Security.addProvider(new BouncyCastleProvider());
byte[] contents=null;
CMSEnvelopedDataParser envelopedDataParser = new CMSEnvelopedDataParser(new ByteArrayInputStream(cipher));
PrivateKey key = keyContainer.privateKey;
X509Certificate cert = keyContainer.certificate;
CMSEnvelopedData enveloped = new CMSEnvelopedData(cipher);
Collection recip = enveloped.getRecipientInfos().getRecipients();
KeyTransRecipientInformation rinfo = (KeyTransRecipientInformation) recip
.iterator().next();
if(keyContainer.provider.equals("Software"))
contents = rinfo.getContent(
new JceKeyTransEnvelopedRecipient(key).setProvider("BC"));
else
contents = rinfo.getContent(
new JceKeyTransEnvelopedRecipient(key).setProvider("SunPKCS11-" + keyContainer.provider));
System.out.println(new String(contents));
return contents;
}
I must say that i use this token provider for cmsSign and cmsVerify and it works fine therefore i think the problem isn't for provider.
You can use PKCS#11 to extract private and public keys from hardware token and then use these extracted public and private keys to encrypt and decrypt data with BouncyCastle PKCS7. which token you are using ? Also I cannot find the code to extract keys from hardware token. Go through the answer in following Link for extracting keys from hardware token. Click here

javax.crypto.BadPaddingException: Data must start with zero

First of all, this is not a duplicate question. I am facing a very strange issue.
Following is what I do.
Case 1:
Generate Key Pair
Encrypt Using Private Key
Decrypt Using Public Key
Everything works fine.
Case 2:
Load Certificate from Mozila Firefox Key Store
Use Certificate A
Encrypt Using Private Key of Certificate A
Decrypt Using Public Keu of Certificate A
Everything works fine.
Case 3:
Load Certificate from Internet Explorer Key Store
Use Certificate A
Encrypt Using Private Key of Certificate A
Decrypt Using Public Keu of Certificate A
At Decrypt time, I get error of BadPadding exception
Following is snippet of each of my codes.
Generating Key Pair
KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
Load Mozilla KeyStore
String strCfg = System.getProperty("user.home")+ File.separator + "jdk6-nss-mozilla.cfg";
Provider p1 = new sun.security.pkcs11.SunPKCS11(strCfg);
Security.addProvider(p1);
keyStore = KeyStore.getInstance("PKCS11");
keyStore.load(null, "password".toCharArray());
Content of Config file
name=NSS
slot=2
library=C:/Program Files/Mozilla Firefox/softokn3.dll
nssArgs="configDir='C:/Documents and Settings/pratik.vohera.DIGI-CORP/Application Data/Mozilla/Firefox/Profiles/t48xsipj.default' certPrefix='' keyPrefix='' secmod='secmod.db' flags=readOnly"
Load IE KeyStore
keyStore = KeyStore.getInstance("Windows-MY");
keyStore.load(null, null);
Get Public and Private key from KeyStore
if (keyStore != null) {
Enumeration<String> enumaration = null;
try {
enumaration = keyStore.aliases();
} catch (KeyStoreException e1) {
e1.printStackTrace();
}
ArrayList<String> certiList;
while (enumaration.hasMoreElements()) {
String aliases = enumaration.nextElement();
certiList = new ArrayList<String>();
certiList.add(aliases);
try {
selectedCert = keyStore.getCertificate(aliases);
selectedpublickey = (RSAPublicKey) selectedCert.getPublicKey();
selectedAlias = aliases;
selectedprivateKey = (PrivateKey) keyStore.getKey(selectedAlias, null);}
} catch (KeyStoreException e) {
e.printStackTrace();
}
}
Encryption
private static String publicEncrypt(String text, Key pubKey) throws Exception {
BASE64Encoder bASE64Encoder = new BASE64Encoder();
byte[] plainText = text.getBytes();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
String encryptedText = bASE64Encoder.encode(cipher.doFinal(plainText));
return encryptedText;
}
Decryption
private static String privateDecrypt(String text, Key priKey)throws Exception {
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] encryptText = base64Decoder.decodeBuffer(text);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, priKey);
String decryptedString = new String(cipher.doFinal(encryptText));
return decryptedString;
}
Exception Stacktrace
javax.crypto.BadPaddingException: Data must start with zero
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at test.testclass.privateDecrypt(testclass.java:198)
at test.testclass.test(testclass.java:137)
at test.testclass.main(testclass.java:120)
I have been working on this for a long time. This is very important. Do let me know if any further information is required.
In the third case, the problem is: You try to encrypt using the private key and decrypt using the public key which is wrong. You should always decrypt using the private key.

How to store and load keys using java.security.KeyStore class

After creating secret keys, how do I store them using the Keystore class' methods and how do I load the keys?
Storing:
KeyStore ks = KeyStore.getInstance("JKS");
ks.setKeyEntry("keyAlias", key, passwordForKeyCharArray, certChain);
OutputStream writeStream = new FileOutputStream(filePathToStore);
ks.store(writeStream, keystorePasswordCharArray);
writeStream.close();
Note thet certChain might be null, unless you are passing PrivateKey
Loading:
KeyStore ks = KeyStore.getInstance("JKS");
InputStream readStream = new FileInputStream(filePathToStore);
ks.load(readStream, keystorePasswordCharArray);
Key key = ks.getKey("keyAlias", passwordForKeyCharArray);
readStream.close();
Read the javadocs
EDIT:
Note that if you are storing a SecretKey or using any part of the SunJCE provider (Java Cryptography Extension), you will need to set your KeyStore type to JCEKS.
KeyStore ks = KeyStore.getInstance("JCEKS");
I had a situation where I didn't know the key alias name, but I knew there was only one key was there in the keystore. I used the following code to load the key (after loading the keystore as shown above):
Enumeration<String> aliases = keyStore.aliases();
String alias = aliases.nextElement();
KeyStore.PrivateKeyEntry keyEnt = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias,
new KeyStore.PasswordProtection(keystorePass.toCharArray()));
PrivateKey privateKey = keyEnt.getPrivateKey();
I have added a post on my blog with details of how to load the private key, public key and how to use them.

Categories

Resources