/** * OnionCoffee - Anonymous Communication through TOR Network * Copyright (C) 2005-2007 RWTH Aachen University, Informatik IV * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package TorJava.Common; import org.bouncycastle.crypto.engines.AESEngine; import org.bouncycastle.crypto.params.KeyParameter; /** * implements AES in Countermode. This special mode turn the block cipher into a * stream cipher. we thus have to create a key stream and take care that no byte * of it gets lost. * * @author Lexi Pimenidis */ public class AESCounterMode { int block_size; byte[] counter; AESEngine aes; byte[] stream_buffer; int stream_next; /** * init the AES-Engine * * @param encrypt * is the key-stream created with encryption or decryption? In * case of doubt: set to TRUE * @param key * the symmetric key for the algorithm */ public AESCounterMode(boolean encrypt, byte[] key) { if (!encrypt) System.err.println("AESCounterMode.<iinit>: WARNING! neve use Counter-mode in TOR with 'decryption'"); // init cipher aes = new AESEngine(); aes.init(encrypt, new KeyParameter(key)); block_size = aes.getBlockSize(); // init counter counter = new byte[block_size]; // JAVA already sets the array to all zeroes // for(int i=0;i<block_size;++i) // counter[i]=0; stream_buffer = new byte[block_size]; stream_next = block_size; } /** * reads the next key of the key stream from the buffer. if the buffer is * not filled, generates the next few bytes in the buffer. * * @return the next byte of the key stream */ private byte nextStreamByte() { ++stream_next; // are there still unused bytes in the buffer? if (stream_next >= block_size) { // fill stream-buffer aes.processBlock(counter, 0, stream_buffer, 0); stream_next = 0; // increase counter int j = block_size - 1; do { ++counter[j]; --j; } while ((counter[j + 1] == 0) && (j >= 0)); } ; return stream_buffer[stream_next]; } /** * encrypts or decrypts an array of arbitrary length. since counter mode is * used as a stream cipher, the cipher is symmetric, i.e. encryption and * decryption is the same. * * @param in * input the plain text, or the cipher text * @return receive the result */ public byte[] processStream(byte[] in) { byte[] out = new byte[in.length]; for (int i = 0; i < in.length; ++i) { byte cipher = nextStreamByte(); out[i] = (byte) (((int) in[i] + 256) ^ ((int) cipher + 256)); } ; return out; } }