junit java.security.NoSuchAlgorithmException: Cannot find any provider supporting
Solution 1
You need to add the Bouncy Castle provider to the Java runtime. You can see how to install the provider by looking at the Bouncy Castle wiki page. Neither the Blowfish algorithm nor zero padding is supported out of the box by Java installations.
The following runs fine on my box:
Security.addProvider(new BouncyCastleProvider());
byte[] mKeyData = new byte[16];
byte[] mIv = new byte[8];
SecretKeySpec KS = new SecretKeySpec(mKeyData, "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish/CBC/ZeroBytePadding");
cipher.init(Cipher.ENCRYPT_MODE, KS, new IvParameterSpec(mIv));
Make sure that the provider is also available to the test framework when it is run. You'll need to put the bcprov-jdk15on-[version].jar
in the class path of the runtime before you can install the provider.
Solution 2
The problem is with this line:
Cipher cipher = Cipher.getInstance("Blowfish/CBC/ZeroBytePadding");
The algorithm you're requesting is not supported on your system. Any particular reason you want that specific one?
The docs specify the following default implementations:
- AES/CBC/NoPadding (128)
- AES/CBC/PKCS5Padding (128)
- AES/ECB/NoPadding (128)
- AES/ECB/PKCS5Padding (128)
- DES/CBC/NoPadding (56)
- DES/CBC/PKCS5Padding (56)
- DES/ECB/NoPadding (56)
- DES/ECB/PKCS5Padding (56)
- DESede/CBC/NoPadding (168)
- DESede/CBC/PKCS5Padding (168)
- DESede/ECB/NoPadding (168)
- DESede/ECB/PKCS5Padding (168)
- RSA/ECB/PKCS1Padding (1024, 2048)
- RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
- RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
Toon Leijtens
Updated on June 04, 2022Comments
-
Toon Leijtens almost 2 years
I'm using JUnit 4 [C:\eclipse\plugins\org.junit_4.11.0.v201303080030\junit.jar] in combination with Eclipse (MARS, Version: Mars Milestone 3 (4.5.0M3) Build id: 20141113-0320.
I have some tests that test a simple class and which work well. But now arrived at the point where I wanted to test my encryption class, which implements the following encrypt function:
public String encrypt(String data) { try { SecretKeySpec KS = new SecretKeySpec(mKeyData, "Blowfish"); Cipher cipher = Cipher.getInstance("Blowfish/CBC/ZeroBytePadding"); // PKCS5Padding cipher.init(Cipher.ENCRYPT_MODE, KS, new IvParameterSpec(mIv)); return bytesToHex(cipher.doFinal(data.getBytes())); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } return null; }
The Crypto class is not sub classed...
public class Crypto {
So to test this Class and more the encrypt function I have designed the following unit test:
package my.junit4.example; import static org.junit.Assert.*; import org.junit.Test; public class CryptoTest { @Test public void testEncryption() { Crypto myCrypto = new Crypto(); String encodedString = myCrypto.encrypt("Secret"); assertTrue("The decrypted encrypted word should deliver the original string", encodedString.equals(myCrypto.decrypt(encodedString))); } }
This test is failing with a stack trace:
java.security.NoSuchAlgorithmException: Cannot find any provider supporting Blowfish/CBC/ZeroBytePaddingnull at javax.crypto.Cipher.getInstance(Cipher.java:535) at my.junit.example.encrypt(Crypto.java:35) at my.junit.example.CryptoTest.testEncrypt(CryptoTest.java:14) at
This didn't make much sense to me. But being relatively new to JUnit I suspect the issue is with me not understanding how to formulate these tests. The code works well encryption - decryption in my debugger is giving me the desired outcome. But how can I get this to work with JUnit. What obvious mistake I have made?
-
Maarten Bodewes over 9 yearsBeware: the zero byte padding of Bouncy Castle is always applied, i.e. 1..8 bytes for Blowfish, this is different than e.g. the zero byte padding performed by mcrypt (in PHP), i.e. 0..7 bytes. You will need to pad yourself if you want to mimic that kind of padding.
-
Toon Leijtens over 9 yearsThanks for responding Rick. This is an interesting observation. As you can see I had the comment '// PKCS5Padding'. I have changed this to ZeroBytePadding since that would align my code to the kind of padding I have at the PHP end. From the Blowfish implementation I observed that I could use it. But formally you are right it did not feature in the docs. But now for the one-million-dollar-question (not going to give that as a reward by the way)... how on earth does this work in my Java-Java and Java-PHP and only fail when using JUnit? Any ideas there? anyone?
-
Toon Leijtens over 9 yearsHi owlstead, this looks like a useful hint I will look into this BC-prov. It is strange though that only JUnit is giving me a problem. Why do you think only JUnit is not fine with the Blowfish/ZeroBytePadding? and why my Java-Java and Java-PHP are fine? But thank you I will test BCprov anyway, let you know how that improved things.
-
Maarten Bodewes over 9 yearsIt's not JUnit, it is because either the provider is not installed or missing from the classpath in that particular runtime coniguration. You can always test by requesting the list of providers from the
Security
class. Check that you are using the correct JRE, I sometimes find out an entirely different JRE is being used. -
Rick over 9 yearsSee the answer by @owlsetad. He provides some instructions regarding installing the provider. However, this isn't JUnit related. If you simply create a
main
method and try usingencrypt
you will run in to the same problems.