/** Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.** This code is free software; you can redistribute it and/or modify it* under the terms of the GNU General Public License version 2 only, as* published by the Free Software Foundation. Oracle designates this* particular file as subject to the "Classpath" exception as provided* by Oracle in the LICENSE file that accompanied this code.** This code is distributed in the hope that it will be useful, but WITHOUT* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License* version 2 for more details (a copy is included in the LICENSE file that* accompanied this code).** You should have received a copy of the GNU General Public License version* 2 along with this work; if not, write to the Free Software Foundation,* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.** Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA* or visit www.oracle.com if you need additional information or have any* questions.*/package javax.crypto;import java.io.InputStream;import java.io.FilterInputStream;import java.io.IOException;import javax.crypto.BadPaddingException;import javax.crypto.IllegalBlockSizeException;/*** A CipherInputStream is composed of an InputStream and a Cipher so* that read() methods return data that are read in from the* underlying InputStream but have been additionally processed by the* Cipher. The Cipher must be fully initialized before being used by* a CipherInputStream.** <p> For example, if the Cipher is initialized for decryption, the* CipherInputStream will attempt to read in data and decrypt them,* before returning the decrypted data.** <p> This class adheres strictly to the semantics, especially the* failure semantics, of its ancestor classes* java.io.FilterInputStream and java.io.InputStream. This class has* exactly those methods specified in its ancestor classes, and* overrides them all. Moreover, this class catches all exceptions* that are not thrown by its ancestor classes. In particular, the* <code>skip</code> method skips, and the <code>available</code>* method counts only data that have been processed by the encapsulated Cipher.* This class may catch BadPaddingException and other exceptions thrown by* failed integrity checks during decryption. These exceptions are not* re-thrown, so the client may not be informed that integrity checks* failed. Because of this behavior, this class may not be suitable* for use with decryption in an authenticated mode of operation (e.g. GCM).* Applications that require authenticated encryption can use the Cipher API* directly as an alternative to using this class.** <p> It is crucial for a programmer using this class not to use* methods that are not defined or overridden in this class (such as a* new method or constructor that is later added to one of the super* classes), because the design and implementation of those methods* are unlikely to have considered security impact with regard to* CipherInputStream.** @author Li Gong* @see java.io.InputStream* @see java.io.FilterInputStream* @see javax.crypto.Cipher* @see javax.crypto.CipherOutputStream** @since 1.4*/public class CipherInputStream extends FilterInputStream {// the cipher engine to use to process stream dataprivate Cipher cipher;// the underlying input streamprivate InputStream input;/* the buffer holding data that have been read in from theunderlying stream, but have not been processed by the cipherengine. the size 512 bytes is somewhat randomly chosen */private byte[] ibuffer = new byte[512];// having reached the end of the underlying input streamprivate boolean done = false;/* the buffer holding data that have been processed by the cipherengine, but have not been read out */private byte[] obuffer;// the offset pointing to the next "new" byteprivate int ostart = 0;// the offset pointing to the last "new" byteprivate int ofinish = 0;// stream statusprivate boolean closed = false;/** private convenience function.** Entry condition: ostart = ofinish** Exit condition: ostart <= ofinish** return (ofinish-ostart) (we have this many bytes for you)* return 0 (no data now, but could have more later)* return -1 (absolutely no more data)** Note: Exceptions are only thrown after the stream is completely read.* For AEAD ciphers a read() of any length will internally cause the* whole stream to be read fully and verify the authentication tag before* returning decrypted data or exceptions.*/private int getMoreData() throws IOException {if (done) return -1;int readin = input.read(ibuffer);if (readin == -1) {done = true;try {obuffer = cipher.doFinal();} catch (IllegalBlockSizeException | BadPaddingException e) {obuffer = null;throw new IOException(e);}if (obuffer == null)return -1;else {ostart = 0;ofinish = obuffer.length;return ofinish;}}try {obuffer = cipher.update(ibuffer, 0, readin);} catch (IllegalStateException e) {obuffer = null;throw e;}ostart = 0;if (obuffer == null)ofinish = 0;else ofinish = obuffer.length;return ofinish;}/*** Constructs a CipherInputStream from an InputStream and a* Cipher.* <br>Note: if the specified input stream or cipher is* null, a NullPointerException may be thrown later when* they are used.* @param is the to-be-processed input stream* @param c an initialized Cipher object*/public CipherInputStream(InputStream is, Cipher c) {super(is);input = is;cipher = c;}/*** Constructs a CipherInputStream from an InputStream without* specifying a Cipher. This has the effect of constructing a* CipherInputStream using a NullCipher.* <br>Note: if the specified input stream is null, a* NullPointerException may be thrown later when it is used.* @param is the to-be-processed input stream*/protected CipherInputStream(InputStream is) {super(is);input = is;cipher = new NullCipher();}/*** Reads the next byte of data from this input stream. The value* byte is returned as an <code>int</code> in the range* <code>0</code> to <code>255</code>. If no byte is available* because the end of the stream has been reached, the value* <code>-1</code> is returned. This method blocks until input data* is available, the end of the stream is detected, or an exception* is thrown.** @return the next byte of data, or <code>-1</code> if the end of the* stream is reached.* @exception IOException if an I/O error occurs.*/public int read() throws IOException {if (ostart >= ofinish) {// we loop for new data as the spec says we are blockingint i = 0;while (i == 0) i = getMoreData();if (i == -1) return -1;}return ((int) obuffer[ostart++] & 0xff);};/*** Reads up to <code>b.length</code> bytes of data from this input* stream into an array of bytes.* <p>* The <code>read</code> method of <code>InputStream</code> calls* the <code>read</code> method of three arguments with the arguments* <code>b</code>, <code>0</code>, and <code>b.length</code>.** @param b the buffer into which the data is read.* @return the total number of bytes read into the buffer, or* <code>-1</code> is there is no more data because the end of* the stream has been reached.* @exception IOException if an I/O error occurs.* @see java.io.InputStream#read(byte[], int, int)*/public int read(byte b[]) throws IOException {return read(b, 0, b.length);}/*** Reads up to <code>len</code> bytes of data from this input stream* into an array of bytes. This method blocks until some input is* available. If the first argument is <code>null,</code> up to* <code>len</code> bytes are read and discarded.** @param b the buffer into which the data is read.* @param off the start offset in the destination array* <code>buf</code>* @param len the maximum number of bytes read.* @return the total number of bytes read into the buffer, or* <code>-1</code> if there is no more data because the end of* the stream has been reached.* @exception IOException if an I/O error occurs.* @see java.io.InputStream#read()*/public int read(byte b[], int off, int len) throws IOException {if (ostart >= ofinish) {// we loop for new data as the spec says we are blockingint i = 0;while (i == 0) i = getMoreData();if (i == -1) return -1;}if (len <= 0) {return 0;}int available = ofinish - ostart;if (len < available) available = len;if (b != null) {System.arraycopy(obuffer, ostart, b, off, available);}ostart = ostart + available;return available;}/*** Skips <code>n</code> bytes of input from the bytes that can be read* from this input stream without blocking.** <p>Fewer bytes than requested might be skipped.* The actual number of bytes skipped is equal to <code>n</code> or* the result of a call to* {@link #available() available},* whichever is smaller.* If <code>n</code> is less than zero, no bytes are skipped.** <p>The actual number of bytes skipped is returned.** @param n the number of bytes to be skipped.* @return the actual number of bytes skipped.* @exception IOException if an I/O error occurs.*/public long skip(long n) throws IOException {int available = ofinish - ostart;if (n > available) {n = available;}if (n < 0) {return 0;}ostart += n;return n;}/*** Returns the number of bytes that can be read from this input* stream without blocking. The <code>available</code> method of* <code>InputStream</code> returns <code>0</code>. This method* <B>should</B> be overridden by subclasses.** @return the number of bytes that can be read from this input stream* without blocking.* @exception IOException if an I/O error occurs.*/public int available() throws IOException {return (ofinish - ostart);}/*** Closes this input stream and releases any system resources* associated with the stream.* <p>* The <code>close</code> method of <code>CipherInputStream</code>* calls the <code>close</code> method of its underlying input* stream.** @exception IOException if an I/O error occurs.*/public void close() throws IOException {if (closed) {return;}closed = true;input.close();// Throw away the unprocessed data and throw no crypto exceptions.// AEAD ciphers are fully readed before closing. Any authentication// exceptions would occur while reading.if (!done) {try {cipher.doFinal();}catch (BadPaddingException | IllegalBlockSizeException ex) {// Catch exceptions as the rest of the stream is unused.}}ostart = 0;ofinish = 0;}/*** Tests if this input stream supports the <code>mark</code>* and <code>reset</code> methods, which it does not.** @return <code>false</code>, since this class does not support the* <code>mark</code> and <code>reset</code> methods.* @see java.io.InputStream#mark(int)* @see java.io.InputStream#reset()*/public boolean markSupported() {return false;}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。