The Bouncy Castle Crypto API

An additional feature that is currently unavailable in J2ME CLDC is the Java Cryptography Extension (JCE). The JCE is a set of packages providing a framework for encryption, key generation and key agreement, and Message Authentication Code (MAC) algorithms. It supports encryption for symmetric, asymmetric, block, and stream ciphers.

The Bouncy Castle Crypto API, which is available from http://www.bouncycastle.org, supports the following features:

  • A clean-room implementation of the JCE 1.2.1

  • A lightweight cryptography API in Java

  • A provider for the JCE and JCA

  • Generators for Version 1 and Version 3 X.509 certificates

Because a complete implementation of the JCE is too big for the J2ME CLDC platform, we will focus on the lightweight API available for the J2ME CLDC platform. It is specially developed for circumstances in which the complete API and the integration of the JCE aren't required.

The lightweight API provides the following subset of the JCE:

  • AsymmetricBlockCipher

  • BlockCipher

  • BufferedBlockCipher

  • BufferedAsymmetricBlockCipher

  • BufferedStreamCipher

  • Digest

  • KeyAgreement

  • Mac

  • PBE

  • StreamCipher

For example, these tools let you cipher a password that needs to be transferred over a network for user authorization. Listing 10.9 shows an example of how a String can be ciphered using a private key with the Blowfish encryption algorithm that is part of the Bouncy Castle Crypto API. Encryption and decryption are performed entirely in the methods encryptText() and decryptText() in order to providing an easy mechanism for adopting to your own implementations. Figure 10.4 shows the original and the encrypted text in the MIDlet.

Figure 10.4. The Blowfish MIDlet showing decrypted text on the left and the encrypted on the right.


Listing 10.9. BlowfishMidp.java—The BlowfishMidp Sample Source Code
import java.io.*;
import java.lang.*;

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

import org.bouncycastle.util.encoders.*;

import org.bouncycastle.crypto.*;
import org.bouncycastle.crypto.engines.*;
import org.bouncycastle.crypto.modes.*;
import org.bouncycastle.crypto.params.*;

public class BlowFishMidp extends MIDlet implements CommandListener {

    private Display display = null;
    private boolean encrypted = false;

    private String key = "abcdefghijklmnopqrstuvwxyz0123456789";
    private String text = "J2ME Crypto";

    private BufferedBlockCipher bfCipher = null;

    private Form mainForm = null;

    private StringItem statusItem = new StringItem ("Status = ", "init");
    private StringItem keyItem = new StringItem ("Key = ", key);
    private StringItem textItem = new StringItem ("Text = ", text);

    public static Command encrypt = new Command ("Encrypt", Command.SCREEN, 1);
    public static Command decrypt = new Command ("Decrypt", Command.SCREEN, 2);


    public BlowFishMidp() throws CryptoException {

        mainForm = new Form("BlowfishMidp");

        mainForm.append (statusItem);
        mainForm.append (textItem);
        mainForm.append (keyItem);

        mainForm.addCommand (encrypt);
        mainForm.addCommand (decrypt);
        mainForm.setCommandListener (this);
    }


    public void startApp() {
        display = Display.getDisplay(this);
        display.setCurrent(mainForm);
    }


    public void pauseApp() {}


    public void destroyApp(boolean unconditional) {}


    public void commandAction (Command c, Displayable d) {
        if (c == encrypt && !encrypted) {
            try {
                textItem.setText (encryptText(key, text));
                statusItem.setText ("encrypted.");
                encrypted = true;
            }
            catch (CryptoException ce) {
                throw new RuntimeException (ce.toString());
            }
        }
        else if (c == decrypt && encrypted) {
            try {
                textItem.setText (decryptText(key, textItem.getText ()));
                statusItem.setText ("decrypted.");
                encrypted = false;
            }
            catch (CryptoException ce) {
                throw new RuntimeException (ce.toString());
            }
        }
    }


    private String encryptText (String key, String text)
        throws CryptoException {

        byte[] keyBytes= Hex.decode(key.getBytes());
        byte[] ptBytes = text.getBytes();
        bfCipher = new PaddedBlockCipher
            (new CBCBlockCipher
                (new BlowfishEngine()));

        bfCipher.init(true, new KeyParameter(keyBytes));
        byte[] result = new byte[bfCipher.getOutputSize(ptBytes.length)];
        int len = bfCipher.processBytes(ptBytes, 0, ptBytes.length, result, 0);
        bfCipher.doFinal(result, len);

        return new String(Hex.encode(result));
    }


    private String decryptText(String key, String cipherText)
        throws CryptoException {

        byte[] keyBytes = Hex.decode(key.getBytes());
        byte[] textBytes = Hex.decode(cipherText.getBytes());

        bfCipher.init(false, new KeyParameter(keyBytes));

        byte[] result = new byte[bfCipher.getOutputSize(textBytes.length)];
        int len = bfCipher.processBytes(textBytes, 0,
                                        textBytes.length, result, 0);
        bfCipher.doFinal(result, len);
        return new String(result).trim();
    }
}

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset