Reputation: 2734
I am writing the app for Android 1.6.
Can anyone tell me if it is possible to use latest Bouncy Castle provider (version 1.46) instead of old one contained in SDK?
If so, correct instructions will be appreciated.
Upvotes: 7
Views: 9039
Reputation: 6298
In the meanwhile Android has changed the package name and BC can be used in its latest version. But there is still at least one problem:
The provider name "BC" is taken by the old built-in BC version. Adding BC with Security.addProvider(new BouncyCastleProvider(), 0)
as first provider might work in simple cases, but Android Pie introduced a nasty check for the BouncyCastleProvider not allowing several modes, e.g. the X.509 certificate path checking cannot be instantiated and some other algorithms. This problem occurs when BC is added with Security.addProvider
before sun.security.jca.Providers
is first touched. Adding BC to the list of providers is usually required to be able to route indirect calls from other code referring the BC to the new BC version. E.g. the PKCS12 key store is using in its code a call to build a CertificateFactory
using BC.
The check is in sun.security.jca.Providers
and called e.g. from java.security.cert.CertificateFactory
. The code cannot differentiate between Android's included BC version and a newer working version. The hack to overcome this problem is to execute this piece of code early when the app is starting. The code must be executed before sun.security.jca.Providers
is touched, otherwise a static code fragment is already executed reading in the existing crypto providers:
private static final String SUN_PROVIDERS = "sun.security.jca.Providers";
...
// remove BC provider first
Security.removeProvider("BC");
// also remove not sufficient AndroidOpenSSL provider for X.509 - most likely only needed if BouncyCastleJsseProvider is used
Security.removeProvider("AndroidOpenSSL");
// touch the internal Providers class to trigger the static provider loading
// see http://androidxref.com/9.0.0_r3/xref/libcore/ojluni/src/main/java/sun/security/jca/Providers.java#SYSTEM_BOUNCY_CASTLE_PROVIDER
try {
Class.forName(SUN_PROVIDERS);
} catch (ClassNotFoundException e) {
throw new RuntimeException(String.format("%s to patch not found.", SUN_PROVIDERS), e);
}
// insert modern BC as first crypto provider
Security.insertProviderAt(new BouncyCastleProvider(), 0);
Upvotes: 7
Reputation: 2734
Found the issue on google and SpongyCastle. After I added jar and called addProvider(), the app became bigger but could use BC 1.46 features like "Whirlpool" digest.
...the Android platform unfortunately incorporates a cut-down version of Bouncy Castle, which also makes installing an updated version of the libraries difficult due to classloader conflicts.
If you really need the full version of the Bouncy Castle libraries in your Android app, you may find it convenient to use Spongy Castle - a repackage of Bouncy Castle for Android:
Upvotes: 13
Reputation: 42009
You should be able to at least use the lightweight crypto library. Look for the lcrypto-jdk* on the releases page. I confess I don't have a android test environment available to verify any of this. Note that this version of the library does not use the JCE API.
Upvotes: 0