From 9433c22d7f2e25f3986f71e4c74ddf1970612b0d Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Sun, 1 Mar 2015 20:55:32 +0100 Subject: [PATCH] minor I/O improvements --- .../jackrabbit/resources/EncryptedDir.java | 8 ++++---- .../jackrabbit/resources/EncryptedFile.java | 18 +++++++----------- .../resources/EncryptedFilePart.java | 7 +------ .../crypto/aes256/Aes256Cryptor.java | 15 +++++++++++++-- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedDir.java b/main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedDir.java index 8c95b62b3..81c139d71 100644 --- a/main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedDir.java +++ b/main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedDir.java @@ -11,6 +11,7 @@ package org.cryptomator.webdav.jackrabbit.resources; import java.io.IOException; import java.nio.channels.SeekableByteChannel; import java.nio.file.DirectoryStream; +import java.nio.file.FileAlreadyExistsException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; @@ -78,17 +79,16 @@ public class EncryptedDir extends AbstractEncryptedNode { private void addMemberFile(DavResource resource, InputContext inputContext) throws DavException { final Path childPath = ResourcePathUtils.getPhysicalPath(resource); - SeekableByteChannel channel = null; - try { - channel = Files.newByteChannel(childPath, StandardOpenOption.WRITE, StandardOpenOption.CREATE); + try (final SeekableByteChannel channel = Files.newByteChannel(childPath, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW)) { cryptor.encryptFile(inputContext.getInputStream(), channel); } catch (SecurityException e) { throw new DavException(DavServletResponse.SC_FORBIDDEN, e); + } catch (FileAlreadyExistsException e) { + throw new DavException(DavServletResponse.SC_CONFLICT, e); } catch (IOException e) { LOG.error("Failed to create file.", e); throw new IORuntimeException(e); } finally { - IOUtils.closeQuietly(channel); IOUtils.closeQuietly(inputContext.getInputStream()); } } diff --git a/main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedFile.java b/main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedFile.java index 83d017a8f..0568b5b75 100644 --- a/main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedFile.java +++ b/main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedFile.java @@ -16,7 +16,6 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.nio.file.attribute.BasicFileAttributes; -import org.apache.commons.io.IOUtils; import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.DavResource; import org.apache.jackrabbit.webdav.DavResourceFactory; @@ -70,9 +69,7 @@ public class EncryptedFile extends AbstractEncryptedNode { if (Files.exists(path)) { outputContext.setModificationTime(Files.getLastModifiedTime(path).toMillis()); outputContext.setProperty(HttpHeader.ACCEPT_RANGES.asString(), HttpHeaderValue.BYTES.asString()); - SeekableByteChannel channel = null; - try { - channel = Files.newByteChannel(path, StandardOpenOption.READ); + try (final SeekableByteChannel channel = Files.newByteChannel(path, StandardOpenOption.READ)) { outputContext.setContentLength(cryptor.decryptedContentLength(channel)); if (outputContext.hasStream()) { cryptor.decryptedFile(channel, outputContext.getOutputStream()); @@ -81,8 +78,6 @@ public class EncryptedFile extends AbstractEncryptedNode { LOG.warn("Unexpected end of stream (possibly client hung up)."); } catch (DecryptFailedException e) { throw new IOException("Error decrypting file " + path.toString(), e); - } finally { - IOUtils.closeQuietly(channel); } } } @@ -91,12 +86,15 @@ public class EncryptedFile extends AbstractEncryptedNode { protected void determineProperties() { final Path path = ResourcePathUtils.getPhysicalPath(this); if (Files.exists(path)) { - SeekableByteChannel channel = null; - try { - channel = Files.newByteChannel(path, StandardOpenOption.READ); + try (final SeekableByteChannel channel = Files.newByteChannel(path, StandardOpenOption.READ)) { final Long contentLength = cryptor.decryptedContentLength(channel); properties.add(new DefaultDavProperty(DavPropertyName.GETCONTENTLENGTH, contentLength)); + } catch (IOException e) { + LOG.error("Error reading filesize " + path.toString(), e); + throw new IORuntimeException(e); + } + try { final BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class); properties.add(new DefaultDavProperty(DavPropertyName.CREATIONDATE, FileTimeUtils.toRfc1123String(attrs.creationTime()))); properties.add(new DefaultDavProperty(DavPropertyName.GETLASTMODIFIED, FileTimeUtils.toRfc1123String(attrs.lastModifiedTime()))); @@ -104,8 +102,6 @@ public class EncryptedFile extends AbstractEncryptedNode { } catch (IOException e) { LOG.error("Error determining metadata " + path.toString(), e); throw new IORuntimeException(e); - } finally { - IOUtils.closeQuietly(channel); } } } diff --git a/main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedFilePart.java b/main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedFilePart.java index c257b39fb..b3c27fb18 100644 --- a/main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedFilePart.java +++ b/main/core/src/main/java/org/cryptomator/webdav/jackrabbit/resources/EncryptedFilePart.java @@ -9,7 +9,6 @@ import java.nio.file.StandardOpenOption; import java.util.HashSet; import java.util.Set; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.MutablePair; @@ -113,9 +112,7 @@ public class EncryptedFilePart extends EncryptedFile { final Path path = ResourcePathUtils.getPhysicalPath(this); if (Files.exists(path)) { outputContext.setModificationTime(Files.getLastModifiedTime(path).toMillis()); - SeekableByteChannel channel = null; - try { - channel = Files.newByteChannel(path, StandardOpenOption.READ); + try (final SeekableByteChannel channel = Files.newByteChannel(path, StandardOpenOption.READ)) { final Long fileSize = cryptor.decryptedContentLength(channel); final Pair range = getUnionRange(fileSize); final Long rangeLength = range.getRight() - range.getLeft() + 1; @@ -130,8 +127,6 @@ public class EncryptedFilePart extends EncryptedFile { } } catch (DecryptFailedException e) { throw new IOException("Error decrypting file " + path.toString(), e); - } finally { - IOUtils.closeQuietly(channel); } } } diff --git a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java index 0f2b3ee44..6b96859d2 100644 --- a/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java +++ b/main/crypto-aes/src/main/java/org/cryptomator/crypto/aes256/Aes256Cryptor.java @@ -504,9 +504,20 @@ public class Aes256Cryptor extends AbstractCryptor implements AesCryptographicCo final ByteBuffer macBuffer = ByteBuffer.allocate(mac.getMacLength()); encryptedFile.write(macBuffer); - // init filesize buffer and skip 16 bytes + // write initial file size = 0 into the next 16 bytes final ByteBuffer encryptedFileSizeBuffer = ByteBuffer.allocate(AES_BLOCK_LENGTH); - encryptedFile.write(encryptedFileSizeBuffer); + try { + final ByteBuffer fileSizeBuffer = ByteBuffer.allocate(Long.BYTES); + fileSizeBuffer.putLong(0l); + final Cipher sizeCipher = aesEcbCipher(primaryMasterKey, Cipher.ENCRYPT_MODE); + final byte[] encryptedFileSize = sizeCipher.doFinal(fileSizeBuffer.array()); + encryptedFileSizeBuffer.position(0); + encryptedFileSizeBuffer.put(encryptedFileSize); + encryptedFileSizeBuffer.position(0); + encryptedFile.write(encryptedFileSizeBuffer); + } catch (IllegalBlockSizeException | BadPaddingException e) { + throw new IllegalStateException("Block size must be valid, as padding is requested. BadPaddingException not possible in encrypt mode.", e); + } // write content: final OutputStream out = new SeekableByteChannelOutputStream(encryptedFile);