Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id B79FD200B29 for ; Thu, 30 Jun 2016 18:04:00 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id B5E7D160A06; Thu, 30 Jun 2016 16:04:00 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 6550C160A52 for ; Thu, 30 Jun 2016 18:03:58 +0200 (CEST) Received: (qmail 97035 invoked by uid 500); 30 Jun 2016 16:03:57 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 96728 invoked by uid 99); 30 Jun 2016 16:03:57 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 30 Jun 2016 16:03:57 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 170BDE00DB; Thu, 30 Jun 2016 16:03:57 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ggregory@apache.org To: commits@commons.apache.org Date: Thu, 30 Jun 2016 16:03:58 -0000 Message-Id: <19049fd6e2934c209b32a4dcac107e9b@git.apache.org> In-Reply-To: <12513ea1dc4041678ea851d04e5cc31d@git.apache.org> References: <12513ea1dc4041678ea851d04e5cc31d@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [2/2] commons-crypto git commit: [CRYPTO-94] Consistently camel-case type names: Ctr*. archived-at: Thu, 30 Jun 2016 16:04:00 -0000 [CRYPTO-94] Consistently camel-case type names: Ctr*. Project: http://git-wip-us.apache.org/repos/asf/commons-crypto/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-crypto/commit/ba14d801 Tree: http://git-wip-us.apache.org/repos/asf/commons-crypto/tree/ba14d801 Diff: http://git-wip-us.apache.org/repos/asf/commons-crypto/diff/ba14d801 Branch: refs/heads/master Commit: ba14d801935decdb9399d6b2f038e0d1a71609e1 Parents: 294d73b Author: Gary Gregory Authored: Thu Jun 30 09:03:53 2016 -0700 Committer: Gary Gregory Committed: Thu Jun 30 09:03:53 2016 -0700 ---------------------------------------------------------------------- .../crypto/stream/CTRCryptoInputStream.java | 672 ------------------- .../crypto/stream/CTRCryptoOutputStream.java | 384 ----------- .../crypto/stream/CryptoInputStream.java | 2 +- .../crypto/stream/CtrCryptoInputStream.java | 672 +++++++++++++++++++ .../crypto/stream/CtrCryptoOutputStream.java | 384 +++++++++++ .../stream/PositionedCryptoInputStream.java | 4 +- .../crypto/stream/CTRCryptoStreamTest.java | 55 -- .../stream/CTRNoPaddingCipherStreamTest.java | 29 - .../crypto/stream/CtrCryptoStreamTest.java | 55 ++ .../stream/CtrNoPaddingCipherStreamTest.java | 29 + 10 files changed, 1143 insertions(+), 1143 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/ba14d801/src/main/java/org/apache/commons/crypto/stream/CTRCryptoInputStream.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/stream/CTRCryptoInputStream.java b/src/main/java/org/apache/commons/crypto/stream/CTRCryptoInputStream.java deleted file mode 100644 index 6c6dacc..0000000 --- a/src/main/java/org/apache/commons/crypto/stream/CTRCryptoInputStream.java +++ /dev/null @@ -1,672 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.crypto.stream; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.channels.ReadableByteChannel; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.util.Properties; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.ShortBufferException; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -import org.apache.commons.crypto.cipher.CryptoCipher; -import org.apache.commons.crypto.stream.input.ChannelInput; -import org.apache.commons.crypto.stream.input.Input; -import org.apache.commons.crypto.stream.input.StreamInput; -import org.apache.commons.crypto.utils.Utils; - -/** - *

- * CTRCryptoInputStream decrypts data. AES CTR mode is required in order to - * ensure that the plain text and cipher text have a 1:1 mapping. CTR crypto - * stream has stream characteristic which is useful for implement features like - * random seek. The decryption is buffer based. The key points of the decryption - * are (1) calculating the counter and (2) padding through stream position: - *

- *

- * counter = base + pos/(algorithm blocksize); padding = pos%(algorithm - * blocksize); - *

