| /* |
| * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. |
| * Please refer to the LICENSE.txt for licensing details. |
| */ |
| package ch.ethz.ssh2.crypto.cipher; |
| |
| /** |
| * CBCMode. |
| * |
| * @author Christian Plattner |
| * @version 2.50, 03/15/10 |
| */ |
| public class CBCMode implements BlockCipher |
| { |
| BlockCipher tc; |
| int blockSize; |
| boolean doEncrypt; |
| |
| byte[] cbc_vector; |
| byte[] tmp_vector; |
| |
| public void init(boolean forEncryption, byte[] key) |
| { |
| } |
| |
| public CBCMode(BlockCipher tc, byte[] iv, boolean doEncrypt) |
| throws IllegalArgumentException |
| { |
| this.tc = tc; |
| this.blockSize = tc.getBlockSize(); |
| this.doEncrypt = doEncrypt; |
| |
| if (this.blockSize != iv.length) |
| throw new IllegalArgumentException("IV must be " + blockSize |
| + " bytes long! (currently " + iv.length + ")"); |
| |
| this.cbc_vector = new byte[blockSize]; |
| this.tmp_vector = new byte[blockSize]; |
| System.arraycopy(iv, 0, cbc_vector, 0, blockSize); |
| } |
| |
| public int getBlockSize() |
| { |
| return blockSize; |
| } |
| |
| private void encryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff) |
| { |
| for (int i = 0; i < blockSize; i++) |
| cbc_vector[i] ^= src[srcoff + i]; |
| |
| tc.transformBlock(cbc_vector, 0, dst, dstoff); |
| |
| System.arraycopy(dst, dstoff, cbc_vector, 0, blockSize); |
| } |
| |
| private void decryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff) |
| { |
| /* Assume the worst, src and dst are overlapping... */ |
| |
| System.arraycopy(src, srcoff, tmp_vector, 0, blockSize); |
| |
| tc.transformBlock(src, srcoff, dst, dstoff); |
| |
| for (int i = 0; i < blockSize; i++) |
| dst[dstoff + i] ^= cbc_vector[i]; |
| |
| /* ...that is why we need a tmp buffer. */ |
| |
| byte[] swap = cbc_vector; |
| cbc_vector = tmp_vector; |
| tmp_vector = swap; |
| } |
| |
| public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) |
| { |
| if (doEncrypt) |
| encryptBlock(src, srcoff, dst, dstoff); |
| else |
| decryptBlock(src, srcoff, dst, dstoff); |
| } |
| } |