11

I am trying to write a small application using bouncycastle algorithm, from the BouncyCastleProvider.java it says we have to import and add the provider during runtime by the following code

import org.bouncycastle.jce.provider.BouncyCastleProvider; Security.addProvider(new BouncyCastleProvider());

error - The import org.bouncycastle cannot be resolved; during import error - BouncyCastleProvider cannot be resolved to a type; when calling addProvider

I though bouncycastle is not provided with the Android 1.6 SDK, so thought of installing separately. how should i do this? If Bouncycastle is shipped along with SDK, what should i do to avoid these errors? I am using Android 1.6, eclipse-V3.4.0 on winXP . Thanks in advance

satur9nine
  • 13,927
  • 5
  • 80
  • 123
Vamsi
  • 5,853
  • 6
  • 29
  • 36
  • See my answer to another similar question: http://stackoverflow.com/questions/4065379/how-to-create-a-bks-bouncycastle-format-java-keystore-that-contains-a-client-c/10026598#10026598 – Vipul Jan 28 '13 at 19:25
  • This question is still valid in 2021 but most answers here are now incorrect. Look for my updated answer. – satur9nine Feb 23 '21 at 17:43

5 Answers5

35

None of these answers is accurate in 2021 or even several years prior.

Neither using Spongy Castle nor recompiling Bouncy Castle with a different package namespace are necessary since the package name conflicts on Android platform were resolved in Honeycomb (unless you still support pre-honeycomb devices). For details why see: https://github.com/rtyley/spongycastle/issues/34

The correct solution is to include the standard Bouncy Castle libraries in your Android application as follows.

The first step is to include the necessary libraries in your gradle file. You can get standard Bouncy Castle from maven, no need to download and check-in the JARs into your project.

When building with gradle add the following to your dependencies section in your gradle project file:

// See https://www.bouncycastle.org/releasenotes.html for latest revision
implementation 'org.bouncycastle:bcpkix-jdk15to18:1.68'
implementation 'org.bouncycastle:bcprov-jdk15to18:1.68'

Depending on your needs you may not need to actually add the Java security provider from the officially released Bouncy Castle. If you just want to use Bouncy Castle classes directly you may do so now. For example I can write this code that builds an X500Name object without installing the security provider:

X500NameBuilder nameBuilder = new X500NameBuilder();
nameBuilder.addRDN(BCStyle.PSEUDONYM, "xyz");
nameBuilder.addRDN(BCStyle.E, "e@example.com");
X500Name name = nameBuilder.build();

On the other hand if you want to write code that takes advantage of Bouncy Castle via the security provider then you should first replace the built-in Android Bouncy Castle security provider with the standard one since Java does not allow two security providers with the same name. This should be done as early as possible during application startup:

import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class MyApplication extends Application {
    static {
        Security.removeProvider("BC");
        // Confirm that positioning this provider at the end works for your needs!
        Security.addProvider(new BouncyCastleProvider());
    }
}

Note that Java security providers rely heavily on reflection. If you are using obfuscation or shrinking your project then the Bouncy Castle classes will end being culled or renamed inappropriately, to prevent that you need to add the following or similar to proguard.pro file:

-keep class org.bouncycastle.jcajce.provider.** { *; }
-keep class org.bouncycastle.jce.provider.** { *; }

Finally you can write code that will use the standard Bouncy Castle security provider under the hood:

// MD2 hash is not secure, just demonstrating...
MessageDigest md = MessageDigest.getInstance("MD2");
byte[] messageDigest = md.digest(byteData);

Since MD2 isn't provided by any of the Android built-in security providers it will only be found if you've added the Bouncy Castle security provider as described above.

