@Test public void testSuccesfulRoundTrip() throws IOException, GeneralSecurityException{ for(EncryptedRandomAccessBufferType type: types){ byte[] bytes = new byte[100]; ByteArrayRandomAccessBuffer barat = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(type, barat, secret, true); erat.pwrite(0, message, 0, message.length); byte[] result = new byte[message.length]; erat.pread(0, result, 0, result.length); erat.close(); assertArrayEquals(message, result); } }
/** * Creates an instance of EncryptedRandomAccessBuffer wrapping underlyingBuffer. Keys for key * encryption and MAC generation are derived from the MasterSecret. If this is a new ERAT then * keys are generated and the footer is written to the end of the underlying RAT. Otherwise the * footer is read from the underlying RAT. * @param type The algorithms to be used for the ERAT * @param underlyingBuffer The underlying RAT that will be storing the data. Must be larger than * the footer size specified in type. * @param masterKey The MasterSecret that will be used to derive various keys. * @param newFile If true, treat it as a new file, and writer a header. If false, the ERAT must * already have been initialised. * @throws IOException * @throws GeneralSecurityException */ public EncryptedRandomAccessBuffer(EncryptedRandomAccessBufferType type, LockableRandomAccessBuffer underlying, MasterSecret masterKey, boolean newFile) throws IOException, GeneralSecurityException{ this.type = type; this.underlyingBuffer = underlying; setup(masterKey, newFile); }
@Test public void testClose() throws IOException, GeneralSecurityException { byte[] bytes = new byte[100]; ByteArrayRandomAccessBuffer barat = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(types[0], barat, secret, true); erat.close(); erat.close(); }
r.nextBytes(buf); FileRandomAccessBuffer rafw = new FileRandomAccessBuffer(tempFile, buf.length+types[0].headerLen, false); EncryptedRandomAccessBuffer eraf = new EncryptedRandomAccessBuffer(types[0], rafw, secret, true); eraf.pwrite(0, buf, 0, buf.length); byte[] tmp = new byte[buf.length]; eraf.pread(0, tmp, 0, buf.length); assertArrayEquals(buf, tmp); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); eraf.storeTo(dos); dos.close(); eraf.close(); DataInputStream dis = new DataInputStream(new ByteArrayInputStream(baos.toByteArray())); ClientContext context = new ClientContext(0, null, null, null, null, null, null, null, null, context.setPersistentMasterSecret(secret); EncryptedRandomAccessBuffer restored = (EncryptedRandomAccessBuffer) BucketTools.restoreRAFFrom(dis, context.persistentFG, context.persistentFileTracker, secret); assertEquals(buf.length, restored.size()); restored.pread(0, tmp, 0, buf.length); assertArrayEquals(buf, tmp); restored.close(); restored.free();
r.nextBytes(buf); FileRandomAccessBuffer rafw = new FileRandomAccessBuffer(tempFile, buf.length+types[0].headerLen, false); EncryptedRandomAccessBuffer eraf = new EncryptedRandomAccessBuffer(types[0], rafw, secret, true); eraf.pwrite(0, buf, 0, buf.length); byte[] tmp = new byte[buf.length]; eraf.pread(0, tmp, 0, buf.length); assertArrayEquals(buf, tmp); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectInputStream ois = new ObjectInputStream(dis); EncryptedRandomAccessBuffer restored = (EncryptedRandomAccessBuffer) ois.readObject(); restored.onResume(context); assertEquals(buf.length, restored.size()); assertEquals(eraf, restored); tmp = new byte[buf.length]; restored.pread(0, tmp, 0, buf.length); assertArrayEquals(buf, tmp); restored.close(); restored.free();
@Override public LockableRandomAccessBuffer toRandomAccessBuffer() throws IOException { if(underlying.size() < type.headerLen) throw new IOException("Converting empty bucket"); underlying.setReadOnly(); LockableRandomAccessBuffer r = underlying.toRandomAccessBuffer(); try { return new EncryptedRandomAccessBuffer(type, r, masterKey, false); } catch (GeneralSecurityException e) { Logger.error(this, "Unable to convert encrypted bucket: "+e, e); throw new IOException(e); } }
@Test public void testClosePread() throws IOException, GeneralSecurityException { byte[] bytes = new byte[100]; ByteArrayRandomAccessBuffer barat = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(types[0], barat, secret, true); erat.close(); byte[] result = new byte[20]; thrown.expect(IOException.class); thrown.expectMessage("This RandomAccessBuffer has already been closed. It can no longer" + " be read from."); erat.pread(0, result, 0, 20); }
@Test public void testClosePwrite() throws IOException, GeneralSecurityException { byte[] bytes = new byte[100]; ByteArrayRandomAccessBuffer barat = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(types[0], barat, secret, true); erat.close(); byte[] result = new byte[20]; thrown.expect(IOException.class); thrown.expectMessage("This RandomAccessBuffer has already been closed. It can no longer" + " be written to."); erat.pwrite(0, result, 0, 20); }
@Test public void testPwriteFileOffsetTooBig() throws IOException, GeneralSecurityException { byte[] bytes = new byte[100]; ByteArrayRandomAccessBuffer barat = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(types[0], barat, secret, true); int len = 20; byte[] result = new byte[len]; int offset = 100; thrown.expect(IOException.class); thrown.expectMessage("Cannot write after end: trying to write from "+offset+" to "+ (offset+len)+" on block length "+erat.size()); erat.pwrite(offset, result, 0, len); }
@Test public void testPreadFileOffsetTooBig() throws IOException, GeneralSecurityException { byte[] bytes = new byte[100]; ByteArrayRandomAccessBuffer barat = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(types[0], barat, secret, true); int len = 20; byte[] result = new byte[len]; int offset = 100; thrown.expect(IOException.class); thrown.expectMessage("Cannot read after end: trying to read from "+offset+" to "+ (offset+len)+" on block length "+erat.size()); erat.pread(offset, result, 0, len); }
@Test public void testSize() throws IOException, GeneralSecurityException { byte[] bytes = new byte[100]; ByteArrayRandomAccessBuffer barat = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(types[0], barat, secret, true); assertEquals(erat.size(), barat.size()-types[0].headerLen); }
@Test public void testPreadFileOffsetTooSmall() throws IOException, GeneralSecurityException { byte[] bytes = new byte[100]; ByteArrayRandomAccessBuffer barat = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(types[0], barat, secret, true); byte[] result = new byte[20]; thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Cannot read before zero"); erat.pread(-1, result, 0, 20); }
@Test public void testPwriteFileOffsetTooSmall() throws IOException, GeneralSecurityException { byte[] bytes = new byte[100]; ByteArrayRandomAccessBuffer barat = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(types[0], barat, secret, true); byte[] result = new byte[20]; thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Cannot read before zero"); erat.pwrite(-1, result, 0, 20); }
@Override public void free() { close(); underlyingBuffer.free(); }
/** Restore a LockableRandomAccessBuffer from a DataInputStream. Inverse of storeTo(). * FIXME Maybe we should just pass the ClientContext? */ public static LockableRandomAccessBuffer restoreRAFFrom(DataInputStream dis, FilenameGenerator fg, PersistentFileTracker persistentFileTracker, MasterSecret masterSecret) throws IOException, StorageFormatException, ResumeFailedException { int magic = dis.readInt(); switch(magic) { case PooledFileRandomAccessBuffer.MAGIC: return new PooledFileRandomAccessBuffer(dis, fg, persistentFileTracker); case FileRandomAccessBuffer.MAGIC: return new FileRandomAccessBuffer(dis); case ReadOnlyRandomAccessBuffer.MAGIC: return new ReadOnlyRandomAccessBuffer(dis, fg, persistentFileTracker, masterSecret); case DelayedFreeRandomAccessBuffer.MAGIC: return new DelayedFreeRandomAccessBuffer(dis, fg, persistentFileTracker, masterSecret); case EncryptedRandomAccessBuffer.MAGIC: return EncryptedRandomAccessBuffer.create(dis, fg, persistentFileTracker, masterSecret); case PaddedRandomAccessBuffer.MAGIC: return new PaddedRandomAccessBuffer(dis, fg, persistentFileTracker, masterSecret); default: throw new StorageFormatException("Unknown magic value for RAF "+magic); } }
@Test public void testWrongERATType() throws IOException, GeneralSecurityException { byte[] bytes = new byte[100]; ByteArrayRandomAccessBuffer barat = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(types[0], barat, secret, true); erat.close(); ByteArrayRandomAccessBuffer barat2 = new ByteArrayRandomAccessBuffer(bytes); thrown.expect(IOException.class); thrown.expectMessage("This is not an EncryptedRandomAccessBuffer"); // Different header lengths. EncryptedRandomAccessBuffer erat2 = new EncryptedRandomAccessBuffer(types[1], barat2, secret, false); }
@Test (expected = NullPointerException.class) public void testEncryptedRandomAccessThingNullBARAT() throws GeneralSecurityException, IOException { ByteArrayRandomAccessBuffer barat = null; EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(types[0], barat, secret, true); }
@Test public void testSuccesfulRoundTripReadHeader() throws IOException, GeneralSecurityException{ for(EncryptedRandomAccessBufferType type: types){ byte[] bytes = new byte[100]; ByteArrayRandomAccessBuffer barat = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(type, barat, secret, true); erat.pwrite(0, message, 0, message.length); erat.close(); ByteArrayRandomAccessBuffer barat2 = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat2 = new EncryptedRandomAccessBuffer(type, barat2, secret, false); byte[] result = new byte[message.length]; erat2.pread(0, result, 0, result.length); erat2.close(); assertArrayEquals(message, result); } }
@Test public void testWrongMagic() throws IOException, GeneralSecurityException{ byte[] bytes = new byte[100]; ByteArrayRandomAccessBuffer barat = new ByteArrayRandomAccessBuffer(bytes); EncryptedRandomAccessBuffer erat = new EncryptedRandomAccessBuffer(types[0], barat, secret, true); erat.close(); ByteArrayRandomAccessBuffer barat2 = new ByteArrayRandomAccessBuffer(bytes); byte[] magic = ByteBuffer.allocate(8).putLong(falseMagic).array(); barat2.pwrite(types[0].headerLen-8, magic, 0, 8); thrown.expect(IOException.class); thrown.expectMessage("This is not an EncryptedRandomAccessBuffer!"); EncryptedRandomAccessBuffer erat2 = new EncryptedRandomAccessBuffer(types[0], barat2, secret, false); }