Skip to content

Commit

Permalink
File content encryption and decryption (still without padding, no par…
Browse files Browse the repository at this point in the history
…tial support)
  • Loading branch information
Sebastian Stenzel committed Dec 19, 2015
1 parent 4e0143e commit 3045805
Show file tree
Hide file tree
Showing 16 changed files with 519 additions and 72 deletions.
6 changes: 0 additions & 6 deletions main/filesystem-crypto/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,6 @@
<artifactId>bcprov-jdk15on</artifactId>
<version>${bouncycastle.version}</version>
</dependency>

<!-- Guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>

<!-- Commons -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
*/
public interface FileContentCryptor {

public static final ByteBuffer EOF = ByteBuffer.allocate(0);

/**
* @return The fixed number of bytes of the file header. The header length is implementation-specific.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package org.cryptomator.crypto.engine;

import java.io.Closeable;
import java.nio.ByteBuffer;

import javax.security.auth.Destroyable;

/**
* Stateful, thus not thread-safe.
*/
public interface FileContentDecryptor extends Destroyable {

public static final ByteBuffer EOF = ByteBuffer.allocate(0);
public interface FileContentDecryptor extends Destroyable, Closeable {

/**
* @return Number of bytes of the decrypted file.
Expand All @@ -19,7 +18,7 @@ public interface FileContentDecryptor extends Destroyable {
/**
* Appends further ciphertext to this decryptor. This method might block until space becomes available. If so, it is interruptable.
*
* @param cleartext Cleartext data or {@link #EOF} to indicate the end of a ciphertext.
* @param cleartext Cleartext data or {@link FileContentCryptor#EOF} to indicate the end of a ciphertext.
* @see #skipToPosition(long)
*/
void append(ByteBuffer ciphertext);
Expand All @@ -30,7 +29,7 @@ public interface FileContentDecryptor extends Destroyable {
*
* This method might block if no cleartext is available yet.
*
* @return Decrypted cleartext or {@link #EOF}.
* @return Decrypted cleartext or {@link FileContentCryptor#EOF}.
*/
ByteBuffer cleartext() throws InterruptedException;

Expand All @@ -57,4 +56,9 @@ public interface FileContentDecryptor extends Destroyable {
@Override
void destroy();

@Override
default void close() {
this.destroy();
}

}
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package org.cryptomator.crypto.engine;

import java.io.Closeable;
import java.nio.ByteBuffer;

import javax.security.auth.Destroyable;

/**
* Stateful, thus not thread-safe.
*/
public interface FileContentEncryptor extends Destroyable {

public static final ByteBuffer EOF = ByteBuffer.allocate(0);
public interface FileContentEncryptor extends Destroyable, Closeable {

/**
* Creates the encrypted file header. This header might depend on the already encrypted data,
Expand All @@ -22,7 +21,7 @@ public interface FileContentEncryptor extends Destroyable {
/**
* Appends further cleartext to this encryptor. This method might block until space becomes available.
*
* @param cleartext Cleartext data or {@link #EOF} to indicate the end of a cleartext.
* @param cleartext Cleartext data or {@link FileContentCryptor#EOF} to indicate the end of a cleartext.
*/
void append(ByteBuffer cleartext);

Expand All @@ -32,7 +31,7 @@ public interface FileContentEncryptor extends Destroyable {
*
* This method might block if no ciphertext is available yet.
*
* @return Encrypted ciphertext of {@link #EOF}.
* @return Encrypted ciphertext of {@link FileContentCryptor#EOF}.
*/
ByteBuffer ciphertext() throws InterruptedException;

Expand All @@ -59,4 +58,9 @@ public interface FileContentEncryptor extends Destroyable {
@Override
void destroy();

@Override
default void close() {
this.destroy();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.cryptomator.crypto.engine.impl;

import java.io.Closeable;
import java.nio.ByteBuffer;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.commons.lang3.concurrent.ConcurrentUtils;

abstract class AbstractFileContentProcessor implements Closeable {

private static final int NUM_WORKERS = Runtime.getRuntime().availableProcessors();
private static final int READ_AHEAD = 0;

private final BlockingQueue<BytesWithSequenceNumber> processedData = new PriorityBlockingQueue<>();
private final BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(NUM_WORKERS + READ_AHEAD);
private final ExecutorService executorService = new ThreadPoolExecutor(1, NUM_WORKERS, 1, TimeUnit.SECONDS, workQueue);
private final AtomicLong jobSequence = new AtomicLong();

/**
* Enqueues a job for execution. The results of multiple submissions can be polled in FIFO order using {@link #processedData()}.
*
* @param processingJob A ByteBuffer-generating task.
*/
protected void submit(Callable<ByteBuffer> processingJob) {
Future<ByteBuffer> result = executorService.submit(processingJob);
processedData.offer(new BytesWithSequenceNumber(result, jobSequence.getAndIncrement()));
}

/**
* Submits already processed data, that can be polled in FIFO order from {@link #processedData()}.
*/
protected void submitPreprocessed(ByteBuffer preprocessedData) {
Future<ByteBuffer> resolvedFuture = ConcurrentUtils.constantFuture(preprocessedData);
processedData.offer(new BytesWithSequenceNumber(resolvedFuture, jobSequence.getAndIncrement()));
}

/**
* Result of previously {@link #submit(Callable) submitted} jobs in the same order as they have been submitted. Blocks if the job didn't finish yet.
*
* @return Next job result
* @throws InterruptedException If the calling thread was interrupted while waiting for the next result.
*/
protected ByteBuffer processedData() throws InterruptedException {
return processedData.take().get();
}

@Override
public void close() {
executorService.shutdown();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,17 @@ public int getHeaderSize() {

@Override
public FileContentDecryptor createFileContentDecryptor(ByteBuffer header) {
throw new UnsupportedOperationException("Method not implemented");
if (header.remaining() != getHeaderSize()) {
throw new IllegalArgumentException("Invalid header.");
}
return new FileContentDecryptorImpl(encryptionKey, macKey, header);
}

@Override
public FileContentEncryptor createFileContentEncryptor(Optional<ByteBuffer> header) {
if (header.isPresent() && header.get().remaining() != getHeaderSize()) {
throw new IllegalArgumentException("Invalid header.");
}
return new FileContentEncryptorImpl(encryptionKey, macKey, randomSource);
}

Expand Down
Loading

0 comments on commit 3045805

Please sign in to comment.