satur9nine
  • 13,927
  • 5
  • 80
  • 123
  • 2
    thanks for the detailed write-up; this is more relevant in 2021 – Vamsi Feb 25 '21 at 09:41
  • Without the provider I get nothing. With the import and provider I get 'Duplicate class org.bouncycastle'...... (HUNDREDS OF THESE ERRORS) – metamonkey Jul 22 '21 at 01:41
  • 2
    @metamonkey Duplicate class indicates you already have Bouncy Castle in your dependency tree somewhere. Bouncy Castle is packaged in a bunch of different ways (for example jdk15to18 and jdk15on) and dependency management tools won't understand these are the same library so they will allow apps to include both. If you are using gradle you can run the dependencies command to show all dependencies and see if Bouncy Castle is being included in multiple forms: https://docs.gradle.org/current/userguide/viewing_debugging_dependencies.html – satur9nine Sep 02 '21 at 01:22
  • 4
    A cleaner/safer way to remove the provider, instead of `Security.removeProvider("BC");`, use `Security.removeProvider(BouncyCastleProvider.PROVIDER_NAME);` – Mendhak Sep 19 '21 at 11:45
7

Or better still use SpongyCastle since the BC shipped with Android is both crippled and old.

Carl Whalley
  • 3,011
  • 8
  • 33
  • 48
  • 8
    Is this still true? Can you be more specific than "old"? Can you define crippled? The SpongyCastle link you include does not explain, either. – Sam Ballantyne Oct 01 '15 at 17:40
  • Any response to Sam's questions? – vojta May 19 '17 at 11:52
  • According to this thread http://bouncy-castle.1462172.n4.nabble.com/Removing-BC-from-Android-td2074914.html "old" is older than 2010, and BouncyCastle has added lots of features and bug fixes since then. You can use "mybc" to build your own custom jars from the current version of BC as a workaround for this issue. Link to my GitHub repo: https://github.com/jbuhacoff/nodejs-mybc-util – jbuhacoff Jul 14 '19 at 05:34
5

You shouldn't need to explicitly add BouncyCastle as a provider. As you say, it's already included with Android.

Here's what I do to get a BouncyCastle AES cipher,

SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC");

If you look in BouncyCastleProvider.java you'll see a reference to PBEWithSHA256And256BitAES-CBC-BC along with a few other ciphers provided by BouncyCastle.

Adrian
  • 2,123
  • 3
  • 18
  • 24
  • 2
    it throws an exception NoSuchAlgorithm – Vamsi Apr 07 '10 at 05:39
  • 1
    Strange. I'm not sure what the problem is. Here's the very code I run, http://upm.svn.sourceforge.net/viewvc/upm/android/trunk/src/com/u17od/upm/crypto/EncryptionService.java?view=markup. Works on Android 1.5 and 2.1. – Adrian Apr 07 '10 at 10:54
  • AES isn't the only encryption algorithm that BouncyCastle provides. BC is necessary for EC encryption, for instance. – Sam Ballantyne Oct 01 '15 at 17:42
3

I'm not familiar with this particular library. However, here are general instructions on how to include a library delivered as a 'jar' file into an Android project.

Download the jar file and put it somewhere on your workstation. You may want to put in the root directory of the project your are installing it in, or maybe in a 'lib' directory in the root.

In Eclipse, select Project->Properties, then select Java Build Path. Then click Add External Jars, navigate to where you put the .jar file, select it and click Open.

Now type or paste some code that attempts to use the classes in the jar. If you are lucky a light bulb icon will appear in the left margin. Clicking on this will prompt you to add the correct Import statement to the top of your .java file.

There are still things that can go wrong at this point. The library may make use of java.* or javax.* content not supplied by Android (it has just a subset of these libraries). Also it may have additional library dependencies of its own. There are other reasons why the .jar may not be compatible with the Android platform.

Note also that it will increase the size of your .apk to accommodate the new content.

Jim Blackler
  • 22,946
  • 12
  • 85
  • 101
  • 1
    i tried to add the bouncy castle jar and tried to getinstance from secretKeyFactory but it throws an exception no such Algorithm – Vamsi Apr 07 '10 at 05:40
  • That sounds like a local exception to that library, not a library inclusion issue. – Jim Blackler Apr 07 '10 at 10:01
1

You would need to compile the BC library under a different name, as it will have a conflict with the built-in BC already in Android - recompile and reference as BC2 or org.BouncyCastle2.x

wolfkabal
  • 86
  • 7