@Override public InputStream createInputStream(InputStream in) throws IOException { if (cipherSession == null) { throw new RuntimeException("Cipher session is not initialized. Call init() before!"); } return new MultiCipherInputStream(in, cipherSession); }
private void readHeader() throws IOException { if (!headerRead) { try { readAndVerifyMagicNoHmac(underlyingInputStream); readAndVerifyVersionNoHmac(underlyingInputStream); headerHmac = readHmacSaltAndInitHmac(underlyingInputStream, cipherSession); cipherInputStream = readCipherSpecsAndUpdateHmac(underlyingInputStream, headerHmac, cipherSession); readAndVerifyHmac(underlyingInputStream, headerHmac); } catch (Exception e) { throw new IOException(e); } headerRead = true; } }
@Override public int read(byte[] b) throws IOException { readHeader(); return cipherInputStream.read(b, 0, b.length); }
public static byte[] decrypt(InputStream fromInputStream, SaltedSecretKey masterKey) throws CipherException { try { CipherSession cipherSession = new CipherSession(masterKey); MultiCipherInputStream multiCipherInputStream = new MultiCipherInputStream(fromInputStream, cipherSession); ByteArrayOutputStream plaintextOutputStream = new ByteArrayOutputStream(); int read = -1; byte[] buffer = new byte[4096]; while (-1 != (read = multiCipherInputStream.read(buffer))) { plaintextOutputStream.write(buffer, 0, read); } multiCipherInputStream.close(); plaintextOutputStream.close(); return plaintextOutputStream.toByteArray(); } catch (IOException e) { throw new CipherException(e); } }
private InputStream readCipherSpecsAndUpdateHmac(InputStream underlyingInputStream, Mac hmac, CipherSession cipherSession) throws Exception { int cipherSpecCount = readByteAndUpdateHmac(underlyingInputStream, hmac); InputStream nestedCipherInputStream = underlyingInputStream; for (int i=0; i<cipherSpecCount; i++) { int cipherSpecId = readByteAndUpdateHmac(underlyingInputStream, hmac); CipherSpec cipherSpec = CipherSpecs.getCipherSpec(cipherSpecId); if (cipherSpec == null) { throw new IOException("Cannot find cipher spec with ID "+cipherSpecId); } byte[] salt = readAndUpdateHmac(underlyingInputStream, MultiCipherOutputStream.SALT_SIZE, hmac); byte[] iv = readAndUpdateHmac(underlyingInputStream, cipherSpec.getIvSize()/8, hmac); SecretKey secretKey = cipherSession.getReadSecretKey(cipherSpec, salt); nestedCipherInputStream = cipherSpec.newCipherInputStream(nestedCipherInputStream, secretKey.getEncoded(), iv); } return nestedCipherInputStream; }
@Override public int read() throws IOException { readHeader(); return cipherInputStream.read(); }
@Override public int read(byte[] b, int off, int len) throws IOException { readHeader(); return cipherInputStream.read(b, off, len); }