/* * EncFS Java Library * Copyright (C) 2013 encfs-java authors * * 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 * GNU Lesser General Public License for more details. */ package org.mrpdaemon.sec.encfs; import java.io.File; import java.io.IOException; import java.security.SecureRandom; /** * Class for building EncFSVolume objects and writing new volume files to file * providers. * * Usage (in order): * * [Required] .withFileProvider(provider) OR .withRootPath(rootPath) * * [Optional] .withConfig(config) AND/OR .withPbkdfProvider(pbkdf2provider) * * [Required] .withPassword(password) * * * Volume building methods: <br> * .writeVolumeConfig() - Write volume configuration file to the file provider <br> * .buildVolume() - Return an EncFSVolume */ public final class EncFSVolumeBuilder { /** * */ public static class FileProviderBuilder { private final EncFSVolume volume; public FileProviderBuilder(EncFSVolume volume, String rootPath) { this(volume, new EncFSLocalFileProvider(new File(rootPath))); } public FileProviderBuilder(EncFSVolume volume, EncFSFileProvider fileProvider) { this.volume = volume; volume.setFileProvider(fileProvider); } public ConfigBuilder withConfig(EncFSConfig config) { return new ConfigBuilder(volume, config); } public Pbkdf2ProviderBuilder withPbkdf2Provider( EncFSPBKDF2Provider pbkdf2Provider) throws EncFSUnsupportedException, IOException, EncFSInvalidConfigException { return new ConfigBuilder(volume).withPbkdf2Provider(pbkdf2Provider); } public PasswordBuilder withPassword(String password) throws EncFSUnsupportedException, IOException, EncFSInvalidConfigException, EncFSCorruptDataException, EncFSInvalidPasswordException { return withPbkdf2Provider(null).withPassword(password); } public PasswordBuilder withDerivedKeyData(byte[] derivedKeyData) throws EncFSUnsupportedException, IOException, EncFSInvalidConfigException, EncFSCorruptDataException, EncFSInvalidPasswordException { return withPbkdf2Provider(null).withDerivedKeyData(derivedKeyData); } } /** * */ public static class ConfigBuilder { private final EncFSVolume volume; public ConfigBuilder(EncFSVolume volume, EncFSConfig config) { this.volume = volume; volume.setVolumeConfig(config); } public ConfigBuilder(EncFSVolume volume) throws EncFSUnsupportedException, IOException, EncFSInvalidConfigException { this.volume = volume; EncFSFileProvider fileProvider = volume.getFileProvider(); EncFSConfig volumeConfiguration = EncFSConfigParser.parseConfig( fileProvider, EncFSVolume.CONFIG_FILE_NAME); volume.setVolumeConfig(volumeConfiguration); } public Pbkdf2ProviderBuilder withPbkdf2Provider( EncFSPBKDF2Provider provider) { return new Pbkdf2ProviderBuilder(volume, provider); } public PasswordBuilder withPassword(String password) throws EncFSCorruptDataException, EncFSInvalidPasswordException, EncFSInvalidConfigException, EncFSUnsupportedException, IOException { return withPbkdf2Provider(null).withPassword(password); } public PasswordBuilder withDerivedKeyData(byte[] derivedKeyData) throws EncFSUnsupportedException, IOException, EncFSInvalidConfigException, EncFSCorruptDataException, EncFSInvalidPasswordException { return withPbkdf2Provider(null).withDerivedKeyData(derivedKeyData); } } /** * */ public static class Pbkdf2ProviderBuilder { private final EncFSVolume volume; private final EncFSPBKDF2Provider provider; public Pbkdf2ProviderBuilder(EncFSVolume volume, EncFSPBKDF2Provider provider) { this.volume = volume; this.provider = provider; } public PasswordBuilder withPassword(String password) { return new PasswordBuilder(volume, password, provider); } public PasswordBuilder withDerivedKeyData(byte[] derivedKeyData) { return new PasswordBuilder(volume, derivedKeyData); } } /** * */ public static class PasswordBuilder { private final EncFSVolume volume; private final EncFSPBKDF2Provider provider; private final String password; public PasswordBuilder(EncFSVolume volume, byte[] derivedPassword) { this.volume = volume; this.provider = null; this.password = null; volume.setDerivedKeyData(derivedPassword); } public PasswordBuilder(EncFSVolume volume, String password, EncFSPBKDF2Provider provider) { this.volume = volume; this.password = password; this.provider = provider; } /** * Creates a new object representing an existing EncFS volume * * @throws EncFSInvalidPasswordException * Given password is incorrect * @throws EncFSCorruptDataException * Corrupt data detected (checksum error) * @throws EncFSInvalidConfigException * Configuration file format not recognized * @throws EncFSUnsupportedException * Unsupported EncFS version or options * @throws IOException * File provider returned I/O error */ public EncFSVolume buildVolume() throws EncFSUnsupportedException, IOException, EncFSInvalidConfigException, EncFSInvalidPasswordException, EncFSCorruptDataException { EncFSConfig config = volume.getConfig(); if (password!=null) { byte[] derivedKeyData = VolumeKey.deriveKeyDataFromPassword( config, password, provider); volume.setDerivedKeyData(derivedKeyData); } volume.readConfigAndInitVolume(); return volume; } /** * Writes EncFS volume configuration to the file provider * * @throws EncFSInvalidPasswordException * Given password is incorrect * @throws EncFSCorruptDataException * Corrupt data detected (checksum error) * @throws EncFSInvalidConfigException * Configuration file format not recognized * @throws EncFSUnsupportedException * Unsupported EncFS version or options * @throws IOException * File provider returned I/O error */ public void writeVolumeConfig() throws EncFSUnsupportedException, IOException, EncFSInvalidConfigException, EncFSCorruptDataException { EncFSConfig config = volume.getConfig(); EncFSFileProvider fileProvider = volume.getFileProvider(); // Create a random volume VolumeCryptKey + IV pair byte[] randVolKey = new byte[config.getVolumeKeySizeInBits()/8 +EncFSVolume.IV_LENGTH_IN_BYTES]; new SecureRandom().nextBytes(randVolKey); VolumeKey.encodeVolumeKey(config, password, randVolKey, provider); EncFSConfigWriter.writeConfig(fileProvider, config); } } public FileProviderBuilder withRootPath(String rootPath) { return new FileProviderBuilder(new EncFSVolume(), rootPath); } public FileProviderBuilder withFileProvider(EncFSFileProvider fileProvider) { return new FileProviderBuilder(new EncFSVolume(), fileProvider); } }