diff options
Diffstat (limited to 'libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java')
-rw-r--r-- | libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java b/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java new file mode 100644 index 000000000..f228baf35 --- /dev/null +++ b/libraries/spongycastle/core/src/main/java/org/spongycastle/crypto/modes/SICBlockCipher.java @@ -0,0 +1,113 @@ +package org.spongycastle.crypto.modes; + +import org.spongycastle.crypto.BlockCipher; +import org.spongycastle.crypto.CipherParameters; +import org.spongycastle.crypto.DataLengthException; +import org.spongycastle.crypto.params.ParametersWithIV; + +/** + * Implements the Segmented Integer Counter (SIC) mode on top of a simple + * block cipher. This mode is also known as CTR mode. + */ +public class SICBlockCipher + implements BlockCipher +{ + private final BlockCipher cipher; + private final int blockSize; + + private byte[] IV; + private byte[] counter; + private byte[] counterOut; + + + /** + * Basic constructor. + * + * @param c the block cipher to be used. + */ + public SICBlockCipher(BlockCipher c) + { + this.cipher = c; + this.blockSize = cipher.getBlockSize(); + this.IV = new byte[blockSize]; + this.counter = new byte[blockSize]; + this.counterOut = new byte[blockSize]; + } + + + /** + * return the underlying block cipher that we are wrapping. + * + * @return the underlying block cipher that we are wrapping. + */ + public BlockCipher getUnderlyingCipher() + { + return cipher; + } + + + public void init( + boolean forEncryption, //ignored by this CTR mode + CipherParameters params) + throws IllegalArgumentException + { + if (params instanceof ParametersWithIV) + { + ParametersWithIV ivParam = (ParametersWithIV)params; + byte[] iv = ivParam.getIV(); + System.arraycopy(iv, 0, IV, 0, IV.length); + + reset(); + + // if null it's an IV changed only. + if (ivParam.getParameters() != null) + { + cipher.init(true, ivParam.getParameters()); + } + } + else + { + throw new IllegalArgumentException("SIC mode requires ParametersWithIV"); + } + } + + public String getAlgorithmName() + { + return cipher.getAlgorithmName() + "/SIC"; + } + + public int getBlockSize() + { + return cipher.getBlockSize(); + } + + + public int processBlock(byte[] in, int inOff, byte[] out, int outOff) + throws DataLengthException, IllegalStateException + { + cipher.processBlock(counter, 0, counterOut, 0); + + // + // XOR the counterOut with the plaintext producing the cipher text + // + for (int i = 0; i < counterOut.length; i++) + { + out[outOff + i] = (byte)(counterOut[i] ^ in[inOff + i]); + } + + // increment counter by 1. + for (int i = counter.length - 1; i >= 0 && ++counter[i] == 0; i--) + { + ; // do nothing - pre-increment and test for 0 in counter does the job. + } + + return counter.length; + } + + + public void reset() + { + System.arraycopy(IV, 0, counter, 0, counter.length); + cipher.reset(); + } +} |