1 6 21 22 package de.schlichtherle.crypto.modes; 23 24 import de.schlichtherle.crypto.SeekableBlockCipher; 25 26 import org.bouncycastle.crypto.BlockCipher; 27 import org.bouncycastle.crypto.CipherParameters; 28 import org.bouncycastle.crypto.DataLengthException; 29 import org.bouncycastle.crypto.params.ParametersWithIV; 30 31 40 public class SICSeekableBlockCipher implements SeekableBlockCipher { 41 42 private final BlockCipher cipher; 43 private final int blockSize; 44 private final byte[] IV; 45 private final byte[] counter; 46 private long blockCounter; private final byte[] counterOut; 48 49 54 public SICSeekableBlockCipher(BlockCipher c) { 55 this.cipher = c; 56 this.blockSize = cipher.getBlockSize(); 57 this.IV = new byte[blockSize]; 58 this.counter = new byte[blockSize]; 59 this.counterOut = new byte[blockSize]; 60 } 61 62 67 public BlockCipher getUnderlyingCipher() { 68 return cipher; 69 } 70 71 public void init(boolean forEncryption, CipherParameters params) 72 throws IllegalArgumentException { 73 if (params instanceof ParametersWithIV) { 74 ParametersWithIV ivParams = (ParametersWithIV) params; 75 byte[] iv = ivParams.getIV(); 76 System.arraycopy(iv, 0, IV, 0, IV.length); 77 78 reset(); 79 cipher.init(true, ivParams.getParameters()); 80 } 81 } 82 83 public String getAlgorithmName() { 84 return cipher.getAlgorithmName() + "/SIC"; 86 } 87 88 public int getBlockSize() { 89 assert blockSize == cipher.getBlockSize(); 90 return blockSize; 91 } 92 93 public int processBlock( 94 final byte[] in, 95 final int inOff, 96 final byte[] out, 97 final int outOff) 98 throws DataLengthException, IllegalStateException { 99 updateCounter(); 100 cipher.processBlock(counter, 0, counterOut, 0); 101 102 for (int i = blockSize; --i >= 0; ) { 104 out[outOff + i] = (byte)(counterOut[i] ^ in[inOff + i]); 105 } 106 107 blockCounter++; 108 109 return blockSize; 110 } 111 112 private final void updateCounter() { 113 long block = this.blockCounter; 114 for (int i = blockSize; --i >= 0; ) { 115 block += IV[i] & 0xff; 116 counter[i] = (byte) block; 117 block >>>= 8; 118 } 119 } 120 121 public void setBlockCounter(long block) { 122 blockCounter = block; 123 } 124 125 public long getBlockCounter() { 126 return blockCounter; 127 } 128 129 public void reset() { 130 blockCounter = 0; 133 134 cipher.reset(); 135 } 136 } | Popular Tags |