Encryption on Android & BouncyCastle

This article is part 8 of 11 in the series Android Development

If you’ve tried to encrypt stuff in an Android app, you may have noticed that not all phones support all encryption algorithms. And that’s particularly sad when the algorithm in question is AES, the Advanced Encryption Standard. So what do you do? You do what every good Java programmer does, and head for the Bouncy Castle.

Dropping the BouncyCastle libs into your project is about as easy as you might imagine: download the files, and put them in your project’s libs directory. But of course that’s not all there is to it, or I wouldn’t have bothered writing this blogpost. But don’t worry, there’s not that much more to it either.

You see, the BouncyCastle libs are already distributed as part of Android. And that’s where the problem lies: some Android versions come with an older version of the libs that may or may not support the encryption algorithm you intend to use. Others have no such problem. You’ll have to make sure that your app uses the updated version of the library, and to that end, I’m using JarJar, even though that name evokes the most horrifying of nightmares. But why would I do that?

Android includes an optimization step in its builds that tries to remove duplicate classes (amongst other things), via the dexopt command. And when I say duplicate, I mean classes that already exist as part of the OS distribution are stripped from your app’s code. Unfortunately, this is a place where it shows that Android has no adult supervision: classes are considered identical if they have the same fully-qualified name. Anyone who has every tried their hand at a little bit of release management will be able to tell you that a set of uniquely identifying criteria for a class requires a little more data than just a name.

But in this case, JarJar comes to the rescue. Although it’s really meant for unpacking and repacking .JAR files, it can also rename classes/packages while it does it’s job. All we need to do, for better or worse, is to rename the version of the BouncyCastle libs we’re bundling to something that isn’t part of the OS. Luckily, Android’s build files (nowadays) provide for a -pre-compile target that we can abuse for this sort of thing:

  <target name="-pre-compile-check">
    <uptodate property="-pre-compile.not-required"
          targetfile="${external.libs.dir}\ext.jar" >
      <srcfiles dir= "${external.3rdparty.absolute.dir}" includes="**/*.jar"/>
    </uptodate>
  </target>
  <target name="-pre-compile" depends="-pre-compile-check"
        unless="-pre-compile.not-required">
    <taskdef name="jarjar"
        classname="com.tonicsystems.jarjar.JarJarTask"
        classpath="${build.absolute.dir}/jarjar-1.0.jar"
      />
    <jarjar destfile="${external.libs.dir}/ext.jar">
      <zipgroupfileset dir="${external.3rdparty.absolute.dir}"
          includes="*.jar" />
      <rule pattern="org.bouncycastle.**" result="ext.org.bouncycastle.@1" />
    </jarjar>
  </target>

What happens here is that a path defined by the external.3rdparty.absolute.dir property is searched for .JAR files. All files found in that way are unpacked by JarJar, and rebundled into an ext.jar file in the project’s libs directory. The rule element towards the end of the snippet then renames any org.bouncycastly symbol by prepending it with ext. And the whole thing is only done if the third-party .JAR files are newer than the resultant ext.jar. Job done! And if you feel like it, you can add a few more third-party files and rename them with additional rules.

The whole thing does mean that your app will end up being slightly larger. On the other hand, you can now safely distinguish in your code between the Android-included org.bouncycastle symbols and your included ext.org.bouncycastly variant.

There’s one last thing to do, though.

  • Shervin

    THANK YOU, I never would have figured this out.

    • http://www.unwesen.de/ unwesen

      You’re welcome! Yeah, that wasn’t obvious to me either.

  • Sylvain

    Nice post, thank you.

    Anyway, I’m still wondering where in Eclipse to write the ”
    …” part…Sorry if it is a silly question!

    • http://www.unwesen.de/ unwesen

      Thanks!

      No, it’s not a silly question at all – but I’m afraid I can’t provide the answer. I don’t use Eclipse; I always feel it gets in my way of trying to just get things done. Consequently I can’t help with Eclipse.

      The XML snippet belongs in build.xml; what I don’t know is how Eclipse treats that file. Worst case would be that it tries to (re-)generate it.

  • Joe Collins

    Thank you thank you thank you for this.