📄 encryptedoutputstream.java
字号:
// EncryptedOutputStream - an OutputStream that supports encryption
//
// Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
// Visit the ACME Labs Java page for up-to-date versions of this and other
// fine Java utilities: http://www.acme.com/java/
package Acme.Crypto;
import java.io.*;
/// An OutputStream that supports encryption.
// <P>
// This class encapsulates a StreamCipher or BlockCipher as an OutputStream.
// You set up your cipher, pass it and the underlying stream to the
// EncryptedOutputStream constructor, and then write your cleartext to
// this stream. It gets encrypted and sent to the underlying stream.
// Decryption is done by an EncryptedInputStream.
// <P>
// When used with a StreamCipher, no output protocol is necessary, each
// byte of cleartext turns into one byte of ciphertext. When used with a
// BlockCipher it's more complicated. First, the raw BlockCipher gets
// encapsulated into a CbcBlockCipher, which needs an initialization
// vector; so each encrypted stream automatically starts off with such
// a vector. After that, the stream is a series of (block,bytecount)
// pairs. Each block of cleartext is encrypted into a block of ciphertext,
// sent to the stream, and then one more byte is sent that says how
// many bytes in the block are valid. Generally the bytecount will
// be equal to the block size, but it can be less if the stream gets
// flushed or closed on a partial block.
// <P>
// <A HREF="/resources/classes/Acme/Crypto/EncryptedOutputStream.java">Fetch the software.</A><BR>
// <A HREF="/resources/classes/Acme.tar.gz">Fetch the entire Acme package.</A>
// <P>
// @see EncryptedInputStream
// @see StreamCipher
// @see BlockCipher
// @see CbcBlockCipher
public class EncryptedOutputStream extends FilterOutputStream
{
// The basic block cipher to use.
private BlockCipher blockCipher = null;
// The stream cipher to use.
private StreamCipher streamCipher = null;
// The cipher to use.
private Cipher cipher;
// The CBC block cipher to use.
private CbcBlockCipher cbcBlockCipher;
// Number of bytes in a block.
private int blockSize;
// Number of bytes available for ciphertext in a block.
private int cryptoSize;
// Block of bytes to be encrypted.
private byte[] clearText;
// Block of bytes that have been encrypted.
private byte[] cipherText;
// How many valid bytes are in the clearText block.
private int byteCount;
/// Constructor for block ciphers.
// @param blockCipher The cipher to use, e.g. DesCipher, IdeaCipher
// @param out The raw output stream that we will be encrypting to.
public EncryptedOutputStream( BlockCipher blockCipher, OutputStream out ) throws IOException
{
super( out );
this.blockCipher = blockCipher;
this.blockSize = blockCipher.blockSize();
cbcBlockCipher = new CbcBlockCipher( blockCipher );
cryptoSize = blockSize;
clearText = new byte[blockSize];
cipherText = new byte[blockSize];
byteCount = 0;
this.cipher = blockCipher;
// Set a random IV and send it.
out.write( cbcBlockCipher.setRandomIv(), 0, blockSize );
}
/// Constructor for stream ciphers.
// @param streamCipher The cipher to use, e.g. Rc4Cipher, Rot13Cipher
// @param out The raw output stream that we will be encrypting to.
public EncryptedOutputStream( StreamCipher streamCipher, OutputStream out )
{
super( out );
this.streamCipher = streamCipher;
this.blockSize = 1;
this.cipher = streamCipher;
}
/// Set the key.
public void setKey( String keyStr )
{
cipher.setKey( keyStr );
}
// Whether we are currently encrypting output or not.
private boolean encrypting = true;
/// Encrypting can be enabled or disabled temporarily.
public void setEncrypting( boolean encrypting ) throws IOException
{
if ( this.encrypting && ! encrypting )
flush();
this.encrypting = encrypting;
}
private void sendBlock() throws IOException
{
// Fill up the block with random bytes, if necessary.
for ( int i = byteCount; i < cryptoSize; ++i )
clearText[i] = (byte) ( Math.random() * 256.0 );
// Encrypt it.
cbcBlockCipher.encrypt( clearText, 0, cipherText, 0 );
// Send the block.
out.write( cipherText, 0, blockSize );
// Write out a count of valid bytes.
out.write( (byte) byteCount );
byteCount = 0;
}
/// Write a byte.
public void write( int b ) throws IOException
{
if ( encrypting )
{
if ( blockCipher != null )
{
clearText[byteCount++] = (byte) b;
if ( byteCount >= cryptoSize )
sendBlock();
}
else
// Stream cipher.
out.write( streamCipher.encrypt( (byte) b ) );
}
else
// Not encrypting.
out.write( b );
}
/// Write some bytes.
public void write( byte b[], int off, int len ) throws IOException
{
if ( encrypting )
{
if ( blockCipher != null )
{
for ( int i = off; i < off + len; ++i )
{
clearText[byteCount++] = b[i];
if ( byteCount >= cryptoSize )
sendBlock();
}
}
else
{
// Stream cipher.
byte[] cipherText = new byte[len];
streamCipher.encrypt( b, off, cipherText, 0, len );
out.write( cipherText, 0, len );
}
}
else
// Not encrypting.
out.write( b, off, len );
}
/// Flush the stream. This will write any buffered output bytes.
public void flush() throws IOException
{
if ( encrypting && blockCipher != null && byteCount != 0 )
sendBlock();
out.flush();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -