protected abstract Cipher initCipherForBlock(Cipher existing, int block) throws GeneralSecurityException;
public ChunkedCipherInputStream(InputStream stream, long size, int chunkSize, int initialPos) throws GeneralSecurityException { super(stream); this.size = size; this.pos = initialPos; this.chunkSize = chunkSize; int cs = chunkSize == -1 ? 4096 : chunkSize; this.chunk = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH); this.plain = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH); this.chunkBits = Integer.bitCount(chunk.length-1); this.lastIndex = (int)(pos >> chunkBits); this.cipher = initCipherForBlock(null, lastIndex); }
private void nextChunk() throws GeneralSecurityException, IOException { if (chunkSize != -1) { int index = (int)(pos >> chunkBits); initCipherForBlock(cipher, index); if (lastIndex != index) { long skipN = (index - lastIndex) << chunkBits; if (super.skip(skipN) < skipN) { throw new EOFException("buffer underrun"); } } lastIndex = index + 1; } final int todo = (int)Math.min(size, chunk.length); int readBytes, totalBytes = 0; do { readBytes = super.read(plain, totalBytes, todo-totalBytes); totalBytes += Math.max(0, readBytes); } while (readBytes != -1 && totalBytes < todo); if (readBytes == -1 && pos+totalBytes < size && size < Integer.MAX_VALUE) { throw new EOFException("buffer underrun"); } System.arraycopy(plain, 0, chunk, 0, totalBytes); invokeCipher(totalBytes, totalBytes == chunkSize); }
protected abstract Cipher initCipherForBlock(Cipher existing, int block) throws GeneralSecurityException;
public ChunkedCipherInputStream(InputStream stream, long size, int chunkSize, int initialPos) throws GeneralSecurityException { super(stream); this.size = size; this.pos = initialPos; this.chunkSize = chunkSize; int cs = chunkSize == -1 ? 4096 : chunkSize; this.chunk = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH); this.plain = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH); this.chunkBits = Integer.bitCount(chunk.length-1); this.lastIndex = (int)(pos >> chunkBits); this.cipher = initCipherForBlock(null, lastIndex); }
private void nextChunk() throws GeneralSecurityException, IOException { if (chunkSize != -1) { int index = (int)(pos >> chunkBits); initCipherForBlock(cipher, index); if (lastIndex != index) { long skipN = (index - lastIndex) << chunkBits; if (super.skip(skipN) < skipN) { throw new EOFException("buffer underrun"); } } lastIndex = index + 1; } final int todo = (int)Math.min(size, chunk.length); int readBytes, totalBytes = 0; do { readBytes = super.read(plain, totalBytes, todo-totalBytes); totalBytes += Math.max(0, readBytes); } while (readBytes != -1 && totalBytes < todo); if (readBytes == -1 && pos+totalBytes < size && size < Integer.MAX_VALUE) { throw new EOFException("buffer underrun"); } System.arraycopy(plain, 0, chunk, 0, totalBytes); invokeCipher(totalBytes, totalBytes == chunkSize); }
protected void decryptRecord(byte[] docstream, int persistId, int offset) { if (dea == null) { return; } Decryptor dec = getEncryptionInfo().getDecryptor(); dec.setChunkSize(-1); try (LittleEndianByteArrayInputStream lei = new LittleEndianByteArrayInputStream(docstream, offset); ChunkedCipherInputStream ccis = (ChunkedCipherInputStream)dec.getDataStream(lei, docstream.length-offset, 0)) { ccis.initCipherForBlock(persistId); // decrypt header and read length to be decrypted readFully(ccis, docstream, offset, 8); // decrypt the rest of the record int rlen = (int)LittleEndian.getUInt(docstream, offset+4); readFully(ccis, docstream, offset+8, rlen); } catch (Exception e) { throw new EncryptedPowerPointFileException(e); } }