- * The underlying stream offset is maintained as state. It is not thread-safe. - */ -public class CTRCryptoInputStream extends CryptoInputStream { - /** - * Underlying stream offset - */ - private long streamOffset = 0; - - /** - * The initial IV. - */ - private final byte[] initIV; - - /** - * Initialization vector for the cipher. - */ - private byte[] iv; - - /** - * Padding = pos%(algorithm blocksize); Padding is put into - * {@link #inBuffer} before any other data goes in. The purpose of padding - * is to put the input data at proper position. - */ - private byte padding; - - /** - * Flag to mark whether the cipher has been reset - */ - private boolean cipherReset = false; - - /** - * For AES, the algorithm block is fixed size of 128 bits. - * - * @see - * http://en.wikipedia.org/wiki/Advanced_Encryption_Standard - */ - private static final int AES_BLOCK_SIZE = 16; - - /** - * Constructs a {@link CTRCryptoInputStream}. - * - * @param props The Properties class represents a set of - * properties. - * @param in the input stream. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @throws IOException if an I/O error occurs. - */ - public CTRCryptoInputStream(Properties props, InputStream in, byte[] key, - byte[] iv) throws IOException { - this(props, in, key, iv, 0); - } - - /** - * Constructs a {@link CTRCryptoInputStream}. - * - * @param props The Properties class represents a set of - * properties. - * @param in the ReadableByteChannel instance. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @throws IOException if an I/O error occurs. - */ - public CTRCryptoInputStream(Properties props, ReadableByteChannel in, - byte[] key, byte[] iv) throws IOException { - this(props, in, key, iv, 0); - } - - /** - * Constructs a {@link CTRCryptoInputStream}. - * - * @param in the input stream. - * @param cipher the CryptoCipher instance. - * @param bufferSize the bufferSize. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @throws IOException if an I/O error occurs. - */ - protected CTRCryptoInputStream(InputStream in, CryptoCipher cipher, - int bufferSize, byte[] key, byte[] iv) throws IOException { - this(in, cipher, bufferSize, key, iv, 0); - } - - /** - * Constructs a {@link CTRCryptoInputStream}. - * - * @param in the ReadableByteChannel instance. - * @param cipher the cipher instance. - * @param bufferSize the bufferSize. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @throws IOException if an I/O error occurs. - */ - protected CTRCryptoInputStream(ReadableByteChannel in, CryptoCipher cipher, - int bufferSize, byte[] key, byte[] iv) throws IOException { - this(in, cipher, bufferSize, key, iv, 0); - } - - /** - * Constructs a {@link CTRCryptoInputStream}. - * - * @param input the input data. - * @param cipher the CryptoCipher instance. - * @param bufferSize the bufferSize. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @throws IOException if an I/O error occurs. - */ - protected CTRCryptoInputStream(Input input, CryptoCipher cipher, - int bufferSize, byte[] key, byte[] iv) throws IOException { - this(input, cipher, bufferSize, key, iv, 0); - } - - /** - * Constructs a {@link CTRCryptoInputStream}. - * - * @param props The Properties class represents a set of - * properties. - * @param in the InputStream instance. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @param streamOffset the start offset in the stream. - * @throws IOException if an I/O error occurs. - */ - public CTRCryptoInputStream(Properties props, InputStream in, byte[] key, - byte[] iv, long streamOffset) throws IOException { - this(in, Utils.getCipherInstance( - "AES/CTR/NoPadding", props), - CryptoInputStream.getBufferSize(props), key, iv, streamOffset); - } - - /** - * Constructs a {@link CTRCryptoInputStream}. - * - * @param props The Properties class represents a set of - * properties. - * @param in the ReadableByteChannel instance. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @param streamOffset the start offset in the stream. - * @throws IOException if an I/O error occurs. - */ - public CTRCryptoInputStream(Properties props, ReadableByteChannel in, - byte[] key, byte[] iv, long streamOffset) throws IOException { - this(in, Utils.getCipherInstance( - "AES/CTR/NoPadding", props), - CryptoInputStream.getBufferSize(props), key, iv, streamOffset); - } - - /** - * Constructs a {@link CTRCryptoInputStream}. - * - * @param in the InputStream instance. - * @param cipher the CryptoCipher instance. - * @param bufferSize the bufferSize. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @param streamOffset the start offset in the stream. - * @throws IOException if an I/O error occurs. - */ - protected CTRCryptoInputStream(InputStream in, CryptoCipher cipher, - int bufferSize, byte[] key, byte[] iv, long streamOffset) - throws IOException { - this(new StreamInput(in, bufferSize), cipher, bufferSize, key, iv, - streamOffset); - } - - /** - * Constructs a {@link CTRCryptoInputStream}. - * - * @param in the ReadableByteChannel instance. - * @param cipher the CryptoCipher instance. - * @param bufferSize the bufferSize. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @param streamOffset the start offset in the stream. - * @throws IOException if an I/O error occurs. - */ - protected CTRCryptoInputStream(ReadableByteChannel in, CryptoCipher cipher, - int bufferSize, byte[] key, byte[] iv, long streamOffset) - throws IOException { - this(new ChannelInput(in), cipher, bufferSize, key, iv, streamOffset); - } - - /** - * Constructs a {@link CTRCryptoInputStream}. - * - * @param input the input data. - * @param cipher the CryptoCipher instance. - * @param bufferSize the bufferSize. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @param streamOffset the start offset in the stream. - * @throws IOException if an I/O error occurs. - */ - protected CTRCryptoInputStream(Input input, CryptoCipher cipher, - int bufferSize, byte[] key, byte[] iv, long streamOffset) - throws IOException { - super(input, cipher, bufferSize, new SecretKeySpec(key, "AES"), - new IvParameterSpec(iv)); - - this.initIV = iv.clone(); - this.iv = iv.clone(); - - CryptoInputStream.checkStreamCipher(cipher); - - resetStreamOffset(streamOffset); - } - - /** - * Overrides the {@link CryptoInputStream#skip(long)}. Skips over and - * discards n bytes of data from this input stream. - * - * @param n the number of bytes to be skipped. - * @return the actual number of bytes skipped. - * @throws IOException if an I/O error occurs. - */ - @Override - public long skip(long n) throws IOException { - Utils.checkArgument(n >= 0, "Negative skip length."); - checkStream(); - - if (n == 0) { - return 0; - } else if (n <= outBuffer.remaining()) { - int pos = outBuffer.position() + (int) n; - outBuffer.position(pos); - return n; - } else { - /* - * Subtract outBuffer.remaining() to see how many bytes we need to - * skip in the underlying stream. Add outBuffer.remaining() to the - * actual number of skipped bytes in the underlying stream to get - * the number of skipped bytes from the user's point of view. - */ - n -= outBuffer.remaining(); - long skipped = input.skip(n); - if (skipped < 0) { - skipped = 0; - } - long pos = streamOffset + skipped; - skipped += outBuffer.remaining(); - resetStreamOffset(pos); - return skipped; - } - } - - /** - * Overrides the {@link CTRCryptoInputStream#read(ByteBuffer)}. Reads a - * sequence of bytes from this channel into the given buffer. - * - * @param buf The buffer into which bytes are to be transferred. - * @return The number of bytes read, possibly zero, or -1 if the - * channel has reached end-of-stream. - * @throws IOException if an I/O error occurs. - */ - @Override - public int read(ByteBuffer buf) throws IOException { - checkStream(); - int unread = outBuffer.remaining(); - if (unread <= 0) { // Fill the unread decrypted data buffer firstly - final int n = input.read(inBuffer); - if (n <= 0) { - return n; - } - - streamOffset += n; // Read n bytes - if (buf.isDirect() && buf.remaining() >= inBuffer.position() - && padding == 0) { - // Use buf as the output buffer directly - decryptInPlace(buf); - padding = postDecryption(streamOffset); - return n; - } - // Use outBuffer as the output buffer - decrypt(); - padding = postDecryption(streamOffset); - } - - // Copy decrypted data from outBuffer to buf - unread = outBuffer.remaining(); - final int toRead = buf.remaining(); - if (toRead <= unread) { - final int limit = outBuffer.limit(); - outBuffer.limit(outBuffer.position() + toRead); - buf.put(outBuffer); - outBuffer.limit(limit); - return toRead; - } - buf.put(outBuffer); - return unread; - } - - /** - * Seeks the stream to a specific position relative to start of the under - * layer stream. - * - * @param position the given position in the data. - * @throws IOException if an I/O error occurs. - */ - public void seek(long position) throws IOException { - Utils.checkArgument(position >= 0, "Cannot seek to negative offset."); - checkStream(); - /* - * If data of target pos in the underlying stream has already been read - * and decrypted in outBuffer, we just need to re-position outBuffer. - */ - if (position >= getStreamPosition() && position <= getStreamOffset()) { - int forward = (int) (position - getStreamPosition()); - if (forward > 0) { - outBuffer.position(outBuffer.position() + forward); - } - } else { - input.seek(position); - resetStreamOffset(position); - } - } - - /** - * Gets the offset of the stream. - * - * @return the stream offset. - */ - protected long getStreamOffset() { - return streamOffset; - } - - /** - * Sets the offset of stream. - * - * @param streamOffset the stream offset. - */ - protected void setStreamOffset(long streamOffset) { - this.streamOffset = streamOffset; - } - - /** - * Gets the position of the stream. - * - * @return the position of the stream. - */ - protected long getStreamPosition() { - return streamOffset - outBuffer.remaining(); - } - - /** - * Decrypts more data by reading the under layer stream. The decrypted data - * will be put in the output buffer. - * - * @return The number of decrypted data. -1 if end of the decrypted stream. - * @throws IOException if an I/O error occurs. - */ - @Override - protected int decryptMore() throws IOException { - int n = input.read(inBuffer); - if (n <= 0) { - return n; - } - - streamOffset += n; // Read n bytes - decrypt(); - padding = postDecryption(streamOffset); - return outBuffer.remaining(); - } - - /** - * Does the decryption using inBuffer as input and outBuffer as output. Upon - * return, inBuffer is cleared; the decrypted data starts at - * outBuffer.position() and ends at outBuffer.limit(). - * - * @throws IOException if an I/O error occurs. - */ - @Override - protected void decrypt() throws IOException { - Utils.checkState(inBuffer.position() >= padding); - if (inBuffer.position() == padding) { - // There is no real data in inBuffer. - return; - } - - inBuffer.flip(); - outBuffer.clear(); - decryptBuffer(outBuffer); - inBuffer.clear(); - outBuffer.flip(); - - if (padding > 0) { - /* - * The plain text and cipher text have a 1:1 mapping, they start at - * the same position. - */ - outBuffer.position(padding); - } - } - - /** - * Does the decryption using inBuffer as input and buf as output. Upon - * return, inBuffer is cleared; the buf's position will be equal to - * p + n where p is the position - * before decryption, n is the number of bytes decrypted. The buf's - * limit will not have changed. - * - * @param buf The buffer into which bytes are to be transferred. - * @throws IOException if an I/O error occurs. - */ - protected void decryptInPlace(ByteBuffer buf) throws IOException { - Utils.checkState(inBuffer.position() >= padding); - Utils.checkState(buf.isDirect()); - Utils.checkState(buf.remaining() >= inBuffer.position()); - Utils.checkState(padding == 0); - - if (inBuffer.position() == padding) { - // There is no real data in inBuffer. - return; - } - inBuffer.flip(); - decryptBuffer(buf); - inBuffer.clear(); - } - - /** - * Decrypts all data in buf: total n bytes from given start position. Output - * is also buf and same start position. buf.position() and buf.limit() - * should be unchanged after decryption. - * - * @param buf The buffer into which bytes are to be transferred. - * @param offset the start offset in the data. - * @param len the the maximum number of decrypted data bytes to read. - * @throws IOException if an I/O error occurs. - */ - protected void decrypt(ByteBuffer buf, int offset, int len) - throws IOException { - final int pos = buf.position(); - final int limit = buf.limit(); - int n = 0; - while (n < len) { - buf.position(offset + n); - buf.limit(offset + n + Math.min(len - n, inBuffer.remaining())); - inBuffer.put(buf); - // Do decryption - try { - decrypt(); - buf.position(offset + n); - buf.limit(limit); - n += outBuffer.remaining(); - buf.put(outBuffer); - } finally { - padding = postDecryption(streamOffset - (len - n)); - } - } - buf.position(pos); - } - - /** - * This method is executed immediately after decryption. Checks whether - * cipher should be updated and recalculate padding if needed. - * - * @param position the given position in the data.. - * @return the byte. - * @throws IOException if an I/O error occurs. - */ - protected byte postDecryption(long position) throws IOException { - byte padding = 0; - if (cipherReset) { - /* - * This code is generally not executed since the cipher usually - * maintains cipher context (e.g. the counter) internally. However, - * some implementations can't maintain context so a re-init is - * necessary after each decryption call. - */ - resetCipher(position); - padding = getPadding(position); - inBuffer.position(padding); - } - return padding; - } - - /** - * Gets the initialization vector. - * - * @return the initIV. - */ - protected byte[] getInitIV() { - return initIV; - } - - /** - * Gets the counter for input stream position. - * - * @param position the given position in the data. - * @return the counter for input stream position. - */ - protected long getCounter(long position) { - return position / cipher.getBlockSize(); - } - - /** - * Gets the padding for input stream position. - * - * @param position the given position in the data. - * @return the padding for input stream position. - */ - protected byte getPadding(long position) { - return (byte) (position % cipher.getBlockSize()); - } - - /** - * Overrides the {@link CTRCryptoInputStream#initCipher()}. Initializes the - * cipher. - */ - @Override - protected void initCipher() { - // Do nothing for initCipher - // Will reset the cipher when reset the stream offset - } - - /** - * Calculates the counter and iv, resets the cipher. - * - * @param position the given position in the data. - * @throws IOException if an I/O error occurs. - */ - protected void resetCipher(long position) throws IOException { - final long counter = getCounter(position); - CTRCryptoInputStream.calculateIV(initIV, counter, iv); - try { - cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); - } catch (InvalidKeyException e) { - throw new IOException(e); - } catch (InvalidAlgorithmParameterException e) { - throw new IOException(e); - } - cipherReset = false; - } - - /** - * Resets the underlying stream offset; clear {@link #inBuffer} and - * {@link #outBuffer}. This Typically happens during {@link #skip(long)}. - * - * @param offset the offset of the stream. - * @throws IOException if an I/O error occurs. - */ - protected void resetStreamOffset(long offset) throws IOException { - streamOffset = offset; - inBuffer.clear(); - outBuffer.clear(); - outBuffer.limit(0); - resetCipher(offset); - padding = getPadding(offset); - inBuffer.position(padding); // Set proper position for input data. - } - - /** - * Does the decryption using out as output. - * - * @param out the output ByteBuffer. - * @throws IOException if an I/O error occurs. - */ - protected void decryptBuffer(ByteBuffer out) throws IOException { - int inputSize = inBuffer.remaining(); - try { - int n = cipher.update(inBuffer, out); - if (n < inputSize) { - /** - * Typically code will not get here. CryptoCipher#update will - * consume all input data and put result in outBuffer. - * CryptoCipher#doFinal will reset the cipher context. - */ - cipher.doFinal(inBuffer, out); - cipherReset = true; - } - } catch (ShortBufferException e) { - throw new IOException(e); - } catch (IllegalBlockSizeException e) { - throw new IOException(e); - } catch (BadPaddingException e) { - throw new IOException(e); - } - } - - /** - *

- * This method is only for Counter (CTR) mode. Generally the CryptoCipher - * calculates the IV and maintain encryption context internally.For example - * a Cipher will maintain its encryption context internally when we do - * encryption/decryption using the CryptoCipher#update interface. - *

- *

- * Encryption/Decryption is not always on the entire file. For example, in - * Hadoop, a node may only decrypt a portion of a file (i.e. a split). In - * these situations, the counter is derived from the file position. - *

- * The IV can be calculated by combining the initial IV and the counter with - * a lossless operation (concatenation, addition, or XOR). - * - * @see - * http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29 - * - * @param initIV initial IV - * @param counter counter for input stream position - * @param IV the IV for input stream position - */ - static void calculateIV(byte[] initIV, long counter, byte[] IV) { - Utils.checkArgument(initIV.length == CTRCryptoInputStream.AES_BLOCK_SIZE); - Utils.checkArgument(IV.length == CTRCryptoInputStream.AES_BLOCK_SIZE); - - int i = IV.length; // IV length - int j = 0; // counter bytes index - int sum = 0; - while (i-- > 0) { - // (sum >>> Byte.SIZE) is the carry for addition - sum = (initIV[i] & 0xff) + (sum >>> Byte.SIZE); // NOPMD - if (j++ < 8) { // Big-endian, and long is 8 bytes length - sum += (byte) counter & 0xff; - counter >>>= 8; - } - IV[i] = (byte) sum; - } - } -} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/ba14d801/src/main/java/org/apache/commons/crypto/stream/CTRCryptoOutputStream.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/stream/CTRCryptoOutputStream.java b/src/main/java/org/apache/commons/crypto/stream/CTRCryptoOutputStream.java deleted file mode 100644 index 6f9ea6b..0000000 --- a/src/main/java/org/apache/commons/crypto/stream/CTRCryptoOutputStream.java +++ /dev/null @@ -1,384 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.crypto.stream; - -import java.io.IOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.channels.WritableByteChannel; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.util.Properties; -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.ShortBufferException; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; - -import org.apache.commons.crypto.cipher.CryptoCipher; -import org.apache.commons.crypto.stream.output.ChannelOutput; -import org.apache.commons.crypto.stream.output.Output; -import org.apache.commons.crypto.stream.output.StreamOutput; -import org.apache.commons.crypto.utils.Utils; - -/** - *

- * CTRCryptoOutputStream encrypts data. It is not thread-safe. AES CTR mode is - * required in order to ensure that the plain text and cipher text have a 1:1 - * mapping. The encryption is buffer based. The key points of the encryption are - * (1) calculating counter and (2) padding through stream position. - *

- *

- * counter = base + pos/(algorithm blocksize); padding = pos%(algorithm - * blocksize); - *

- * The underlying stream offset is maintained as state. - */ -public class CTRCryptoOutputStream extends CryptoOutputStream { - /** - * Underlying stream offset. - */ - private long streamOffset = 0; - - /** - * The initial IV. - */ - private final byte[] initIV; - - /** - * Initialization vector for the cipher. - */ - private byte[] iv; - - /** - * Padding = pos%(algorithm blocksize); Padding is put into - * {@link #inBuffer} before any other data goes in. The purpose of padding - * is to put input data at proper position. - */ - private byte padding; - - /** - * Flag to mark whether the cipher has been reset - */ - private boolean cipherReset = false; - - /** - * Constructs a {@link CTRCryptoOutputStream}. - * - * @param props The Properties class represents a set of - * properties. - * @param out the output stream. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @throws IOException if an I/O error occurs. - */ - public CTRCryptoOutputStream(Properties props, OutputStream out, - byte[] key, byte[] iv) throws IOException { - this(props, out, key, iv, 0); - } - - /** - * Constructs a {@link CTRCryptoOutputStream}. - * - * @param props The Properties class represents a set of - * properties. - * @param out the WritableByteChannel instance. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @throws IOException if an I/O error occurs. - */ - public CTRCryptoOutputStream(Properties props, WritableByteChannel out, - byte[] key, byte[] iv) throws IOException { - this(props, out, key, iv, 0); - } - - /** - * Constructs a {@link CTRCryptoOutputStream}. - * - * @param out the output stream. - * @param cipher the CryptoCipher instance. - * @param bufferSize the bufferSize. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @throws IOException if an I/O error occurs. - */ - protected CTRCryptoOutputStream(OutputStream out, CryptoCipher cipher, - int bufferSize, byte[] key, byte[] iv) throws IOException { - this(out, cipher, bufferSize, key, iv, 0); - } - - /** - * Constructs a {@link CTRCryptoOutputStream}. - * - * @param channel the WritableByteChannel instance. - * @param cipher the CryptoCipher instance. - * @param bufferSize the bufferSize. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @throws IOException if an I/O error occurs. - */ - protected CTRCryptoOutputStream(WritableByteChannel channel, - CryptoCipher cipher, int bufferSize, byte[] key, byte[] iv) - throws IOException { - this(channel, cipher, bufferSize, key, iv, 0); - } - - /** - * Constructs a {@link CTRCryptoOutputStream}. - * - * @param output the Output instance. - * @param cipher the CryptoCipher instance. - * @param bufferSize the bufferSize. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @throws IOException if an I/O error occurs. - */ - protected CTRCryptoOutputStream(Output output, CryptoCipher cipher, - int bufferSize, byte[] key, byte[] iv) throws IOException { - this(output, cipher, bufferSize, key, iv, 0); - } - - /** - * Constructs a {@link CTRCryptoOutputStream}. - * - * @param props The Properties class represents a set of - * properties. - * @param out the output stream. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @param streamOffset the start offset in the data. - * @throws IOException if an I/O error occurs. - */ - public CTRCryptoOutputStream(Properties props, OutputStream out, - byte[] key, byte[] iv, long streamOffset) throws IOException { - this(out, Utils.getCipherInstance( - "AES/CTR/NoPadding", props), - CryptoInputStream.getBufferSize(props), key, iv, streamOffset); - } - - /** - * Constructs a {@link CTRCryptoOutputStream}. - * - * @param props The Properties class represents a set of - * properties. - * @param out the WritableByteChannel instance. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @param streamOffset the start offset in the data. - * @throws IOException if an I/O error occurs. - */ - public CTRCryptoOutputStream(Properties props, WritableByteChannel out, - byte[] key, byte[] iv, long streamOffset) throws IOException { - this(out, Utils.getCipherInstance( - "AES/CTR/NoPadding", props), - CryptoInputStream.getBufferSize(props), key, iv, streamOffset); - } - - /** - * Constructs a {@link CTRCryptoOutputStream}. - * - * @param out the output stream. - * @param cipher the CryptoCipher instance. - * @param bufferSize the bufferSize. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @param streamOffset the start offset in the data. - * @throws IOException if an I/O error occurs. - */ - protected CTRCryptoOutputStream(OutputStream out, CryptoCipher cipher, - int bufferSize, byte[] key, byte[] iv, long streamOffset) - throws IOException { - this(new StreamOutput(out, bufferSize), cipher, bufferSize, key, iv, - streamOffset); - } - - /** - * Constructs a {@link CTRCryptoOutputStream}. - * - * @param channel the WritableByteChannel instance. - * @param cipher the CryptoCipher instance. - * @param bufferSize the bufferSize. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @param streamOffset the start offset in the data. - * @throws IOException if an I/O error occurs. - */ - protected CTRCryptoOutputStream(WritableByteChannel channel, - CryptoCipher cipher, int bufferSize, byte[] key, byte[] iv, - long streamOffset) throws IOException { - this(new ChannelOutput(channel), cipher, bufferSize, key, iv, - streamOffset); - } - - /** - * Constructs a {@link CTRCryptoOutputStream}. - * - * @param output the output stream. - * @param cipher the CryptoCipher instance. - * @param bufferSize the bufferSize. - * @param key crypto key for the cipher. - * @param iv Initialization vector for the cipher. - * @param streamOffset the start offset in the data. - * @throws IOException if an I/O error occurs. - */ - protected CTRCryptoOutputStream(Output output, CryptoCipher cipher, - int bufferSize, byte[] key, byte[] iv, long streamOffset) - throws IOException { - super(output, cipher, bufferSize, new SecretKeySpec(key, "AES"), - new IvParameterSpec(iv)); - - CryptoInputStream.checkStreamCipher(cipher); - this.streamOffset = streamOffset; - this.initIV = iv.clone(); - this.iv = iv.clone(); - - resetCipher(); - } - - /** - * Does the encryption, input is {@link #inBuffer} and output is - * {@link #outBuffer}. - * - * @throws IOException if an I/O error occurs. - */ - @Override - protected void encrypt() throws IOException { - Utils.checkState(inBuffer.position() >= padding); - if (inBuffer.position() == padding) { - // There is no real data in the inBuffer. - return; - } - - inBuffer.flip(); - outBuffer.clear(); - encryptBuffer(outBuffer); - inBuffer.clear(); - outBuffer.flip(); - - if (padding > 0) { - /* - * The plain text and cipher text have a 1:1 mapping, they start at - * the same position. - */ - outBuffer.position(padding); - padding = 0; - } - - final int len = output.write(outBuffer); - streamOffset += len; - if (cipherReset) { - /* - * This code is generally not executed since the encryptor usually - * maintains encryption context (e.g. the counter) internally. - * However, some implementations can't maintain context so a re-init - * is necessary after each encryption call. - */ - resetCipher(); - } - } - - /** - * Does final encryption of the last data. - * - * @throws IOException if an I/O error occurs. - */ - @Override - protected void encryptFinal() throws IOException { - // The same as the normal encryption for Counter mode - encrypt(); - } - - /** - * Overrides the {@link CryptoOutputStream#initCipher()}. Initializes the - * cipher. - */ - @Override - protected void initCipher() { - // Do nothing for initCipher - // Will reset the cipher considering the stream offset - } - - /** - * Resets the {@link #cipher}: calculate counter and {@link #padding}. - * - * @throws IOException if an I/O error occurs. - */ - private void resetCipher() throws IOException { - final long counter = streamOffset - / cipher.getBlockSize(); - padding = (byte) (streamOffset % cipher.getBlockSize()); - inBuffer.position(padding); // Set proper position for input data. - - CTRCryptoInputStream.calculateIV(initIV, counter, iv); - try { - cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); - } catch (InvalidKeyException e) { - throw new IOException(e); - } catch (InvalidAlgorithmParameterException e) { - throw new IOException(e); - } - cipherReset = false; - } - - /** - * Does the encryption if the ByteBuffer data. - * - * @param out the output ByteBuffer. - * @throws IOException if an I/O error occurs. - */ - private void encryptBuffer(ByteBuffer out) throws IOException { - int inputSize = inBuffer.remaining(); - try { - int n = cipher.update(inBuffer, out); - if (n < inputSize) { - /** - * Typically code will not get here. CryptoCipher#update will - * consume all input data and put result in outBuffer. - * CryptoCipher#doFinal will reset the cipher context. - */ - cipher.doFinal(inBuffer, out); - cipherReset = true; - } - } catch (ShortBufferException e) { - throw new IOException(e); - } catch (BadPaddingException e) { - throw new IOException(e); - } catch (IllegalBlockSizeException e) { - throw new IOException(e); - } - } - - /** - * Get the underlying stream offset - * - * @return the underlying stream offset - */ - protected long getStreamOffset() { - return streamOffset; - } - - /** - * Set the underlying stream offset - * - * @param streamOffset the underlying stream offset - */ - protected void setStreamOffset(long streamOffset) { - this.streamOffset = streamOffset; - } -} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/ba14d801/src/main/java/org/apache/commons/crypto/stream/CryptoInputStream.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/stream/CryptoInputStream.java b/src/main/java/org/apache/commons/crypto/stream/CryptoInputStream.java index 655f3b5..334d391 100644 --- a/src/main/java/org/apache/commons/crypto/stream/CryptoInputStream.java +++ b/src/main/java/org/apache/commons/crypto/stream/CryptoInputStream.java @@ -356,7 +356,7 @@ public class CryptoInputStream extends InputStream implements /** * Overrides the {@link InputStream#markSupported()}. * - * @return false,the {@link CTRCryptoInputStream} don't support the mark + * @return false,the {@link CtrCryptoInputStream} don't support the mark * method. */ @Override http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/ba14d801/src/main/java/org/apache/commons/crypto/stream/CtrCryptoInputStream.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/stream/CtrCryptoInputStream.java b/src/main/java/org/apache/commons/crypto/stream/CtrCryptoInputStream.java new file mode 100644 index 0000000..56ad048 --- /dev/null +++ b/src/main/java/org/apache/commons/crypto/stream/CtrCryptoInputStream.java @@ -0,0 +1,672 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.crypto.stream; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.util.Properties; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.crypto.cipher.CryptoCipher; +import org.apache.commons.crypto.stream.input.ChannelInput; +import org.apache.commons.crypto.stream.input.Input; +import org.apache.commons.crypto.stream.input.StreamInput; +import org.apache.commons.crypto.utils.Utils; + +/** + *

+ * CtrCryptoInputStream decrypts data. AES CTR mode is required in order to + * ensure that the plain text and cipher text have a 1:1 mapping. CTR crypto + * stream has stream characteristic which is useful for implement features like + * random seek. The decryption is buffer based. The key points of the decryption + * are (1) calculating the counter and (2) padding through stream position: + *

+ *

+ * counter = base + pos/(algorithm blocksize); padding = pos%(algorithm + * blocksize); + *

+ * The underlying stream offset is maintained as state. It is not thread-safe. + */ +public class CtrCryptoInputStream extends CryptoInputStream { + /** + * Underlying stream offset + */ + private long streamOffset = 0; + + /** + * The initial IV. + */ + private final byte[] initIV; + + /** + * Initialization vector for the cipher. + */ + private byte[] iv; + + /** + * Padding = pos%(algorithm blocksize); Padding is put into + * {@link #inBuffer} before any other data goes in. The purpose of padding + * is to put the input data at proper position. + */ + private byte padding; + + /** + * Flag to mark whether the cipher has been reset + */ + private boolean cipherReset = false; + + /** + * For AES, the algorithm block is fixed size of 128 bits. + * + * @see + * http://en.wikipedia.org/wiki/Advanced_Encryption_Standard + */ + private static final int AES_BLOCK_SIZE = 16; + + /** + * Constructs a {@link CtrCryptoInputStream}. + * + * @param props The Properties class represents a set of + * properties. + * @param in the input stream. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @throws IOException if an I/O error occurs. + */ + public CtrCryptoInputStream(Properties props, InputStream in, byte[] key, + byte[] iv) throws IOException { + this(props, in, key, iv, 0); + } + + /** + * Constructs a {@link CtrCryptoInputStream}. + * + * @param props The Properties class represents a set of + * properties. + * @param in the ReadableByteChannel instance. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @throws IOException if an I/O error occurs. + */ + public CtrCryptoInputStream(Properties props, ReadableByteChannel in, + byte[] key, byte[] iv) throws IOException { + this(props, in, key, iv, 0); + } + + /** + * Constructs a {@link CtrCryptoInputStream}. + * + * @param in the input stream. + * @param cipher the CryptoCipher instance. + * @param bufferSize the bufferSize. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @throws IOException if an I/O error occurs. + */ + protected CtrCryptoInputStream(InputStream in, CryptoCipher cipher, + int bufferSize, byte[] key, byte[] iv) throws IOException { + this(in, cipher, bufferSize, key, iv, 0); + } + + /** + * Constructs a {@link CtrCryptoInputStream}. + * + * @param in the ReadableByteChannel instance. + * @param cipher the cipher instance. + * @param bufferSize the bufferSize. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @throws IOException if an I/O error occurs. + */ + protected CtrCryptoInputStream(ReadableByteChannel in, CryptoCipher cipher, + int bufferSize, byte[] key, byte[] iv) throws IOException { + this(in, cipher, bufferSize, key, iv, 0); + } + + /** + * Constructs a {@link CtrCryptoInputStream}. + * + * @param input the input data. + * @param cipher the CryptoCipher instance. + * @param bufferSize the bufferSize. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @throws IOException if an I/O error occurs. + */ + protected CtrCryptoInputStream(Input input, CryptoCipher cipher, + int bufferSize, byte[] key, byte[] iv) throws IOException { + this(input, cipher, bufferSize, key, iv, 0); + } + + /** + * Constructs a {@link CtrCryptoInputStream}. + * + * @param props The Properties class represents a set of + * properties. + * @param in the InputStream instance. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @param streamOffset the start offset in the stream. + * @throws IOException if an I/O error occurs. + */ + public CtrCryptoInputStream(Properties props, InputStream in, byte[] key, + byte[] iv, long streamOffset) throws IOException { + this(in, Utils.getCipherInstance( + "AES/CTR/NoPadding", props), + CryptoInputStream.getBufferSize(props), key, iv, streamOffset); + } + + /** + * Constructs a {@link CtrCryptoInputStream}. + * + * @param props The Properties class represents a set of + * properties. + * @param in the ReadableByteChannel instance. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @param streamOffset the start offset in the stream. + * @throws IOException if an I/O error occurs. + */ + public CtrCryptoInputStream(Properties props, ReadableByteChannel in, + byte[] key, byte[] iv, long streamOffset) throws IOException { + this(in, Utils.getCipherInstance( + "AES/CTR/NoPadding", props), + CryptoInputStream.getBufferSize(props), key, iv, streamOffset); + } + + /** + * Constructs a {@link CtrCryptoInputStream}. + * + * @param in the InputStream instance. + * @param cipher the CryptoCipher instance. + * @param bufferSize the bufferSize. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @param streamOffset the start offset in the stream. + * @throws IOException if an I/O error occurs. + */ + protected CtrCryptoInputStream(InputStream in, CryptoCipher cipher, + int bufferSize, byte[] key, byte[] iv, long streamOffset) + throws IOException { + this(new StreamInput(in, bufferSize), cipher, bufferSize, key, iv, + streamOffset); + } + + /** + * Constructs a {@link CtrCryptoInputStream}. + * + * @param in the ReadableByteChannel instance. + * @param cipher the CryptoCipher instance. + * @param bufferSize the bufferSize. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @param streamOffset the start offset in the stream. + * @throws IOException if an I/O error occurs. + */ + protected CtrCryptoInputStream(ReadableByteChannel in, CryptoCipher cipher, + int bufferSize, byte[] key, byte[] iv, long streamOffset) + throws IOException { + this(new ChannelInput(in), cipher, bufferSize, key, iv, streamOffset); + } + + /** + * Constructs a {@link CtrCryptoInputStream}. + * + * @param input the input data. + * @param cipher the CryptoCipher instance. + * @param bufferSize the bufferSize. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @param streamOffset the start offset in the stream. + * @throws IOException if an I/O error occurs. + */ + protected CtrCryptoInputStream(Input input, CryptoCipher cipher, + int bufferSize, byte[] key, byte[] iv, long streamOffset) + throws IOException { + super(input, cipher, bufferSize, new SecretKeySpec(key, "AES"), + new IvParameterSpec(iv)); + + this.initIV = iv.clone(); + this.iv = iv.clone(); + + CryptoInputStream.checkStreamCipher(cipher); + + resetStreamOffset(streamOffset); + } + + /** + * Overrides the {@link CryptoInputStream#skip(long)}. Skips over and + * discards n bytes of data from this input stream. + * + * @param n the number of bytes to be skipped. + * @return the actual number of bytes skipped. + * @throws IOException if an I/O error occurs. + */ + @Override + public long skip(long n) throws IOException { + Utils.checkArgument(n >= 0, "Negative skip length."); + checkStream(); + + if (n == 0) { + return 0; + } else if (n <= outBuffer.remaining()) { + int pos = outBuffer.position() + (int) n; + outBuffer.position(pos); + return n; + } else { + /* + * Subtract outBuffer.remaining() to see how many bytes we need to + * skip in the underlying stream. Add outBuffer.remaining() to the + * actual number of skipped bytes in the underlying stream to get + * the number of skipped bytes from the user's point of view. + */ + n -= outBuffer.remaining(); + long skipped = input.skip(n); + if (skipped < 0) { + skipped = 0; + } + long pos = streamOffset + skipped; + skipped += outBuffer.remaining(); + resetStreamOffset(pos); + return skipped; + } + } + + /** + * Overrides the {@link CtrCryptoInputStream#read(ByteBuffer)}. Reads a + * sequence of bytes from this channel into the given buffer. + * + * @param buf The buffer into which bytes are to be transferred. + * @return The number of bytes read, possibly zero, or -1 if the + * channel has reached end-of-stream. + * @throws IOException if an I/O error occurs. + */ + @Override + public int read(ByteBuffer buf) throws IOException { + checkStream(); + int unread = outBuffer.remaining(); + if (unread <= 0) { // Fill the unread decrypted data buffer firstly + final int n = input.read(inBuffer); + if (n <= 0) { + return n; + } + + streamOffset += n; // Read n bytes + if (buf.isDirect() && buf.remaining() >= inBuffer.position() + && padding == 0) { + // Use buf as the output buffer directly + decryptInPlace(buf); + padding = postDecryption(streamOffset); + return n; + } + // Use outBuffer as the output buffer + decrypt(); + padding = postDecryption(streamOffset); + } + + // Copy decrypted data from outBuffer to buf + unread = outBuffer.remaining(); + final int toRead = buf.remaining(); + if (toRead <= unread) { + final int limit = outBuffer.limit(); + outBuffer.limit(outBuffer.position() + toRead); + buf.put(outBuffer); + outBuffer.limit(limit); + return toRead; + } + buf.put(outBuffer); + return unread; + } + + /** + * Seeks the stream to a specific position relative to start of the under + * layer stream. + * + * @param position the given position in the data. + * @throws IOException if an I/O error occurs. + */ + public void seek(long position) throws IOException { + Utils.checkArgument(position >= 0, "Cannot seek to negative offset."); + checkStream(); + /* + * If data of target pos in the underlying stream has already been read + * and decrypted in outBuffer, we just need to re-position outBuffer. + */ + if (position >= getStreamPosition() && position <= getStreamOffset()) { + int forward = (int) (position - getStreamPosition()); + if (forward > 0) { + outBuffer.position(outBuffer.position() + forward); + } + } else { + input.seek(position); + resetStreamOffset(position); + } + } + + /** + * Gets the offset of the stream. + * + * @return the stream offset. + */ + protected long getStreamOffset() { + return streamOffset; + } + + /** + * Sets the offset of stream. + * + * @param streamOffset the stream offset. + */ + protected void setStreamOffset(long streamOffset) { + this.streamOffset = streamOffset; + } + + /** + * Gets the position of the stream. + * + * @return the position of the stream. + */ + protected long getStreamPosition() { + return streamOffset - outBuffer.remaining(); + } + + /** + * Decrypts more data by reading the under layer stream. The decrypted data + * will be put in the output buffer. + * + * @return The number of decrypted data. -1 if end of the decrypted stream. + * @throws IOException if an I/O error occurs. + */ + @Override + protected int decryptMore() throws IOException { + int n = input.read(inBuffer); + if (n <= 0) { + return n; + } + + streamOffset += n; // Read n bytes + decrypt(); + padding = postDecryption(streamOffset); + return outBuffer.remaining(); + } + + /** + * Does the decryption using inBuffer as input and outBuffer as output. Upon + * return, inBuffer is cleared; the decrypted data starts at + * outBuffer.position() and ends at outBuffer.limit(). + * + * @throws IOException if an I/O error occurs. + */ + @Override + protected void decrypt() throws IOException { + Utils.checkState(inBuffer.position() >= padding); + if (inBuffer.position() == padding) { + // There is no real data in inBuffer. + return; + } + + inBuffer.flip(); + outBuffer.clear(); + decryptBuffer(outBuffer); + inBuffer.clear(); + outBuffer.flip(); + + if (padding > 0) { + /* + * The plain text and cipher text have a 1:1 mapping, they start at + * the same position. + */ + outBuffer.position(padding); + } + } + + /** + * Does the decryption using inBuffer as input and buf as output. Upon + * return, inBuffer is cleared; the buf's position will be equal to + * p + n where p is the position + * before decryption, n is the number of bytes decrypted. The buf's + * limit will not have changed. + * + * @param buf The buffer into which bytes are to be transferred. + * @throws IOException if an I/O error occurs. + */ + protected void decryptInPlace(ByteBuffer buf) throws IOException { + Utils.checkState(inBuffer.position() >= padding); + Utils.checkState(buf.isDirect()); + Utils.checkState(buf.remaining() >= inBuffer.position()); + Utils.checkState(padding == 0); + + if (inBuffer.position() == padding) { + // There is no real data in inBuffer. + return; + } + inBuffer.flip(); + decryptBuffer(buf); + inBuffer.clear(); + } + + /** + * Decrypts all data in buf: total n bytes from given start position. Output + * is also buf and same start position. buf.position() and buf.limit() + * should be unchanged after decryption. + * + * @param buf The buffer into which bytes are to be transferred. + * @param offset the start offset in the data. + * @param len the the maximum number of decrypted data bytes to read. + * @throws IOException if an I/O error occurs. + */ + protected void decrypt(ByteBuffer buf, int offset, int len) + throws IOException { + final int pos = buf.position(); + final int limit = buf.limit(); + int n = 0; + while (n < len) { + buf.position(offset + n); + buf.limit(offset + n + Math.min(len - n, inBuffer.remaining())); + inBuffer.put(buf); + // Do decryption + try { + decrypt(); + buf.position(offset + n); + buf.limit(limit); + n += outBuffer.remaining(); + buf.put(outBuffer); + } finally { + padding = postDecryption(streamOffset - (len - n)); + } + } + buf.position(pos); + } + + /** + * This method is executed immediately after decryption. Checks whether + * cipher should be updated and recalculate padding if needed. + * + * @param position the given position in the data.. + * @return the byte. + * @throws IOException if an I/O error occurs. + */ + protected byte postDecryption(long position) throws IOException { + byte padding = 0; + if (cipherReset) { + /* + * This code is generally not executed since the cipher usually + * maintains cipher context (e.g. the counter) internally. However, + * some implementations can't maintain context so a re-init is + * necessary after each decryption call. + */ + resetCipher(position); + padding = getPadding(position); + inBuffer.position(padding); + } + return padding; + } + + /** + * Gets the initialization vector. + * + * @return the initIV. + */ + protected byte[] getInitIV() { + return initIV; + } + + /** + * Gets the counter for input stream position. + * + * @param position the given position in the data. + * @return the counter for input stream position. + */ + protected long getCounter(long position) { + return position / cipher.getBlockSize(); + } + + /** + * Gets the padding for input stream position. + * + * @param position the given position in the data. + * @return the padding for input stream position. + */ + protected byte getPadding(long position) { + return (byte) (position % cipher.getBlockSize()); + } + + /** + * Overrides the {@link CtrCryptoInputStream#initCipher()}. Initializes the + * cipher. + */ + @Override + protected void initCipher() { + // Do nothing for initCipher + // Will reset the cipher when reset the stream offset + } + + /** + * Calculates the counter and iv, resets the cipher. + * + * @param position the given position in the data. + * @throws IOException if an I/O error occurs. + */ + protected void resetCipher(long position) throws IOException { + final long counter = getCounter(position); + CtrCryptoInputStream.calculateIV(initIV, counter, iv); + try { + cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); + } catch (InvalidKeyException e) { + throw new IOException(e); + } catch (InvalidAlgorithmParameterException e) { + throw new IOException(e); + } + cipherReset = false; + } + + /** + * Resets the underlying stream offset; clear {@link #inBuffer} and + * {@link #outBuffer}. This Typically happens during {@link #skip(long)}. + * + * @param offset the offset of the stream. + * @throws IOException if an I/O error occurs. + */ + protected void resetStreamOffset(long offset) throws IOException { + streamOffset = offset; + inBuffer.clear(); + outBuffer.clear(); + outBuffer.limit(0); + resetCipher(offset); + padding = getPadding(offset); + inBuffer.position(padding); // Set proper position for input data. + } + + /** + * Does the decryption using out as output. + * + * @param out the output ByteBuffer. + * @throws IOException if an I/O error occurs. + */ + protected void decryptBuffer(ByteBuffer out) throws IOException { + int inputSize = inBuffer.remaining(); + try { + int n = cipher.update(inBuffer, out); + if (n < inputSize) { + /** + * Typically code will not get here. CryptoCipher#update will + * consume all input data and put result in outBuffer. + * CryptoCipher#doFinal will reset the cipher context. + */ + cipher.doFinal(inBuffer, out); + cipherReset = true; + } + } catch (ShortBufferException e) { + throw new IOException(e); + } catch (IllegalBlockSizeException e) { + throw new IOException(e); + } catch (BadPaddingException e) { + throw new IOException(e); + } + } + + /** + *

+ * This method is only for Counter (CTR) mode. Generally the CryptoCipher + * calculates the IV and maintain encryption context internally.For example + * a Cipher will maintain its encryption context internally when we do + * encryption/decryption using the CryptoCipher#update interface. + *

+ *

+ * Encryption/Decryption is not always on the entire file. For example, in + * Hadoop, a node may only decrypt a portion of a file (i.e. a split). In + * these situations, the counter is derived from the file position. + *

+ * The IV can be calculated by combining the initial IV and the counter with + * a lossless operation (concatenation, addition, or XOR). + * + * @see + * http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_.28CTR.29 + * + * @param initIV initial IV + * @param counter counter for input stream position + * @param IV the IV for input stream position + */ + static void calculateIV(byte[] initIV, long counter, byte[] IV) { + Utils.checkArgument(initIV.length == CtrCryptoInputStream.AES_BLOCK_SIZE); + Utils.checkArgument(IV.length == CtrCryptoInputStream.AES_BLOCK_SIZE); + + int i = IV.length; // IV length + int j = 0; // counter bytes index + int sum = 0; + while (i-- > 0) { + // (sum >>> Byte.SIZE) is the carry for addition + sum = (initIV[i] & 0xff) + (sum >>> Byte.SIZE); // NOPMD + if (j++ < 8) { // Big-endian, and long is 8 bytes length + sum += (byte) counter & 0xff; + counter >>>= 8; + } + IV[i] = (byte) sum; + } + } +} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/ba14d801/src/main/java/org/apache/commons/crypto/stream/CtrCryptoOutputStream.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/stream/CtrCryptoOutputStream.java b/src/main/java/org/apache/commons/crypto/stream/CtrCryptoOutputStream.java new file mode 100644 index 0000000..c05b0c0 --- /dev/null +++ b/src/main/java/org/apache/commons/crypto/stream/CtrCryptoOutputStream.java @@ -0,0 +1,384 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.crypto.stream; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.WritableByteChannel; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.util.Properties; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import org.apache.commons.crypto.cipher.CryptoCipher; +import org.apache.commons.crypto.stream.output.ChannelOutput; +import org.apache.commons.crypto.stream.output.Output; +import org.apache.commons.crypto.stream.output.StreamOutput; +import org.apache.commons.crypto.utils.Utils; + +/** + *

+ * CtrCryptoOutputStream encrypts data. It is not thread-safe. AES CTR mode is + * required in order to ensure that the plain text and cipher text have a 1:1 + * mapping. The encryption is buffer based. The key points of the encryption are + * (1) calculating counter and (2) padding through stream position. + *

+ *

+ * counter = base + pos/(algorithm blocksize); padding = pos%(algorithm + * blocksize); + *

+ * The underlying stream offset is maintained as state. + */ +public class CtrCryptoOutputStream extends CryptoOutputStream { + /** + * Underlying stream offset. + */ + private long streamOffset = 0; + + /** + * The initial IV. + */ + private final byte[] initIV; + + /** + * Initialization vector for the cipher. + */ + private byte[] iv; + + /** + * Padding = pos%(algorithm blocksize); Padding is put into + * {@link #inBuffer} before any other data goes in. The purpose of padding + * is to put input data at proper position. + */ + private byte padding; + + /** + * Flag to mark whether the cipher has been reset + */ + private boolean cipherReset = false; + + /** + * Constructs a {@link CtrCryptoOutputStream}. + * + * @param props The Properties class represents a set of + * properties. + * @param out the output stream. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @throws IOException if an I/O error occurs. + */ + public CtrCryptoOutputStream(Properties props, OutputStream out, + byte[] key, byte[] iv) throws IOException { + this(props, out, key, iv, 0); + } + + /** + * Constructs a {@link CtrCryptoOutputStream}. + * + * @param props The Properties class represents a set of + * properties. + * @param out the WritableByteChannel instance. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @throws IOException if an I/O error occurs. + */ + public CtrCryptoOutputStream(Properties props, WritableByteChannel out, + byte[] key, byte[] iv) throws IOException { + this(props, out, key, iv, 0); + } + + /** + * Constructs a {@link CtrCryptoOutputStream}. + * + * @param out the output stream. + * @param cipher the CryptoCipher instance. + * @param bufferSize the bufferSize. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @throws IOException if an I/O error occurs. + */ + protected CtrCryptoOutputStream(OutputStream out, CryptoCipher cipher, + int bufferSize, byte[] key, byte[] iv) throws IOException { + this(out, cipher, bufferSize, key, iv, 0); + } + + /** + * Constructs a {@link CtrCryptoOutputStream}. + * + * @param channel the WritableByteChannel instance. + * @param cipher the CryptoCipher instance. + * @param bufferSize the bufferSize. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @throws IOException if an I/O error occurs. + */ + protected CtrCryptoOutputStream(WritableByteChannel channel, + CryptoCipher cipher, int bufferSize, byte[] key, byte[] iv) + throws IOException { + this(channel, cipher, bufferSize, key, iv, 0); + } + + /** + * Constructs a {@link CtrCryptoOutputStream}. + * + * @param output the Output instance. + * @param cipher the CryptoCipher instance. + * @param bufferSize the bufferSize. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @throws IOException if an I/O error occurs. + */ + protected CtrCryptoOutputStream(Output output, CryptoCipher cipher, + int bufferSize, byte[] key, byte[] iv) throws IOException { + this(output, cipher, bufferSize, key, iv, 0); + } + + /** + * Constructs a {@link CtrCryptoOutputStream}. + * + * @param props The Properties class represents a set of + * properties. + * @param out the output stream. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @param streamOffset the start offset in the data. + * @throws IOException if an I/O error occurs. + */ + public CtrCryptoOutputStream(Properties props, OutputStream out, + byte[] key, byte[] iv, long streamOffset) throws IOException { + this(out, Utils.getCipherInstance( + "AES/CTR/NoPadding", props), + CryptoInputStream.getBufferSize(props), key, iv, streamOffset); + } + + /** + * Constructs a {@link CtrCryptoOutputStream}. + * + * @param props The Properties class represents a set of + * properties. + * @param out the WritableByteChannel instance. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @param streamOffset the start offset in the data. + * @throws IOException if an I/O error occurs. + */ + public CtrCryptoOutputStream(Properties props, WritableByteChannel out, + byte[] key, byte[] iv, long streamOffset) throws IOException { + this(out, Utils.getCipherInstance( + "AES/CTR/NoPadding", props), + CryptoInputStream.getBufferSize(props), key, iv, streamOffset); + } + + /** + * Constructs a {@link CtrCryptoOutputStream}. + * + * @param out the output stream. + * @param cipher the CryptoCipher instance. + * @param bufferSize the bufferSize. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @param streamOffset the start offset in the data. + * @throws IOException if an I/O error occurs. + */ + protected CtrCryptoOutputStream(OutputStream out, CryptoCipher cipher, + int bufferSize, byte[] key, byte[] iv, long streamOffset) + throws IOException { + this(new StreamOutput(out, bufferSize), cipher, bufferSize, key, iv, + streamOffset); + } + + /** + * Constructs a {@link CtrCryptoOutputStream}. + * + * @param channel the WritableByteChannel instance. + * @param cipher the CryptoCipher instance. + * @param bufferSize the bufferSize. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @param streamOffset the start offset in the data. + * @throws IOException if an I/O error occurs. + */ + protected CtrCryptoOutputStream(WritableByteChannel channel, + CryptoCipher cipher, int bufferSize, byte[] key, byte[] iv, + long streamOffset) throws IOException { + this(new ChannelOutput(channel), cipher, bufferSize, key, iv, + streamOffset); + } + + /** + * Constructs a {@link CtrCryptoOutputStream}. + * + * @param output the output stream. + * @param cipher the CryptoCipher instance. + * @param bufferSize the bufferSize. + * @param key crypto key for the cipher. + * @param iv Initialization vector for the cipher. + * @param streamOffset the start offset in the data. + * @throws IOException if an I/O error occurs. + */ + protected CtrCryptoOutputStream(Output output, CryptoCipher cipher, + int bufferSize, byte[] key, byte[] iv, long streamOffset) + throws IOException { + super(output, cipher, bufferSize, new SecretKeySpec(key, "AES"), + new IvParameterSpec(iv)); + + CryptoInputStream.checkStreamCipher(cipher); + this.streamOffset = streamOffset; + this.initIV = iv.clone(); + this.iv = iv.clone(); + + resetCipher(); + } + + /** + * Does the encryption, input is {@link #inBuffer} and output is + * {@link #outBuffer}. + * + * @throws IOException if an I/O error occurs. + */ + @Override + protected void encrypt() throws IOException { + Utils.checkState(inBuffer.position() >= padding); + if (inBuffer.position() == padding) { + // There is no real data in the inBuffer. + return; + } + + inBuffer.flip(); + outBuffer.clear(); + encryptBuffer(outBuffer); + inBuffer.clear(); + outBuffer.flip(); + + if (padding > 0) { + /* + * The plain text and cipher text have a 1:1 mapping, they start at + * the same position. + */ + outBuffer.position(padding); + padding = 0; + } + + final int len = output.write(outBuffer); + streamOffset += len; + if (cipherReset) { + /* + * This code is generally not executed since the encryptor usually + * maintains encryption context (e.g. the counter) internally. + * However, some implementations can't maintain context so a re-init + * is necessary after each encryption call. + */ + resetCipher(); + } + } + + /** + * Does final encryption of the last data. + * + * @throws IOException if an I/O error occurs. + */ + @Override + protected void encryptFinal() throws IOException { + // The same as the normal encryption for Counter mode + encrypt(); + } + + /** + * Overrides the {@link CryptoOutputStream#initCipher()}. Initializes the + * cipher. + */ + @Override + protected void initCipher() { + // Do nothing for initCipher + // Will reset the cipher considering the stream offset + } + + /** + * Resets the {@link #cipher}: calculate counter and {@link #padding}. + * + * @throws IOException if an I/O error occurs. + */ + private void resetCipher() throws IOException { + final long counter = streamOffset + / cipher.getBlockSize(); + padding = (byte) (streamOffset % cipher.getBlockSize()); + inBuffer.position(padding); // Set proper position for input data. + + CtrCryptoInputStream.calculateIV(initIV, counter, iv); + try { + cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); + } catch (InvalidKeyException e) { + throw new IOException(e); + } catch (InvalidAlgorithmParameterException e) { + throw new IOException(e); + } + cipherReset = false; + } + + /** + * Does the encryption if the ByteBuffer data. + * + * @param out the output ByteBuffer. + * @throws IOException if an I/O error occurs. + */ + private void encryptBuffer(ByteBuffer out) throws IOException { + int inputSize = inBuffer.remaining(); + try { + int n = cipher.update(inBuffer, out); + if (n < inputSize) { + /** + * Typically code will not get here. CryptoCipher#update will + * consume all input data and put result in outBuffer. + * CryptoCipher#doFinal will reset the cipher context. + */ + cipher.doFinal(inBuffer, out); + cipherReset = true; + } + } catch (ShortBufferException e) { + throw new IOException(e); + } catch (BadPaddingException e) { + throw new IOException(e); + } catch (IllegalBlockSizeException e) { + throw new IOException(e); + } + } + + /** + * Get the underlying stream offset + * + * @return the underlying stream offset + */ + protected long getStreamOffset() { + return streamOffset; + } + + /** + * Set the underlying stream offset + * + * @param streamOffset the underlying stream offset + */ + protected void setStreamOffset(long streamOffset) { + this.streamOffset = streamOffset; + } +} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/ba14d801/src/main/java/org/apache/commons/crypto/stream/PositionedCryptoInputStream.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/crypto/stream/PositionedCryptoInputStream.java b/src/main/java/org/apache/commons/crypto/stream/PositionedCryptoInputStream.java index bd6c39d..b3d0509 100644 --- a/src/main/java/org/apache/commons/crypto/stream/PositionedCryptoInputStream.java +++ b/src/main/java/org/apache/commons/crypto/stream/PositionedCryptoInputStream.java @@ -42,7 +42,7 @@ import org.apache.commons.crypto.utils.Utils; * starting at random position as well as provides the foundation for positioned * read for decrypting. This needs a stream cipher mode such as AES CTR mode. */ -public class PositionedCryptoInputStream extends CTRCryptoInputStream { +public class PositionedCryptoInputStream extends CtrCryptoInputStream { /** * DirectBuffer pool @@ -296,7 +296,7 @@ public class PositionedCryptoInputStream extends CTRCryptoInputStream { private void resetCipher(CipherState state, long position, byte[] iv) throws IOException { final long counter = getCounter(position); - CTRCryptoInputStream.calculateIV(getInitIV(), counter, iv); + CtrCryptoInputStream.calculateIV(getInitIV(), counter, iv); try { state.getCipher().init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/ba14d801/src/test/java/org/apache/commons/crypto/stream/CTRCryptoStreamTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/crypto/stream/CTRCryptoStreamTest.java b/src/test/java/org/apache/commons/crypto/stream/CTRCryptoStreamTest.java deleted file mode 100644 index 3ba55ec..0000000 --- a/src/test/java/org/apache/commons/crypto/stream/CTRCryptoStreamTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.crypto.stream; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.channels.Channels; - -import org.apache.commons.crypto.cipher.CryptoCipher; - -public class CTRCryptoStreamTest extends AbstractCipherStreamTest { - - @Override - public void setUp() throws IOException { - transformation = "AES/CTR/NoPadding"; - } - - @Override - protected CTRCryptoInputStream getCryptoInputStream( - ByteArrayInputStream bais, CryptoCipher cipher, int bufferSize, - byte[] iv, boolean withChannel) throws IOException { - if (withChannel) { - return new CTRCryptoInputStream(Channels.newChannel(bais), cipher, - bufferSize, key, iv); - } - return new CTRCryptoInputStream(bais, cipher, bufferSize, key, iv); - } - - @Override - protected CTRCryptoOutputStream getCryptoOutputStream( - ByteArrayOutputStream baos, CryptoCipher cipher, int bufferSize, - byte[] iv, boolean withChannel) throws IOException { - if (withChannel) { - return new CTRCryptoOutputStream(Channels.newChannel(baos), cipher, - bufferSize, key, iv); - } - return new CTRCryptoOutputStream(baos, cipher, bufferSize, key, iv); - } -} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/ba14d801/src/test/java/org/apache/commons/crypto/stream/CTRNoPaddingCipherStreamTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/crypto/stream/CTRNoPaddingCipherStreamTest.java b/src/test/java/org/apache/commons/crypto/stream/CTRNoPaddingCipherStreamTest.java deleted file mode 100644 index 76b8a7e..0000000 --- a/src/test/java/org/apache/commons/crypto/stream/CTRNoPaddingCipherStreamTest.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.commons.crypto.stream; - -import java.io.IOException; - -public class CTRNoPaddingCipherStreamTest extends AbstractCipherStreamTest { - - @Override - public void setUp() throws IOException { - transformation = "AES/CTR/NoPadding"; - } - -} http://git-wip-us.apache.org/repos/asf/commons-crypto/blob/ba14d801/src/test/java/org/apache/commons/crypto/stream/CtrCryptoStreamTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/crypto/stream/CtrCryptoStreamTest.java b/src/test/java/org/apache/commons/crypto/stream/CtrCryptoStreamTest.java new file mode 100644 index 0000000..7b9c12b --- /dev/null +++ b/src/test/java/org/apache/commons/crypto/stream/CtrCryptoStreamTest.java @@ -0,0 +1,55 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.crypto.stream; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.channels.Channels; + +import org.apache.commons.crypto.cipher.CryptoCipher; + +public class CtrCryptoStreamTest extends AbstractCipherStreamTest { + + @Override + public void setUp() throws IOException { + transformation = "AES/CTR/NoPadding"; + } + + @Override + protected CtrCryptoInputStream getCryptoInputStream( + ByteArrayInputStream bais, CryptoCipher cipher, int bufferSize, + byte[] iv, boolean withChannel) throws IOException { + if (withChannel) { + return new CtrCryptoInputStream(Channels.newChannel(bais), cipher, + bufferSize, key, iv); + } + return new CtrCryptoInputStream(bais, cipher, bufferSize, key, iv); + } + + @Override + protected CtrCryptoOutputStream getCryptoOutputStream( + ByteArrayOutputStream baos, CryptoCipher cipher, int bufferSize, + byte[] iv, boolean withChannel) throws IOException { + if (withChannel) { + return new CtrCryptoOutputStream(Channels.newChannel(baos), cipher, + bufferSize, key, iv); + } + return new CtrCryptoOutputStream(baos, cipher, bufferSize, key, iv); + } +}