1 29 package Acme.Crypto; 30 31 import java.io.*; 32 33 61 public class EncryptedInputStream extends FilterInputStream 62 { 63 64 private BlockCipher blockCipher = null; 66 67 private StreamCipher streamCipher = null; 69 70 private Cipher cipher; 72 73 private CbcBlockCipher cbcBlockCipher = null; 75 76 private int blockSize; 78 79 private int cryptoSize; 81 82 private byte[] cipherText; 84 85 private byte[] clearText; 87 88 private int byteCount; 90 91 private int bytesRead; 93 94 public EncryptedInputStream( BlockCipher blockCipher, InputStream in ) 98 { 99 super( in ); 100 this.blockCipher = blockCipher; 101 this.blockSize = blockCipher.blockSize(); 102 cbcBlockCipher = new CbcBlockCipher( blockCipher ); 103 this.cryptoSize = blockSize; 104 cipherText = new byte[blockSize]; 105 clearText = new byte[blockSize]; 106 byteCount = 0; 107 bytesRead = 0; 108 this.cipher = blockCipher; 109 } 110 111 public EncryptedInputStream( StreamCipher streamCipher, InputStream in ) 115 { 116 super( in ); 117 this.streamCipher = streamCipher; 118 this.cipher = streamCipher; 119 } 120 121 122 private boolean inited = false; 123 124 private void init() throws IOException 125 { 126 if ( ! inited ) 127 { 128 inited = true; 129 if ( blockCipher != null ) 130 { 131 byte[] iv = new byte[blockSize]; 133 int r = Acme.Utils.read( in, iv, 0, blockSize ); 134 if ( r == -1 || r != blockSize ) 135 throw new IOException( "truncated initialization vector" ); 136 cbcBlockCipher.setIv( iv ); 137 } 138 } 139 } 140 141 142 public void setKey( String keyStr ) 144 { 145 cipher.setKey( keyStr ); 146 } 147 148 149 private boolean decrypting = true; 151 152 public void setDecrypting( boolean decrypting ) throws IOException 154 { 155 if ( this.decrypting && ! decrypting ) 156 { 157 } 159 this.decrypting = decrypting; 160 } 161 162 163 private int getBlock() throws IOException 165 { 166 int r = Acme.Utils.read( in, cipherText, 0, blockSize ); 167 if ( r == -1 ) 168 return -1; 169 if ( r != blockSize ) 170 throw new IOException( "truncated ciphertext block" ); 171 cbcBlockCipher.decrypt( cipherText, 0, clearText, 0 ); 173 byteCount = in.read(); 175 if ( byteCount == -1 ) 176 throw new IOException( "missing ciphertext bytecount" ); 177 if ( byteCount == 0 || byteCount > cryptoSize ) 178 throw new IOException( "invalid ciphertext bytecount" ); 179 bytesRead = 0; 180 return byteCount; 181 } 182 183 public int read() throws IOException 186 { 187 init(); 188 if ( decrypting ) 189 { 190 if ( blockCipher != null ) 191 { 192 if ( bytesRead >= byteCount ) 193 if ( getBlock() == -1 ) 194 return -1; 195 return clearText[bytesRead++] & 0xff; 196 } 197 else 198 { 199 int r = in.read(); 201 if ( r == -1 ) 202 return -1; 203 return streamCipher.decrypt( (byte) r ) & 0xff; 204 } 205 } 206 else 207 return in.read(); 209 } 210 211 public int read( byte[] b, int off, int len ) throws IOException 216 { 217 init(); 218 if ( decrypting ) 219 { 220 if ( blockCipher != null ) 221 return Acme.Utils.read( this, b, off, len ); 223 else 224 { 225 byte[] cipherText = new byte[len]; 227 int r = Acme.Utils.read( in, cipherText, 0, len ); 228 if ( r == -1 ) 229 return -1; 230 streamCipher.decrypt( cipherText, 0, b, off, r ); 231 return r; 232 } 233 } 234 else 235 return Acme.Utils.read( in, b, off, len ); 237 } 238 239 } 240 | Popular Tags |