Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Bouncy Castle Cipher Algorithms with Android

How can I use the Bouncy Castle provider to implement algorithms such as Serpent and Twofish, because Sun's providers don't implement these at all. I know when multiple providers can implement the same algorithm, you get the implementation form the highest ranking provider which is going to be the Sun provider. If for some reason you want to use the implementation from a specific provider (perhaps because you know it is faster), you can specify the provider in two-arg version of getInstance(). In my case, the Sun provider doesn't implement the algorithms I'm interested in at all.

I have attempted to implement Serpent:

    public static final String FILE_EXTENSION = ".serpent";
    public static final String PROVIDER = "BC"; // Bouncy Castle
    public static final String BLOCK_CIPHER = "Serpent";
    public static final String TRANSFORMATION = "Serpent/CBC/PKCS7Padding";
    public static final String KEY_ALGORITHM = "PBKDF2WithHmacSHA1";
    public static final String PRNG_ALGORITHM = "SHA1PRNG";

    public static final int BLOCK_SIZE = 128; // bits
    public static final int KEY_SIZE = 256; // bits
    public static final int ITERATION_COUNT = 1024; // for PBE

    /** Performs the encryption of a file. */
    public void encrypt(String pathname, char[] password, byte[] salt) {
        // Use bouncy castle as our provider
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

        // Convert the file into a byte array
        byte[] plaintext = fileToBytes(new File(pathname));

        // Generate a 256-bit key
        SecretKey key = generateSecretKey(password,salt);

        // Generate a 128-bit secure random IV
        byte[] iv = generateIV();

        // Setup the cipher and perform the encryption
        Cipher cipher = null;
        byte[] ciphertext = null;
        try {
            cipher = Cipher.getInstance(TRANSFORMATION, PROVIDER);
            cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
            ciphertext = cipher.doFinal(plaintext);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Append the IV to the ciphertext
        byte[] temp = new byte[iv.length+ciphertext.length];
        System.arraycopy(iv, 0, temp, 0, iv.length);
        System.arraycopy(ciphertext, 0, temp, iv.length, ciphertext.length);
        ciphertext = temp;

        // Store the encrypted file in the same directory we found it
        if (Environment.getExternalStorageDirectory().canWrite()) {
            bytesToFile(ciphertext, pathname+FILE_EXTENSION);
            File file = new File(pathname);
            file.delete();
        }       
    }

This however throws a

java.security.NoSuchAlgorithmException: Serpent/CBC/PKCS7Padding

on the line where I call

cipher = Cipher.getInstance(TRANSFORMATION, PROVIDER);

Running

$ adb shell
# logcat

I get tons of

not resolving ambiguous class
not verifying
multiple definitions

errors being outputted. Any idea what can be causing this to happen and how I can resolve the issue?

like image 904
mcorley Avatar asked Jan 20 '23 17:01

mcorley


1 Answers

You probably want Spongy Castle - a repackage I made of Bouncy Castle specifically targeted for Android.

Spongy Castle is a full replacement for the crippled versions of the Bouncy Castle cryptographic libraries which ship with Android. There are a couple of small changes to make it work on Android:

  • all package names have been moved from org.bouncycastle.* to org.spongycastle.* - so no classloader conflicts
  • the Java Security API Provider name is now SC rather than BC

"Spongy Castle saved my ass." - feedback from one happy user :)

like image 108
Roberto Tyley Avatar answered Jan 31 '23 04:01

Roberto Tyley