Search code examples
cryptographybouncycastle

How do I get started using BouncyCastle?


So after CodingHorror's fun with encryption and the thrashing comments, we are reconsidering doing our own encryption.

In this case, we need to pass some information that identifies a user to a 3rd party service which will then call back to a service on our website with the information plus a hash.

The 2nd service looks up info on that user and then passes it back to the 3rd party service.

We want to encrypt this user information going into the 3rd party service and decrypt it after it comes out. So it is not a long lived encryption.

On the coding horror article, Coda Hale recommended BouncyCastle and a high level abstraction in the library to do the encryption specific to a particular need.

My problem is that the BouncyCastle namespaces are huge and the documentation is non-existant. Can anyone point me to this high level abstraction library? (Or another option besides BouncyCastle?)


Solution

  • High level abstraction? I suppose the highest level abstractions in the Bouncy Castle library would include:

    I am mostly familiar with the Java version of the library. Perhaps this code snippet will offer you a high enough abstraction for your purposes (example is using AES-256 encryption):

    public byte[] encryptAES256(byte[] input, byte[] key) throws InvalidCipherTextException {
        assert key.length == 32; // 32 bytes == 256 bits
        CipherParameters cipherParameters = new KeyParameter(key);
    
        /*
         * A full list of BlockCiphers can be found at http://www.bouncycastle.org/docs/docs1.6/org/bouncycastle/crypto/BlockCipher.html
         */
        BlockCipher blockCipher = new AESEngine();
    
        /*
         * Paddings available (http://www.bouncycastle.org/docs/docs1.6/org/bouncycastle/crypto/paddings/BlockCipherPadding.html):
         *   - ISO10126d2Padding
         *   - ISO7816d4Padding
         *   - PKCS7Padding
         *   - TBCPadding
         *   - X923Padding
         *   - ZeroBytePadding
         */
        BlockCipherPadding blockCipherPadding = new ZeroBytePadding();
    
        BufferedBlockCipher bufferedBlockCipher = new PaddedBufferedBlockCipher(blockCipher, blockCipherPadding);
    
        return encrypt(input, bufferedBlockCipher, cipherParameters);
    }
    
    public byte[] encrypt(byte[] input, BufferedBlockCipher bufferedBlockCipher, CipherParameters cipherParameters) throws InvalidCipherTextException {
        boolean forEncryption = true;
        return process(input, bufferedBlockCipher, cipherParameters, forEncryption);
    }
    
    public byte[] decrypt(byte[] input, BufferedBlockCipher bufferedBlockCipher, CipherParameters cipherParameters) throws InvalidCipherTextException {
        boolean forEncryption = false;
        return process(input, bufferedBlockCipher, cipherParameters, forEncryption);
    }
    
    public byte[] process(byte[] input, BufferedBlockCipher bufferedBlockCipher, CipherParameters cipherParameters, boolean forEncryption) throws InvalidCipherTextException {
        bufferedBlockCipher.init(forEncryption, cipherParameters);
    
        int inputOffset = 0;
        int inputLength = input.length;
    
        int maximumOutputLength = bufferedBlockCipher.getOutputSize(inputLength);
        byte[] output = new byte[maximumOutputLength];
        int outputOffset = 0;
        int outputLength = 0;
    
        int bytesProcessed;
    
        bytesProcessed = bufferedBlockCipher.processBytes(
                input, inputOffset, inputLength,
                output, outputOffset
            );
        outputOffset += bytesProcessed;
        outputLength += bytesProcessed;
    
        bytesProcessed = bufferedBlockCipher.doFinal(output, outputOffset);
        outputOffset += bytesProcessed;
        outputLength += bytesProcessed;
    
        if (outputLength == output.length) {
            return output;
        } else {
            byte[] truncatedOutput = new byte[outputLength];
            System.arraycopy(
                    output, 0,
                    truncatedOutput, 0,
                    outputLength
                );
            return truncatedOutput;
        }
    }
    

    Edit: Whoops, I just read the article you linked to. It sounds like he is talking about even higher level abstractions than I thought (e.g., "send a confidential message"). I am afraid I don't quite understand what he is getting at.