📄 cipherinputstream.java
字号:
isDPBC = (cipher.isPaddingBlockCipher() && state == Cipher.DECRYPT); this.cipher = cipher; }// FilterInputStream methods//........................................................................... /** * Fills up the specified bytes of the <i>out</i> array with the next * <i>len</i> encrypted or decrypted bytes (depending on the cipher state). * * @param out the byte array into which the encrypted or decrypted * bytes will be read. * @param offset the offset into <i>out</i> indicating where the * first encrypted or decrypted byte should be read. * @param length the number of encrypted/decrypted bytes to read. * @return the number of bytes read into <i>out</i>, or -1 if no * encrypted or decrypted bytes remained. * @exception IOException if an error occurs. * * @see java.security.Cipher#ENCRYPT * @see java.security.Cipher#DECRYPT * @see java.security.Cipher#getState */ public synchronized int read(byte[] out, int offset, int length) throws IOException {if (DEBUG && debuglevel >= 5) debug("read(<" + out + ">, " + offset + ", " + length + ") ..."); // was the stream closed last time we read it? if (cipher == null) {if (DEBUG && debuglevel >= 7) debug("... stream closed"); return -1; } if (length <= 0) return 0; // consistent with other stream implementations. if (offset < 0) throw new ArrayIndexOutOfBoundsException("offset < 0");// if (length > out.length - offset)// length = out.length - offset; // first output any buffered data. int k = 0; if (buffered > 0) { k = buffered < length ? buffered : length; System.arraycopy(outBuf, outPtr, out, offset, k); outPtr += k; buffered -= k; offset += k; length -= k;if (DEBUG && debuglevel >= 7) debug(" outBuf = <" + dump(outBuf) + ">, outPtr = " + outPtr + ", buffered = " + buffered + ", offset = " + offset + ", length = " + length); if (buffered == 0) outPtr = 0; if (length == 0) {if (DEBUG && debuglevel >= 5) debug("... = " + k); return k; } } int inLen = cipher.inBufferSize(length); if (isDPBC) inLen++; byte[] in = (inLen <= preallocated1.length) ? preallocated1 : new byte[inLen];if (DEBUG && debuglevel >= 7) debug(" inLen = " + inLen); // now try reading as many bytes as needed. int l = readFully(in, 0, inLen); // crypt the input into a temporary buffer. byte[] temp; int n; if (l < inLen) { // EOF encountered Cipher _cipher = cipher; cipher = null; // must be done here, since crypt or outBufferSize may // throw an exception int tempLen = _cipher.outBufferSizeFinal(l); temp = (tempLen <= preallocated2.length) ? preallocated2 : new byte[tempLen]; n = _cipher.crypt(in, 0, l, temp, 0); } else { int tempLen = cipher.outBufferSize(l); temp = (tempLen <= preallocated2.length) ? preallocated2 : new byte[tempLen]; n = cipher.update(in, 0, l, temp, 0); }if (DEBUG && debuglevel >= 7) debug(" temp = <" + dump(temp) + ">, n = " + n); // if more data was returned than requested, buffer the excess, making // sure that the buffer is long enough. if (n > length) { buffered = n - length; if (buffered > outBuf.length) outBuf = new byte[buffered]; System.arraycopy(temp, length, outBuf, 0, buffered); n = length;if (DEBUG && debuglevel >= 7) debug(" buffered = " + buffered + ", length = " + length + ", n = " + n); } // n is now the length of output to be copied to the out array. System.arraycopy(temp, 0, out, offset, n); // take into account k bytes previously copied. n += k; if (n == 0 && cipher == null) n = -1;if (DEBUG && debuglevel >= 5) debug("... = " + n); return n; } /** * Read bytes from the underlying stream, until <i>len</i> bytes or EOF. */ private int readFully(byte[] in, int offset, int length) throws IOException { int n = 0, k = 0; do { n += k; k = super.read(in, n, length-n);if (DEBUG && debuglevel >= 7) debug(" n = " + n + ", k = " + k); } while (k >= 0 && n < length); return n; } /** * Returns the next encrypted or decrypted byte, depending on the * cipher state. * * @return the next encrypted or decrypted byte, or -1 if the * last encrypted/decrypted byte was already returned. * @exception IOException if an error occurs. * * @see java.security.Cipher#ENCRYPT * @see java.security.Cipher#DECRYPT * @see java.security.Cipher#getState */ public synchronized int read() throws IOException { if (read(tempByte, 0, 1) < 1) return -1; else return tempByte[0] & 0xFF; } /** * Skips over and discards <i>n</i> bytes of data from the * input stream. The <code>skip</code> method may, for a variety of * reasons, end up skipping over some smaller number of bytes, * possibly 0. 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 synchronized long skip(long n) throws IOException { // FIXME: this is horribly inefficient for large n. final int FUDGE_LEN = 100000; int length = (n < FUDGE_LEN) ? (int) n : FUDGE_LEN; byte[] out = new byte[length]; long m = n; while (m > 0) { length = this.read(out, 0, length); if (length < 0) return n-m; m -= length; length = (m < FUDGE_LEN) ? (int) m : FUDGE_LEN; } return n; } /** * Returns the number of bytes that can be guaranteed to be read from this * input stream without blocking. * * @exception IOException if an I/O error occurs. */ public synchronized int available() throws IOException { // Note: we don't know whether the count returned by super.available() // will include the final block. However, outBufferSize should always // return <= outBufferSizeFinal, and it is OK for available() to // return an underestimate of the number of available bytes. if (cipher == null) return 0; return buffered + cipher.outBufferSize(super.available()); } /** * Closes the input stream. * * @exception IOException if an error occurs. */ public synchronized void close() throws IOException { cipher = null; super.close(); } /** * Does nothing, since this class does not support mark/reset. */ public void mark(int readlimit) {} /** * Always throws an IOException, since this class does not support mark/reset. */ public void reset() throws IOException { throw new IOException("CipherInputStream does not support mark/reset"); } /** * Tests if this input stream supports the <code>mark</code> and * <code>reset</code> methods of InputStream, which it does not. * * @return <code>false</code>, since this class does not support the * <code>mark</code> and <code>reset</code> methods. */ public boolean markSupported() { return false; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -