master
Lars Gohlke 2013-02-17 17:04:35 +01:00
parent 556dd427b7
commit 6c5757f1f9
3 changed files with 49 additions and 85 deletions

View File

@ -1,12 +1,12 @@
/*
* EncFS Java Library
* Copyright (C) 2011
* Copyright (C) 2011
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@ -23,28 +23,17 @@ import java.io.IOException;
*/
public class EncFSFileOutputStream extends FilterOutputStream {
/**
* Creates an EncFSFileOutputStream to write encrypted data to a file under
* and EncFS volume
*
* @param encfsFile
* EncFSFile to open an output stream to
* @param inputLength
* Length of the input file that will be written to this output
* stream. Note that this parameter is optional if using
* EncFSLocalFileProvider, but some network based storage API's
* require knowing the file length in advance.
*
* @throws EncFSCorruptDataException
* Filename encoding failed
* @throws EncFSUnsupportedException
* File header uses an unsupported IV length
* @throws IOException
* File provider returned I/O error
*/
public EncFSFileOutputStream(EncFSFile encfsFile, long inputLength)
throws IOException, EncFSUnsupportedException,
EncFSCorruptDataException, EncFSChecksumException {
super(encfsFile.openOutputStream(inputLength));
}
/**
* Creates an EncFSFileOutputStream to write encrypted data to a file under
* and EncFS volume
*
* @param encfsFile EncFSFile to open an output stream to
* @param inputLength Length of the input file that will be written to this output
* stream. Note that this parameter is optional if using
* EncFSLocalFileProvider, but some network based storage API's
* require knowing the file length in advance.
*/
public EncFSFileOutputStream(EncFSFile encfsFile, long inputLength) throws IOException, EncFSUnsupportedException, EncFSCorruptDataException {
super(encfsFile.openOutputStream(inputLength));
}
}

View File

@ -15,14 +15,13 @@
package org.mrpdaemon.sec.encfs;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidAlgorithmParameterException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
/**
* FilterInputStream extension that allows decrypted data to be read from a file
* on an EncFS volume.
@ -41,10 +40,7 @@ public class EncFSInputStream extends FilterInputStream {
// Number of MAC bytes for each block
private final int numMACBytes;
// Number of random bytes for each block header
private final int numRandBytes;
// Size of the block header for each block
// Size of the block header for each block
private final int blockHeaderSize;
// Current block number for generating block IV
@ -70,13 +66,6 @@ public class EncFSInputStream extends FilterInputStream {
* @param volumePath
* Volume path of the file being decrypted (needed for
* externalIVChaining)
*
* @throws EncFSCorruptDataException
* File data is corrupt
* @throws EncFSUnsupportedException
* Unsupported EncFS configuration
* @throws IOException
* File provider returned I/O error
*/
public EncFSInputStream(EncFSVolume volume, InputStream in,
String volumePath) throws EncFSCorruptDataException,
@ -86,8 +75,8 @@ public class EncFSInputStream extends FilterInputStream {
this.config = volume.getConfig();
this.blockSize = config.getEncryptedFileBlockSizeInBytes();
this.numMACBytes = config.getNumberOfMACBytesForEachFileBlock();
this.numRandBytes = config.getNumberOfRandomBytesInEachMACHeader();
this.blockHeaderSize = this.numMACBytes + this.numRandBytes;
int numRandBytes = config.getNumberOfRandomBytesInEachMACHeader();
this.blockHeaderSize = this.numMACBytes + numRandBytes;
this.blockBuf = null;
this.bufCursor = 0;
this.blockNum = 0;
@ -161,14 +150,12 @@ public class EncFSInputStream extends FilterInputStream {
*/
@Override
public int read(byte[] output, int offset, int size) throws IOException {
byte[] b = output;
int len = size;
int bytesRead = 0;
int bytesRead = 0;
int destOffset = offset;
int bytesToCopy;
int ret;
while (bytesRead < len) {
while (bytesRead < size) {
// Read more data if the data buffer is out
if ((blockBuf == null) || (bufCursor == (blockBuf.length))) {
@ -190,8 +177,8 @@ public class EncFSInputStream extends FilterInputStream {
}
bytesToCopy = Math
.min(blockBuf.length - bufCursor, len - bytesRead);
System.arraycopy(blockBuf, bufCursor, b, destOffset, bytesToCopy);
.min(blockBuf.length - bufCursor, size - bytesRead);
System.arraycopy(blockBuf, bufCursor, output, destOffset, bytesToCopy);
bufCursor += bytesToCopy;
bytesRead += bytesToCopy;
@ -260,7 +247,7 @@ public class EncFSInputStream extends FilterInputStream {
boolean zeroBlock = false;
int bytesRead = 0;
int lastBytesRead = 0;
int lastBytesRead ;
// Read until we read a whole block or we reach the end of the input
while (bytesRead < blockSize) {
@ -288,15 +275,15 @@ public class EncFSInputStream extends FilterInputStream {
*/
if (config.isHolesAllowedInFiles()) {
zeroBlock = true;
for (int i = 0; i < cipherBuf.length; i++)
if (cipherBuf[i] != 0) {
zeroBlock = false;
break;
}
for (byte aCipherBuf : cipherBuf)
if (aCipherBuf != 0) {
zeroBlock = false;
break;
}
}
try {
if (zeroBlock == true) {
if (zeroBlock) {
blockBuf = cipherBuf;
} else {
blockBuf = EncFSCrypto.blockDecode(volume, getBlockIV(),
@ -328,7 +315,7 @@ public class EncFSInputStream extends FilterInputStream {
}
// Verify the block header
if ((bytesRead > 0) && (blockHeaderSize > 0) && (zeroBlock == false)) {
if ((bytesRead > 0) && (blockHeaderSize > 0) && (!zeroBlock)) {
byte mac[] = EncFSCrypto.mac64(volume.getMac(), blockBuf,
numMACBytes);
for (int i = 0; i < numMACBytes; i++) {

View File

@ -15,6 +15,9 @@
package org.mrpdaemon.sec.encfs;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@ -22,10 +25,6 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.SecureRandom;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
/**
* FilterOutputStream extension that allows encrypted data to be written to a
* file on an EncFS volume.
@ -41,10 +40,7 @@ public class EncFSOutputStream extends FilterOutputStream {
// Volume configuration
private final EncFSConfig config;
// Block size for the file
private final int blockSize;
// IV used for this file
// IV used for this file
private byte[] fileIv;
// Buffer to hold file header contents (uniqueIV)
@ -68,13 +64,7 @@ public class EncFSOutputStream extends FilterOutputStream {
// Index of the current block to be written
private int curBlockIndex;
// Cipher to use for block encryption
private final Cipher blockCipher;
// Cipher to use for stream encryption
private final Cipher streamCipher;
/**
/**
* Create a new EncFSOutputStream for writing encrypted data to a file on an
* EncFS volume
*
@ -97,7 +87,7 @@ public class EncFSOutputStream extends FilterOutputStream {
super(out);
this.volume = volume;
this.config = volume.getConfig();
this.blockSize = config.getEncryptedFileBlockSizeInBytes();
int blockSize = config.getEncryptedFileBlockSizeInBytes();
this.blockHeaderSize = config.getNumberOfMACBytesForEachFileBlock()
+ config.getNumberOfRandomBytesInEachMACHeader();
this.dataBytes = this.blockHeaderSize;
@ -137,14 +127,14 @@ public class EncFSOutputStream extends FilterOutputStream {
this.fileIv = new byte[8];
}
this.blockCipher = EncFSCrypto.newBlockCipher();
Cipher blockCipher = EncFSCrypto.newBlockCipher();
try {
EncFSCrypto.cipherInit(volume, Cipher.ENCRYPT_MODE, blockCipher,
fileIv);
} catch (InvalidAlgorithmParameterException e) {
throw new EncFSCorruptDataException(e);
}
this.streamCipher = EncFSCrypto.newStreamCipher();
Cipher streamCipher = EncFSCrypto.newStreamCipher();
try {
EncFSCrypto.cipherInit(volume, Cipher.ENCRYPT_MODE, streamCipher,
fileIv);
@ -159,7 +149,7 @@ public class EncFSOutputStream extends FilterOutputStream {
// Flush the internal buffer
private void writeBuffer(boolean isFinal) throws IOException {
if (isFinal == false && dataBytes != dataBuf.length) {
if (!isFinal && dataBytes != dataBuf.length) {
throw new IllegalStateException("Buffer not full");
}
@ -174,9 +164,7 @@ public class EncFSOutputStream extends FilterOutputStream {
if (blockMACRandLen > 0) {
byte randomBytes[] = new byte[blockMACRandLen];
secureRandom.nextBytes(randomBytes);
for (int i = 0; i < blockMACRandLen; i++) {
dataBuf[blockMACLen + i] = randomBytes[i];
}
System.arraycopy(randomBytes, 0, dataBuf, blockMACLen , blockMACRandLen);
}
// Compute MAC bytes and add them to the buffer
@ -199,15 +187,15 @@ public class EncFSOutputStream extends FilterOutputStream {
boolean zeroBlock = false;
if (config.isHolesAllowedInFiles()) {
zeroBlock = true;
for (int i = 0; i < dataBuf.length; i++) {
if (dataBuf[i] != 0) {
zeroBlock = false;
break;
}
}
for (byte aDataBuf : dataBuf) {
if (aDataBuf != 0) {
zeroBlock = false;
break;
}
}
}
if (zeroBlock == true) {
if (zeroBlock) {
encBuffer = dataBuf;
} else {
encBuffer = EncFSCrypto.blockEncode(volume, getBlockIV(),