+ public static class CBC implements Cipher {
+ private final Cipher c;
+ private final byte[] iv;
+ private final int blockSize;
+ private final boolean reverse;
+ public CBC(Cipher c, int blockSize, byte[] iv, boolean reverse) {
+ this.c = c;
+ this.blockSize = blockSize;
+ this.iv = iv;
+ this.reverse = reverse;
+ if(iv.length != blockSize) throw new IllegalArgumentException("iv.length != blockSize");
+ }
+
+ public void process(byte[] in, int inp, byte[] out, int outp, int len) {
+ if((len % blockSize) != 0) throw new IllegalArgumentException("buffer must be a multiple of block size");
+ while(len != 0) {
+ if(!reverse) {
+ for(int i=0;i<blockSize;i++) iv[i] ^= in[inp+i]; // mangle the cleartext
+ c.process(iv,0,out,outp,blockSize); // process it
+ System.arraycopy(out,outp,iv,0,blockSize); // copy the block to iv
+ } else {
+ c.process(in,inp,out,outp,blockSize); // process the ciphertext
+ for(int i=0;i<blockSize;i++) out[outp+i] ^= iv[i]; // mangle the cleartext
+ System.arraycopy(in,inp,iv,0,blockSize); // copy the ciphertext to iv
+ }
+ inp+=16; outp+=16; len-=16;
+ }
+ }
+ }
+