[botan-devel] botan java aes bouncycastle

Timothy Prepscius timprepscius at gmail.com
Thu Jul 26 11:41:16 EDT 2012


I thought I would post one more code set, save some other programmers some time.

If you are coming from bouncy castle on java.  (which you should be to avoid the export requirement thing)

Your java code should probably look something like this, maybe this can be optimized, stick the cipher in the constructor, not an issue for me at the moment, not sure why I was worried len would not be getOutputSize():


package piratecore.crypt;

import java.util.Arrays;

import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.engines.AESEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.BlockCipherPadding;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;

import piratecore.exceptions.CryptoException;

public class CryptorAES extends Cryptor
{
	CipherParameters params;
	
	public CryptorAES (SecretKeySpec secretKey, IvParameterSpec iv)
	{
		// setup cipher parameters with key and IV
	    KeyParameter keyParam = new KeyParameter(secretKey.getEncoded());
	    params = new ParametersWithIV(keyParam, iv.getIV());
	}
	
	@Override
	public byte[] decrypt(byte[] bytes) throws CryptoException
	{
		try
		{
		    BlockCipherPadding padding = new PKCS7Padding();
		    BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
		            new CBCBlockCipher(new AESEngine()), padding);

		    cipher.reset();
		    cipher.init(false, params);		
		    
		    byte[] out = new byte[cipher.getOutputSize(bytes.length)];
		    int len = cipher.processBytes(bytes, 0, bytes.length, out, 0);
		    len += cipher.doFinal(out, len);
		    
		    if (len == out.length)
		    	return out;
		    
		    return Arrays.copyOf(out, len);
		}
		catch (Exception e)
		{
			throw new CryptoException(e);
		}
	}

	@Override
	public byte[] encrypt(byte[] bytes) throws CryptoException
	{
		try
		{
		    BlockCipherPadding padding = new PKCS7Padding();
		    BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
		            new CBCBlockCipher(new AESEngine()), padding);

		    cipher.reset();
		    cipher.init(true, params);		
		    
		    byte[] out = new byte[cipher.getOutputSize(bytes.length)];
		    int len = cipher.processBytes(bytes, 0, bytes.length, out, 0);
		    len += cipher.doFinal(out, len);
		    
		    if (len == out.length)
		    	return out;
		    
		    return Arrays.copyOf(out, len);
		}
		catch (Exception e)
		{
			throw new CryptoException(e);
		}
	}
}


And your botan code should probably look something like this:

(header)

#ifndef __pirate_core_crypt_CryptorAES_h__
#define __pirate_core_crypt_CryptorAES_h__

#include "Cryptor.h"

namespace pirate {
namespace core {
namespace crypt {

class CryptorAES : public Cryptor
{
protected:
	Key key;
	IV iv;
	
public:
	static const IV NullIV;

public:
	CryptorAES (const Key &_key, const IV &_iv) :
		key(_key),
		iv(_iv)
	{
	}
	
	virtual Block encrypt (const Block &bytes) throw (CryptoException);
	virtual Block decrypt (const Block &bytes) throw (CryptoException);
} ;

} // namespace
} // namespace
} // namespace

#endif


(cpp)


#include "CryptorAES.h"
#include <botan/botan.h>
#include <sstream>

using namespace pirate::core::crypt;
using namespace pirate;

using namespace Botan;

const IV CryptorAES::NullIV = filledBlock(16, 0);

Block CryptorAES::encrypt (const Block &block) throw (CryptoException)
{
	try 
	{
		SymmetricKey _key (OctetString((const byte *)key.data(), key.size()));
		InitializationVector _iv (OctetString((const byte *)iv.data(), iv.size()));
		
		Pipe pipe(get_cipher("AES/CBC/PKCS7", _key, _iv, ENCRYPTION));
		pipe.process_msg(block.data(), block.size());
		return fromString(pipe.read_all_as_string());
	}
	catch (std::exception &e)
	{
		throw CryptoException(e.what());
	}
}

Block CryptorAES::decrypt (const Block &block) throw (CryptoException)
{
	try 
	{
		SymmetricKey _key (OctetString((const byte *)key.data(), key.size()));
		InitializationVector _iv (OctetString((const byte *)iv.data(), iv.size()));
		
		Pipe pipe(get_cipher("AES/CBC/PKCS7", _key, _iv, DECRYPTION));
		pipe.process_msg(block.data(), block.size());
		return fromString(pipe.read_all_as_string());
	}
	catch (std::exception &e)
	{
		throw CryptoException(e.what());
	}
}



Thanks again for all the hard work with botan.  I think I have all the functionality I need at the moment.
Keep up the awesome work!

I've actually shown your code to friends a few times in the past.

If you want to read some other awesome code, check out Eberly's stuff:  http://www.geometrictools.com/
It's also perfect.

-tim


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.randombit.net/pipermail/botan-devel/attachments/20120726/07983514/attachment.html>


More information about the botan-devel mailing list