public byte[] unwrap(byte[] in, int inOff, int inLen) throws InvalidCipherTextException { if (forWrapping) { throw new IllegalStateException("not set for unwrapping"); } int n = inLen / 8; if ((n * 8) != inLen) { throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes"); } byte[] block = new byte[inLen - iv.length]; byte[] a = new byte[iv.length]; byte[] buf = new byte[8 + iv.length]; System.arraycopy(in, inOff, a, 0, iv.length); System.arraycopy(in, inOff + iv.length, block, 0, inLen - iv.length); engine.init(false, param); n = n - 1; for (int j = 5; j >= 0; j--) { for (int i = n; i >= 1; i--) { System.arraycopy(a, 0, buf, 0, iv.length); System.arraycopy(block, 8 * (i - 1), buf, iv.length, 8); int t = n * j + i; for (int k = 1; t != 0; k++) { byte v = (byte) t; buf[iv.length - k] ^= v; t >>>= 8; } engine.processBlock(buf, 0, buf, 0); System.arraycopy(buf, 0, a, 0, 8); System.arraycopy(buf, 8, block, 8 * (i - 1), 8); } } if (!Arrays.constantTimeAreEqual(a, iv)) { throw new InvalidCipherTextException("checksum failed"); } return block; }
public byte[] wrap(byte[] in, int inOff, int inLen) { if (!forWrapping) { throw new IllegalStateException("not set for wrapping"); } int n = inLen / 8; if ((n * 8) != inLen) { throw new DataLengthException("wrap data must be a multiple of 8 bytes"); } byte[] block = new byte[inLen + iv.length]; byte[] buf = new byte[8 + iv.length]; System.arraycopy(iv, 0, block, 0, iv.length); System.arraycopy(in, inOff, block, iv.length, inLen); engine.init(true, param); for (int j = 0; j != 6; j++) { for (int i = 1; i <= n; i++) { System.arraycopy(block, 0, buf, 0, iv.length); System.arraycopy(block, 8 * i, buf, iv.length, 8); engine.processBlock(buf, 0, buf, 0); int t = n * j + i; for (int k = 1; t != 0; k++) { byte v = (byte) t; buf[iv.length - k] ^= v; t >>>= 8; } System.arraycopy(buf, 0, block, 0, 8); System.arraycopy(buf, 8, block, 8 * i, 8); } } return block; }
public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException { byte[] k = Arrays.clone(((KeyParameter) params).getKey()); DESedeParameters.setOddParity(k); if (!Arrays.areEqual(((KeyParameter) params).getKey(), k)) { fail("key not odd parity"); } cipher.init(forEncryption, params); }
/** * Create a buffered block cipher that uses Cipher Text Stealing * * @param cipher the underlying block cipher this buffering object wraps. */ public CTSBlockCipher(BlockCipher cipher) { if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher) || (cipher instanceof SICBlockCipher)) { // TODO: This is broken - need to introduce marker interface to differentiate block cipher // primitive from mode? throw new IllegalArgumentException("CTSBlockCipher can only accept ECB, or CBC ciphers"); } this.cipher = cipher; blockSize = cipher.getBlockSize(); buf = new byte[blockSize * 2]; bufOff = 0; }
/** * Create a buffered block cipher with, or without, padding. * * @param cipher the underlying block cipher this buffering object wraps. */ public PaddedBlockCipher(BlockCipher cipher) { this.cipher = cipher; buf = new byte[cipher.getBlockSize()]; bufOff = 0; }
public String getAlgorithmName() { return engine.getAlgorithmName(); }
public void reset() { cipher.reset(); }
public int processBlock(byte[] in, int inOff, byte[] out, int outOff) throws DataLengthException, IllegalStateException { return cipher.processBlock(in, inOff, out, outOff); }
public int getBlockSize() { return cipher.getBlockSize(); }
public String getAlgorithmName() { return cipher.getAlgorithmName(); }
/** * Process the last block in the buffer. * * @param out the array the block currently being held is copied into. * @param outOff the offset at which the copying starts. * @return the number of output bytes copied to out. * @exception DataLengthException if there is insufficient space in out for the output. * @exception IllegalStateException if the underlying cipher is not initialised. * @exception InvalidCipherTextException if cipher text decrypts wrongly (in case the exception * will never get thrown). */ public int doFinal(byte[] out, int outOff) throws DataLengthException, IllegalStateException, InvalidCipherTextException { if (bufOff + outOff > out.length) { throw new DataLengthException("output buffer to small in doFinal"); } int blockSize = cipher.getBlockSize(); int len = bufOff - blockSize; byte[] block = new byte[blockSize]; if (forEncryption) { if (bufOff < blockSize) { throw new DataLengthException("need at least one block of input for CTS"); } cipher.processBlock(buf, 0, block, 0); if (bufOff > blockSize) { for (int i = bufOff; i != buf.length; i++) { buf[i] = block[i - blockSize]; } for (int i = blockSize; i != bufOff; i++) { buf[i] ^= block[i - blockSize]; } if (cipher instanceof CBCBlockCipher) { BlockCipher c = ((CBCBlockCipher) cipher).getUnderlyingCipher(); c.processBlock(buf, blockSize, out, outOff); } else { cipher.processBlock(buf, blockSize, out, outOff); } System.arraycopy(block, 0, out, outOff + blockSize, len); } else { System.arraycopy(block, 0, out, outOff, blockSize); } } else { if (bufOff < blockSize) { throw new DataLengthException("need at least one block of input for CTS"); } byte[] lastBlock = new byte[blockSize]; if (bufOff > blockSize) { if (cipher instanceof CBCBlockCipher) { BlockCipher c = ((CBCBlockCipher) cipher).getUnderlyingCipher(); c.processBlock(buf, 0, block, 0); } else { cipher.processBlock(buf, 0, block, 0); } for (int i = blockSize; i != bufOff; i++) { lastBlock[i - blockSize] = (byte) (block[i - blockSize] ^ buf[i]); } System.arraycopy(buf, blockSize, block, 0, len); cipher.processBlock(block, 0, out, outOff); System.arraycopy(lastBlock, 0, out, outOff + blockSize, len); } else { cipher.processBlock(buf, 0, block, 0); System.arraycopy(block, 0, out, outOff, blockSize); } } int offset = bufOff; reset(); return offset; }