├── .gitignore
├── AUTHORS
├── LICENSE
├── README.md
├── pom.xml
├── src
├── main
│ ├── java
│ │ ├── EncFSShell.java
│ │ └── org
│ │ │ └── mrpdaemon
│ │ │ └── sec
│ │ │ └── encfs
│ │ │ ├── BasicFilenameDecryptionStrategy.java
│ │ │ ├── BasicFilenameEncryptionStrategy.java
│ │ │ ├── BlockCrypto.java
│ │ │ ├── BlockFilenameDecryptionStrategy.java
│ │ │ ├── BlockFilenameEncryptionStrategy.java
│ │ │ ├── EncFSBase64.java
│ │ │ ├── EncFSChecksumException.java
│ │ │ ├── EncFSConfig.java
│ │ │ ├── EncFSConfigFactory.java
│ │ │ ├── EncFSConfigParser.java
│ │ │ ├── EncFSConfigWriter.java
│ │ │ ├── EncFSCorruptDataException.java
│ │ │ ├── EncFSCrypto.java
│ │ │ ├── EncFSException.java
│ │ │ ├── EncFSFile.java
│ │ │ ├── EncFSFileInfo.java
│ │ │ ├── EncFSFileInputStream.java
│ │ │ ├── EncFSFileOutputStream.java
│ │ │ ├── EncFSFileProvider.java
│ │ │ ├── EncFSFilenameEncryptionAlgorithm.java
│ │ │ ├── EncFSInputStream.java
│ │ │ ├── EncFSInvalidConfigException.java
│ │ │ ├── EncFSInvalidPasswordException.java
│ │ │ ├── EncFSLocalFileProvider.java
│ │ │ ├── EncFSOutputStream.java
│ │ │ ├── EncFSPBKDF2Provider.java
│ │ │ ├── EncFSProgressListener.java
│ │ │ ├── EncFSUnsupportedException.java
│ │ │ ├── EncFSUtil.java
│ │ │ ├── EncFSVolume.java
│ │ │ ├── EncFSVolumeBuilder.java
│ │ │ ├── FilenameDecryptionStrategy.java
│ │ │ ├── FilenameEncryptionStrategy.java
│ │ │ ├── NullFilenameDecryptionStrategy.java
│ │ │ ├── NullFilenameEncryptionStrategy.java
│ │ │ ├── StreamCrypto.java
│ │ │ ├── StreamFilenameDecryptionStrategy.java
│ │ │ ├── StreamFilenameEncryptionStrategy.java
│ │ │ └── VolumeKey.java
│ └── resources
│ │ └── org
│ │ └── mrpdaemon
│ │ └── sec
│ │ └── encfs
│ │ └── library.properties
└── test
│ └── java
│ └── org
│ └── mrpdaemon
│ └── sec
│ └── encfs
│ └── tests
│ ├── EncFSBase64Test.java
│ ├── EncFSComparer.java
│ ├── EncFSCryptoTest.java
│ ├── EncFSFilenameEncryptionAlgorithmTest.java
│ ├── EncFSUtilTest.java
│ ├── EncFSVolumeFileTest.java
│ ├── EncFSVolumeIntegrationTest.java
│ ├── EncFSVolumeTest.java
│ ├── EncFSVolumeTestCommon.java
│ ├── EncFSVolumeVFSTest.java
│ └── vfs
│ ├── CommonsVFSFileProvider.java
│ └── CommonsVFSRamFileProvider.java
└── test
└── encfs_samples
├── Samples.txt
├── boxcryptor_1
├── .encfs6.xml
└── W3gLoUqL-0YzUh8udP8
├── boxcryptor_2
├── .encfs6.xml
├── Z4Qzgr-iwj-1dgA
└── hc2yatLg
│ └── lcgwUaXICbCjBW4
├── boxcryptor_3
├── .encfs6.xml
├── cJTbxx2GhjzRDYYra4twBcIr0-pPGtD
└── desktop.ini
├── boxcryptor_null
├── .encfs6.xml
└── testfile.txt
├── testvol-blockmac
├── .encfs6.xml
└── 85hMcPOogQFKISDxPi,QcvlY
├── testvol-default
├── .encfs6.xml
├── kNmBCW-Coq1CvGZ1EabjsiB4
├── ko1GW2gcuNSbGWQryepRJpSC
└── qQQTyqU5n10lZYe-YTOfkTo2
├── testvol-extivchn
├── .encfs6.xml
├── CjIsKUMxWNJZJ5mLWPboFUb5
│ └── FGSPI4b,efiE-vCHTF5-XAmw7jeS35Jy,EgYsJ7nhxwRN-
└── pWxw6SiMcDvaieR0K9IS4f0n
├── testvol-nouniqueiv
├── .encfs6.xml
├── XSuCblFoZx5WZQFkf3O6E8HS
└── fFHqdbodgs8p5Q1NH,pjhHle
└── testvol-streamname
├── .encfs6.xml
└── 7W2,dU4
└── H-mMw-IyZnf6SdpOZo,
/.gitignore:
--------------------------------------------------------------------------------
1 | .classpath
2 | .project
3 | .settings
4 | eclipse_bin
5 | target
6 | .idea
7 | *.iml
8 | .vimrc
9 | cscope*
10 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
1 | Authors:
2 | Mark Pariente
3 | Andrew Ormerod
4 | Lars Gohlke
5 |
6 | Contributors:
7 | michael1 (GitHub)
8 | Zdenek Farana
9 | Joscha Feth
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | encfs-java
2 | ==========
3 |
4 | encfs-java is a Java library for accessing data in
5 | [EncFS](http://www.arg0.net/encfs) volumes. It is able to derive the volume key
6 | from a user password, decode encrypted filenames (IV chaining is implemented),
7 | decrypt file contents, create new volumes, move/copy/rename files and
8 | directories within the volume as well as encrypt file contents into the
9 | volume
10 |
11 | We do support all encfs volume configuration options, and are interoperable
12 | with the official encfs implementation (http://www.arg0.net/encfs). Currently
13 | we only support volume created with the latest version (1.7.4), but we target
14 | to be able to support volumes created with legacy versions as well.
15 |
16 | ## Building
17 |
18 | encfs-java uses [Maven](http://maven.apache.org) for building. Assuming you
19 | have a working installation, simply run the following to build the code:
20 |
21 | $ mvn compile
22 |
23 | To create a JAR file for using encfs-java from another application, do:
24 |
25 | $ mvn package
26 |
27 | Which will create a JAR file in the {$PROJECT_ROOT}/target/ directory.
28 |
29 | ## Usage
30 |
31 | This library comes with a demo/example application called EncFSShell. It is a
32 | simple shell supporting a few commands such as 'ls', 'cd', 'cat', 'mv' and 'cp'
33 | on an EncFS volume. After building the library, add the
34 | {$PROJECT_ROOT}/target/classes/ directory to your CLASSPATH, and run like so:
35 |
36 | $ java -classpath ${PROJECT_ROOT}/target/classes EncFSShell /path/to/an/encfs/volume
37 |
38 | For using the library from another project, include the .JAR file in your
39 | classpath and import the org.mrpdaemon.encfs.sec package.s
40 |
41 | ## API Documentation
42 |
43 | For API documentation, see:
44 |
45 | http://mrpdaemon.github.com/encfs-java/apidocs/index.html
46 |
47 | To test your own comment changes, generate up-to-date docs using Maven:
48 |
49 | $ mvn javadoc:javadoc
50 |
51 | Which will place your documentation in ${PROJECT_ROOT}/target/site/apidocs/
52 |
53 | ## Common issues
54 |
55 | If you are getting an exception due to "Illegal key size" and you are using Sun's JDK,
56 | you need to install the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction
57 | Policy Files. See the following link for more information:
58 |
59 | Java 6 JCE Link http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
60 | Java 7 JCE Link http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
61 | Java 8 JCE Link http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
62 | Extract files into JDK/JRE/lib/security folder (To whichever version of JRE/JDK x64/x86 you are using)
63 |
64 | Thanks to aormerod for pointing this out!
65 |
66 | ## Licensing
67 |
68 | encfs-java is licensed under the Lesser GNU Public License, which allows non-GPL
69 | applications to make use of the library with the restriction that the source code
70 | for any modifications to the library itself need to be made available to be able
71 | to legally redistribute the modified library. For more information, please see the
72 | LICENSE file and the Free Software Foundation
73 | [website](http://www.gnu.org/licenses/lgpl.html).
74 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | org.mrpdaemon.sec.encfs
5 | encfs-java
6 | jar
7 | 0.9-dev
8 | encfs-java
9 | http://maven.apache.org
10 |
11 | UTF-8
12 |
13 |
14 |
15 |
16 | junit
17 | junit
18 | 4.10
19 | test
20 |
21 |
22 | org.slf4j
23 | slf4j-api
24 | 1.6.4
25 |
26 |
27 | org.slf4j
28 | slf4j-simple
29 | 1.6.4
30 | test
31 |
32 |
33 | org.apache.commons
34 | commons-vfs2
35 | 2.0
36 | test
37 |
38 |
39 |
40 |
41 |
42 | org.apache.maven.plugins
43 | maven-jar-plugin
44 | 2.4
45 |
46 |
47 |
48 | EncFSShell
49 |
50 |
51 |
52 |
53 |
54 | maven-compiler-plugin
55 | 3.0
56 |
57 | UTF-8
58 | 1.6
59 | 1.6
60 |
61 |
62 |
63 | maven-surefire-plugin
64 | 2.12.4
65 |
66 | methods
67 |
68 |
69 |
70 |
71 |
72 |
73 | src/main/resources
74 | true
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/BasicFilenameDecryptionStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | import java.util.Arrays;
18 |
19 | // Common class for filename decryption strategies
20 | abstract class BasicFilenameDecryptionStrategy extends
21 | FilenameDecryptionStrategy {
22 |
23 | BasicFilenameDecryptionStrategy(EncFSVolume volume, String volumePath,
24 | EncFSFilenameEncryptionAlgorithm algorithm) {
25 | super(volume, volumePath, algorithm);
26 | }
27 |
28 | // Actual decryption to be implemented by the subclass
29 | protected abstract byte[] decryptConcrete(EncFSVolume volume,
30 | byte[] encFileName, byte[] fileIv) throws EncFSCorruptDataException;
31 |
32 | // Filename decryption implementation
33 | protected String decryptImpl(String fileName)
34 | throws EncFSCorruptDataException, EncFSChecksumException {
35 | EncFSVolume volume = getVolume();
36 | String volumePath = getVolumePath();
37 | EncFSConfig config = volume.getConfig();
38 |
39 | byte[] chainIv = EncFSCrypto.computeChainedIV(volume, volumePath,
40 | config);
41 | byte[] base256FileName = EncFSBase64.decodeEncfs(fileName.getBytes());
42 | byte[] macBytes;
43 |
44 | try {
45 | macBytes = EncFSCrypto.getMacBytes(base256FileName);
46 | } catch (ArrayIndexOutOfBoundsException e) {
47 | /*
48 | * It's possible for fileName to be malformed so as to make
49 | * base256FileName shorter than 2 bytes. In this case, getMacBytes()
50 | * will throw an exception.
51 | */
52 | throw new EncFSCorruptDataException(e);
53 | }
54 |
55 | byte[] encFileName = Arrays.copyOfRange(base256FileName, 2,
56 | base256FileName.length);
57 |
58 | if (encFileName.length == 0) {
59 | throw new EncFSCorruptDataException(
60 | "Malformed file name (too short)");
61 | }
62 |
63 | byte[] fileIv = EncFSCrypto.computeFileIV(chainIv, macBytes);
64 |
65 | byte[] decFileName = decryptConcrete(volume, encFileName, fileIv);
66 |
67 | verifyDecryptionWorked(volume, chainIv, base256FileName, decFileName);
68 |
69 | return decryptPost(decFileName);
70 | }
71 |
72 | // Post decrpytion hook for subclasses
73 | protected abstract String decryptPost(byte[] fileName);
74 |
75 | // Verify that the decryption worked
76 | private void verifyDecryptionWorked(EncFSVolume volume, byte[] chainIv,
77 | byte[] base256FileName, byte[] decFileName)
78 | throws EncFSChecksumException {
79 | // Verify decryption worked
80 | // current versions store the checksum at the beginning (encfs 0.x
81 | // stored checksums at the end)
82 | byte[] mac16;
83 | if (volume.getConfig().isChainedNameIV()) {
84 | mac16 = EncFSCrypto.mac16(volume.getMAC(), decFileName, chainIv);
85 | } else {
86 | mac16 = EncFSCrypto.mac16(volume.getMAC(), decFileName);
87 | }
88 |
89 | byte[] expectedMac = Arrays.copyOfRange(base256FileName, 0, 2);
90 | if (!Arrays.equals(mac16, expectedMac)) {
91 | throw new EncFSChecksumException("Mismatch in file name checksum");
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/BasicFilenameEncryptionStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | import java.util.Arrays;
18 |
19 | // Common class for filename encryption strategies
20 | abstract class BasicFilenameEncryptionStrategy extends
21 | FilenameEncryptionStrategy {
22 |
23 | BasicFilenameEncryptionStrategy(EncFSVolume volume, String volumePath,
24 | EncFSFilenameEncryptionAlgorithm algorithm) {
25 | super(volume, volumePath, algorithm);
26 | }
27 |
28 | // Actual encryption to be implemented by the subclass
29 | protected abstract byte[] encryptConcrete(EncFSVolume volume,
30 | byte[] paddedDecFileName, byte[] fileIv)
31 | throws EncFSCorruptDataException;
32 |
33 | // Filename encryption implementation
34 | protected String encryptImpl(String fileName)
35 | throws EncFSCorruptDataException {
36 | EncFSVolume volume = getVolume();
37 | String volumePath = getVolumePath();
38 | EncFSConfig config = volume.getConfig();
39 |
40 | byte[] decFileName = fileName.getBytes();
41 | byte[] paddedDecFileName = getPaddedDecFilename(decFileName);
42 | byte[] chainIv = EncFSCrypto.computeChainedIV(volume, volumePath,
43 | config);
44 | byte[] mac16 = getMac16(volume, paddedDecFileName, chainIv);
45 | byte[] macBytes = EncFSCrypto.getMacBytes(mac16);
46 | byte[] fileIv = EncFSCrypto.computeFileIV(chainIv, macBytes);
47 |
48 | byte[] encFileName = encryptConcrete(volume, paddedDecFileName, fileIv);
49 |
50 | return getBase256Filename(mac16, encFileName);
51 | }
52 |
53 | // Filename padding implementation hook for subclasses
54 | protected abstract byte[] getPaddedDecFilename(byte[] decFileName);
55 |
56 | // Returns the base 256 filename for the given encrypted filename
57 | private String getBase256Filename(byte[] mac16, byte[] encFileName) {
58 | // current versions store the checksum at the beginning (encfs 0.x
59 | // stored checksums at the end)
60 |
61 | byte[] base256FileName = new byte[encFileName.length + 2];
62 | base256FileName[0] = mac16[0];
63 | base256FileName[1] = mac16[1];
64 | System.arraycopy(encFileName, 0, base256FileName, 2, encFileName.length);
65 |
66 | byte[] fileNameOutput = EncFSBase64.encodeEncfs(base256FileName);
67 |
68 | return new String(fileNameOutput);
69 | }
70 |
71 | // Returns the mac16 of the given file name
72 | private byte[] getMac16(EncFSVolume volume, byte[] paddedDecFileName,
73 | byte[] chainIv) {
74 | if (volume.getConfig().isChainedNameIV()) {
75 | return EncFSCrypto.mac16(volume.getMAC(), paddedDecFileName,
76 | Arrays.copyOf(chainIv, chainIv.length));
77 | } else {
78 | return EncFSCrypto.mac16(volume.getMAC(), paddedDecFileName);
79 | }
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/BlockCrypto.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | import javax.crypto.BadPaddingException;
18 | import javax.crypto.Cipher;
19 | import javax.crypto.IllegalBlockSizeException;
20 | import java.security.InvalidAlgorithmParameterException;
21 |
22 | // Static methods for block cryptography
23 | class BlockCrypto {
24 |
25 | // Returns a new block cipher object
26 | protected static Cipher newBlockCipher() throws EncFSUnsupportedException {
27 | return EncFSCrypto.getCipher(EncFSCrypto.BLOCK_CIPHER);
28 | }
29 |
30 | // Common method to perform a block operation
31 | private static byte[] blockOperation(EncFSVolume volume, byte[] ivSeed,
32 | byte[] data, int opMode) throws InvalidAlgorithmParameterException,
33 | IllegalBlockSizeException, BadPaddingException {
34 | Cipher cipher = volume.getBlockCipher();
35 | EncFSCrypto.cipherInit(volume, opMode, cipher, ivSeed);
36 | return cipher.doFinal(data);
37 | }
38 |
39 | // Perform block encryption
40 | protected static byte[] blockDecrypt(EncFSVolume volume, byte[] ivSeed,
41 | byte[] data) throws InvalidAlgorithmParameterException,
42 | IllegalBlockSizeException, BadPaddingException {
43 | return blockOperation(volume, ivSeed, data, Cipher.DECRYPT_MODE);
44 | }
45 |
46 | // Perform block decryption
47 | protected static byte[] blockEncrypt(EncFSVolume volume, byte[] ivSeed,
48 | byte[] data) throws IllegalBlockSizeException,
49 | InvalidAlgorithmParameterException, BadPaddingException {
50 | return blockOperation(volume, ivSeed, data, Cipher.ENCRYPT_MODE);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/BlockFilenameDecryptionStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | import javax.crypto.BadPaddingException;
18 | import javax.crypto.IllegalBlockSizeException;
19 | import java.security.InvalidAlgorithmParameterException;
20 | import java.util.Arrays;
21 |
22 | // Implementation of block filename decryption strategy
23 | class BlockFilenameDecryptionStrategy extends BasicFilenameDecryptionStrategy {
24 |
25 | BlockFilenameDecryptionStrategy(EncFSVolume volume, String volumePath) {
26 | super(volume, volumePath, EncFSFilenameEncryptionAlgorithm.BLOCK);
27 | }
28 |
29 | // Block decryption
30 | protected byte[] decryptConcrete(EncFSVolume volume, byte[] encFileName,
31 | byte[] fileIv) throws EncFSCorruptDataException {
32 | try {
33 | return BlockCrypto.blockDecrypt(volume, fileIv, encFileName);
34 | } catch (InvalidAlgorithmParameterException e) {
35 | throw new EncFSCorruptDataException(e);
36 | } catch (IllegalBlockSizeException e) {
37 | throw new EncFSCorruptDataException(e);
38 | } catch (BadPaddingException e) {
39 | throw new EncFSCorruptDataException(e);
40 | }
41 | }
42 |
43 | // Remove padding after decryption
44 | protected String decryptPost(byte[] fileName) {
45 | int padLen = fileName[fileName.length - 1];
46 |
47 | return new String(Arrays.copyOfRange(fileName, 0, fileName.length
48 | - padLen));
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/BlockFilenameEncryptionStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | import javax.crypto.BadPaddingException;
18 | import javax.crypto.IllegalBlockSizeException;
19 | import java.security.InvalidAlgorithmParameterException;
20 | import java.util.Arrays;
21 |
22 | // Implementation of block filename encryption strategy
23 | class BlockFilenameEncryptionStrategy extends BasicFilenameEncryptionStrategy {
24 |
25 | BlockFilenameEncryptionStrategy(EncFSVolume volume, String volumePath) {
26 | super(volume, volumePath, EncFSFilenameEncryptionAlgorithm.BLOCK);
27 | }
28 |
29 | // Block encryption
30 | @Override
31 | protected byte[] encryptConcrete(EncFSVolume volume,
32 | byte[] paddedDecFileName, byte[] fileIv)
33 | throws EncFSCorruptDataException {
34 | try {
35 | return BlockCrypto.blockEncrypt(volume, fileIv, paddedDecFileName);
36 | } catch (InvalidAlgorithmParameterException e) {
37 | throw new EncFSCorruptDataException(e);
38 | } catch (IllegalBlockSizeException e) {
39 | throw new EncFSCorruptDataException(e);
40 | } catch (BadPaddingException e) {
41 | throw new EncFSCorruptDataException(e);
42 | }
43 | }
44 |
45 | // Padding implementation
46 | protected byte[] getPaddedDecFilename(byte[] decFileName) {
47 | // Pad to the nearest 16 bytes, add a full block if needed
48 | int padBytesSize = 16;
49 | int padLen = padBytesSize - (decFileName.length % padBytesSize);
50 | if (padLen == 0) {
51 | padLen = padBytesSize;
52 | }
53 | byte[] paddedDecFileName = Arrays.copyOf(decFileName,
54 | decFileName.length + padLen);
55 | Arrays.fill(paddedDecFileName, decFileName.length,
56 | paddedDecFileName.length, (byte) padLen);
57 | return paddedDecFileName;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSChecksumException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | public class EncFSChecksumException extends EncFSException {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | public EncFSChecksumException(String message) {
23 | super(message);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | /**
19 | * Class representing an EncFS volume configuration.
20 | *
21 | */
22 | public class EncFSConfig {
23 |
24 | private int volumeKeySizeInBits;
25 | private int encryptedFileBlockSizeInBytes;
26 | private boolean useUniqueIV;
27 |
28 | /*
29 | * Whether name IV chaining is being used. When using IV chaining, each
30 | * parent element in a file's path contributes to the IV that is used to
31 | * encrypt the file's name.
32 | */
33 | private boolean chainedNameIV;
34 | private boolean holesAllowedInFiles;
35 | private int encodedKeyLengthInBytes;
36 |
37 | /*
38 | * String containing the Base64 encoded representation of the volume
39 | * encryption key encrypted with the password generated key.
40 | */
41 | private String base64EncodedVolumeKey;
42 | private int saltLengthBytes;
43 |
44 | /*
45 | * String containing the salt data applied to the password hash for
46 | * generating the password derived key.
47 | */
48 | private String base64Salt;
49 | private int iterationForPasswordKeyDerivationCount;
50 | private EncFSFilenameEncryptionAlgorithm filenameAlgorithm;
51 | private int numberOfMACBytesForEachFileBlock;
52 | private int numberOfRandomBytesInEachMACHeader;
53 | private boolean supportedExternalIVChaining;
54 |
55 | public EncFSConfig() {
56 | }
57 |
58 | public int getVolumeKeySizeInBits() {
59 | return volumeKeySizeInBits;
60 | }
61 |
62 | public void setVolumeKeySizeInBits(int volumeKeySizeInBits) {
63 | this.volumeKeySizeInBits = volumeKeySizeInBits;
64 | }
65 |
66 | public int getEncryptedFileBlockSizeInBytes() {
67 | return encryptedFileBlockSizeInBytes;
68 | }
69 |
70 | public void setEncryptedFileBlockSizeInBytes(
71 | int encryptedFileBlockSizeInBytes) {
72 | this.encryptedFileBlockSizeInBytes = encryptedFileBlockSizeInBytes;
73 | }
74 |
75 | public boolean isUseUniqueIV() {
76 | return useUniqueIV;
77 | }
78 |
79 | public void setUseUniqueIV(boolean useUniqueIV) {
80 | this.useUniqueIV = useUniqueIV;
81 | }
82 |
83 | public boolean isChainedNameIV() {
84 | return chainedNameIV;
85 | }
86 |
87 | public void setChainedNameIV(boolean chainedNameIV) {
88 | this.chainedNameIV = chainedNameIV;
89 | }
90 |
91 | public boolean isHolesAllowedInFiles() {
92 | return holesAllowedInFiles;
93 | }
94 |
95 | public void setHolesAllowedInFiles(boolean holesAllowedInFiles) {
96 | this.holesAllowedInFiles = holesAllowedInFiles;
97 | }
98 |
99 | public int getEncodedKeyLengthInBytes() {
100 | return encodedKeyLengthInBytes;
101 | }
102 |
103 | public void setEncodedKeyLengthInBytes(int encodedKeyLengthInBytes) {
104 | this.encodedKeyLengthInBytes = encodedKeyLengthInBytes;
105 | }
106 |
107 | public String getBase64EncodedVolumeKey() {
108 | return base64EncodedVolumeKey;
109 | }
110 |
111 | public void setBase64EncodedVolumeKey(String base64EncodedVolumeKey) {
112 | this.base64EncodedVolumeKey = base64EncodedVolumeKey;
113 | }
114 |
115 | public int getSaltLengthBytes() {
116 | return saltLengthBytes;
117 | }
118 |
119 | public void setSaltLengthBytes(int saltLengthBytes) {
120 | this.saltLengthBytes = saltLengthBytes;
121 | }
122 |
123 | public String getBase64Salt() {
124 | return base64Salt;
125 | }
126 |
127 | public void setBase64Salt(String salt) {
128 | this.base64Salt = salt;
129 | }
130 |
131 | public int getIterationForPasswordKeyDerivationCount() {
132 | return iterationForPasswordKeyDerivationCount;
133 | }
134 |
135 | public void setIterationForPasswordKeyDerivationCount(
136 | int iterationForPasswordKeyDerivationCount) {
137 | this.iterationForPasswordKeyDerivationCount = iterationForPasswordKeyDerivationCount;
138 | }
139 |
140 | public EncFSFilenameEncryptionAlgorithm getFilenameAlgorithm() {
141 | return filenameAlgorithm;
142 | }
143 |
144 | public void setFilenameAlgorithm(
145 | EncFSFilenameEncryptionAlgorithm filenameAlgorithm) {
146 | this.filenameAlgorithm = filenameAlgorithm;
147 | }
148 |
149 | public int getNumberOfMACBytesForEachFileBlock() {
150 | return numberOfMACBytesForEachFileBlock;
151 | }
152 |
153 | public void setNumberOfMACBytesForEachFileBlock(
154 | int numberOfMACBytesForEachFileBlock) {
155 | this.numberOfMACBytesForEachFileBlock = numberOfMACBytesForEachFileBlock;
156 | }
157 |
158 | public int getNumberOfRandomBytesInEachMACHeader() {
159 | return numberOfRandomBytesInEachMACHeader;
160 | }
161 |
162 | public void setNumberOfRandomBytesInEachMACHeader(
163 | int numberOfRandomBytesInEachMACHeader) {
164 | this.numberOfRandomBytesInEachMACHeader = numberOfRandomBytesInEachMACHeader;
165 | }
166 |
167 | public boolean isSupportedExternalIVChaining() {
168 | return supportedExternalIVChaining;
169 | }
170 |
171 | public void setSupportedExternalIVChaining(
172 | boolean supportedExternalIVChaining) {
173 | this.supportedExternalIVChaining = supportedExternalIVChaining;
174 | }
175 |
176 | public void validate() throws EncFSInvalidConfigException {
177 | if (isSupportedExternalIVChaining()
178 | && (!isChainedNameIV() || !isUseUniqueIV())) {
179 | throw new EncFSInvalidConfigException(
180 | "External IV chaining requires chained name IV and unique IV to be enabled");
181 | }
182 | }
183 |
184 | @Override
185 | public String toString() {
186 | return "EncFSConfig [volumeKeySizeInBits=" + volumeKeySizeInBits
187 | + ", encryptedFileBlockSizeInBytes="
188 | + encryptedFileBlockSizeInBytes + ", useUniqueIV="
189 | + useUniqueIV + ", chainedNameIV=" + chainedNameIV
190 | + ", holesAllowedInFiles=" + holesAllowedInFiles
191 | + ", encodedKeyLengthInBytes=" + encodedKeyLengthInBytes
192 | + ", base64EncodedVolumeKey=" + base64EncodedVolumeKey
193 | + ", saltLengthBytes=" + saltLengthBytes + ", base64Salt="
194 | + base64Salt + ", iterationForPasswordKeyDerivationCount="
195 | + iterationForPasswordKeyDerivationCount + ", algorithm="
196 | + filenameAlgorithm + ", numberOfMACBytesForEachFileBlock="
197 | + numberOfMACBytesForEachFileBlock
198 | + ", numberOfRandomBytesInEachMACHeader="
199 | + numberOfRandomBytesInEachMACHeader
200 | + ", supportedExternalIVChaining="
201 | + supportedExternalIVChaining + "]";
202 | }
203 | }
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSConfigFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | /**
18 | * Class for creating EncFSConfig objects
19 | */
20 | public final class EncFSConfigFactory {
21 |
22 | /**
23 | * Creates an EncFSConfig with default parameters:
24 | *
25 | * nameio/block
26 | * 192-bit key
27 | * 1024 byte block size
28 | * Unique IV
29 | * Chained name IV
30 | * AllowHoles
31 | * 5000 PBKDF2 iterations
32 | *
33 | * @return An EncFSConfig object with default parameters
34 | */
35 | public static EncFSConfig createDefault() {
36 | EncFSConfig config = new EncFSConfig();
37 | config.setFilenameAlgorithm(EncFSFilenameEncryptionAlgorithm.BLOCK);
38 | config.setVolumeKeySizeInBits(192);
39 | config.setEncryptedFileBlockSizeInBytes(1024);
40 | config.setUseUniqueIV(true);
41 | config.setChainedNameIV(true);
42 | config.setHolesAllowedInFiles(true);
43 | config.setIterationForPasswordKeyDerivationCount(5000);
44 | config.setNumberOfMACBytesForEachFileBlock(0);
45 | config.setNumberOfRandomBytesInEachMACHeader(0);
46 | config.setSupportedExternalIVChaining(false);
47 | return config;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSConfigParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | import org.w3c.dom.Document;
19 | import org.w3c.dom.Node;
20 | import org.w3c.dom.NodeList;
21 | import org.xml.sax.SAXException;
22 |
23 | import javax.xml.parsers.DocumentBuilder;
24 | import javax.xml.parsers.DocumentBuilderFactory;
25 | import javax.xml.parsers.ParserConfigurationException;
26 | import java.io.File;
27 | import java.io.FileInputStream;
28 | import java.io.IOException;
29 | import java.io.InputStream;
30 |
31 | /**
32 | * Parser methods that read and interpret EncFS configuration files.
33 | */
34 | public class EncFSConfigParser {
35 |
36 | private static String getNodeValue(Node n) {
37 | return n.getChildNodes().item(0).getNodeValue();
38 | }
39 |
40 | /**
41 | * Parse the given configuration file
42 | *
43 | * @param configFile
44 | * EncFS volume configuration file.
45 | * @return An EncFSConfig object containing the configuration data
46 | * interpreted from the given file.
47 | */
48 | public static EncFSConfig parseFile(File configFile)
49 | throws ParserConfigurationException, SAXException, IOException,
50 | EncFSInvalidConfigException, EncFSUnsupportedException {
51 | FileInputStream inputStream = new FileInputStream(configFile);
52 | try {
53 | return parseFile(inputStream);
54 | } finally {
55 | inputStream.close();
56 | }
57 |
58 | }
59 |
60 | /**
61 | * Parse the configuration file residing on an EncFSFileProvider with the
62 | * given path
63 | *
64 | * @param fileProvider
65 | * File provider to access the config file
66 | * @param path
67 | * Path of the config file in the file provider's notation
68 | * @return An EncFSConfig object representing the parsing result
69 | */
70 | public static EncFSConfig parseConfig(EncFSFileProvider fileProvider,
71 | String path) throws EncFSUnsupportedException,
72 | EncFSInvalidConfigException, IOException {
73 |
74 | EncFSConfig config;
75 | // TODO: Need to implement a connector method in EncFSFileProvider for
76 | // '/'
77 | if (!fileProvider.exists(fileProvider.getFilesystemRootPath() + path)) {
78 | // Try old versions
79 | for (String altConfigFileName : EncFSVolume.OLD_CONFIG_FILE_NAMES) {
80 | if (fileProvider.exists(fileProvider.getFilesystemRootPath()
81 | + altConfigFileName)) {
82 | throw new EncFSUnsupportedException(
83 | "Unsupported EncFS version");
84 | }
85 | }
86 |
87 | throw new EncFSInvalidConfigException(
88 | "No EncFS configuration file found");
89 | }
90 |
91 | // Parse the configuration file
92 | try {
93 | config = EncFSConfigParser.parseFile(fileProvider
94 | .openInputStream(fileProvider.getFilesystemRootPath()
95 | + path));
96 | } catch (ParserConfigurationException e2) {
97 | throw new EncFSUnsupportedException("XML parser not supported");
98 | } catch (SAXException e2) {
99 | throw new EncFSInvalidConfigException("Parse error in config file");
100 | } catch (IOException e2) {
101 | throw new EncFSInvalidConfigException("Couldn't open config file");
102 | }
103 |
104 | // Validate the configuration
105 | config.validate();
106 |
107 | return config;
108 | }
109 |
110 | /**
111 | * Parse the given configuration file from a stream
112 | *
113 | * @param inputStream
114 | * InputStream for the config file
115 | * @return An EncFSConfig object containing the configuration data
116 | * interpreted from the given file.
117 | */
118 | private static EncFSConfig parseFile(InputStream inputStream)
119 | throws ParserConfigurationException, SAXException, IOException,
120 | EncFSInvalidConfigException {
121 | EncFSConfig config = EncFSConfigFactory.createDefault();
122 |
123 | DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
124 | DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
125 | Document doc = dBuilder.parse(inputStream);
126 | doc.getDocumentElement().normalize();
127 |
128 | NodeList cfgNodeList = doc.getElementsByTagName("cfg").item(0)
129 | .getChildNodes();
130 |
131 | if (cfgNodeList.getLength() == 0) {
132 | throw new EncFSInvalidConfigException(
133 | " element not present in config file");
134 | }
135 |
136 | for (int i = 0; i < cfgNodeList.getLength(); i++) {
137 | Node cfgNode = cfgNodeList.item(i);
138 |
139 | if (cfgNode.getNodeType() == Node.ELEMENT_NODE) {
140 | if (cfgNode.getNodeName().equals("nameAlg")) {
141 | NodeList nameAlgNodeList = cfgNode.getChildNodes();
142 | for (int j = 0; j < nameAlgNodeList.getLength(); j++) {
143 | Node nameAlgChildNode = nameAlgNodeList.item(j);
144 | if (nameAlgChildNode.getNodeName().equals("name")) {
145 | String algName = getNodeValue(nameAlgChildNode);
146 | try {
147 | config.setFilenameAlgorithm(EncFSFilenameEncryptionAlgorithm
148 | .parse(algName));
149 | } catch (IllegalArgumentException e) {
150 | throw new EncFSInvalidConfigException(
151 | "Unknown name algorithm in config file: "
152 | + algName);
153 | }
154 | }
155 | }
156 | } else if (cfgNode.getNodeName().equals("keySize")) {
157 | config.setVolumeKeySizeInBits(Integer
158 | .parseInt(getNodeValue(cfgNode)));
159 | } else if (cfgNode.getNodeName().equals("blockSize")) {
160 | config.setEncryptedFileBlockSizeInBytes(Integer
161 | .parseInt(getNodeValue(cfgNode)));
162 | } else if (cfgNode.getNodeName().equals("uniqueIV")) {
163 | config.setUseUniqueIV(Integer
164 | .parseInt(getNodeValue(cfgNode)) == 1);
165 | } else if (cfgNode.getNodeName().equals("chainedNameIV")) {
166 | config.setChainedNameIV(Integer
167 | .parseInt(getNodeValue(cfgNode)) == 1);
168 | } else if (cfgNode.getNodeName().equals("allowHoles")) {
169 | config.setHolesAllowedInFiles(Integer
170 | .parseInt(getNodeValue(cfgNode)) == 1);
171 | } else if (cfgNode.getNodeName().equals("encodedKeySize")) {
172 | config.setEncodedKeyLengthInBytes(Integer
173 | .parseInt(getNodeValue(cfgNode)));
174 | } else if (cfgNode.getNodeName().equals("encodedKeyData")) {
175 | config.setBase64EncodedVolumeKey(getNodeValue(cfgNode));
176 | } else if (cfgNode.getNodeName().equals("saltLen")) {
177 | config.setSaltLengthBytes(Integer
178 | .parseInt(getNodeValue(cfgNode)));
179 | } else if (cfgNode.getNodeName().equals("saltData")) {
180 | config.setBase64Salt(getNodeValue(cfgNode));
181 | } else if (cfgNode.getNodeName().equals("kdfIterations")) {
182 | config.setIterationForPasswordKeyDerivationCount(Integer
183 | .parseInt(getNodeValue(cfgNode)));
184 | } else if (cfgNode.getNodeName().equals("blockMACBytes")) {
185 | config.setNumberOfMACBytesForEachFileBlock(Integer
186 | .parseInt(getNodeValue(cfgNode)));
187 | } else if (cfgNode.getNodeName().equals("blockMACRandBytes")) {
188 | config.setNumberOfRandomBytesInEachMACHeader(Integer
189 | .parseInt(getNodeValue(cfgNode)));
190 | } else if (cfgNode.getNodeName().equals("externalIVChaining")) {
191 | config.setSupportedExternalIVChaining(Integer
192 | .parseInt(getNodeValue(cfgNode)) == 1);
193 | }
194 | }
195 | }
196 |
197 | return config;
198 | }
199 | }
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSConfigWriter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011-2012 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | import java.io.IOException;
19 | import java.io.InputStream;
20 | import java.io.OutputStream;
21 | import java.util.Properties;
22 |
23 | /**
24 | * Writer methods that write an EncFSConfig into a file
25 | */
26 | public class EncFSConfigWriter {
27 |
28 | // Version to use if the properties file can't be read
29 | private static final String ENCFS_JAVA_LIB_VERSION_DEV = "dev";
30 |
31 | // Property file
32 | private static final String ENCFS_JAVA_LIB_PROPERTY_FILE = "library.properties";
33 |
34 | // Property key for version
35 | private static final String ENCFS_JAVA_LIB_VERSION_KEY = "library.version";
36 |
37 | // Retrieve library version
38 | private static String getLibraryVersion() {
39 | Properties prop = new Properties();
40 | InputStream in = EncFSConfigWriter.class
41 | .getResourceAsStream(ENCFS_JAVA_LIB_PROPERTY_FILE);
42 |
43 | if (in != null) {
44 | try {
45 | prop.load(in);
46 | String version = prop.getProperty(ENCFS_JAVA_LIB_VERSION_KEY);
47 | if (version != null) {
48 | return version;
49 | } else {
50 | return ENCFS_JAVA_LIB_VERSION_DEV;
51 | }
52 | } catch (IOException e) {
53 | return ENCFS_JAVA_LIB_VERSION_DEV;
54 | }
55 | } else {
56 | return ENCFS_JAVA_LIB_VERSION_DEV;
57 | }
58 | }
59 |
60 | // Create config file contents from a given EncFSConfig / password
61 | private static String createConfigFileContents(EncFSConfig config) {
62 | // XXX: This implementation is pretty horrible, but it works :)
63 | String result = "";
64 |
65 | result += "\n";
66 | result += "\n";
67 | result += "\n";
68 | result += " \n";
69 | result += "\t20100713\n";
70 | result += "\tencfs-java " + getLibraryVersion()
71 | + "\n";
72 | result += "\t\n";
73 | result += "\t\tssl/aes\n";
74 | result += "\t\t3\n";
75 | result += "\t\t0\n";
76 | result += "\t\n";
77 |
78 | result += "\t\n";
79 |
80 | EncFSFilenameEncryptionAlgorithm algorithm = config
81 | .getFilenameAlgorithm();
82 | result += "\t\t" + algorithm.getIdentifier() + "\n";
83 | result += "\t\t" + algorithm.getMajor() + "\n";
84 | result += "\t\t" + algorithm.getMinor() + "\n";
85 |
86 | result += "\t\n";
87 |
88 | result += "\t"
89 | + Integer.toString(config.getVolumeKeySizeInBits())
90 | + "\n";
91 |
92 | result += "\t"
93 | + Integer.toString(config.getEncryptedFileBlockSizeInBytes())
94 | + "\n";
95 |
96 | result += "\t" + (config.isUseUniqueIV() ? "1" : "0")
97 | + "\n";
98 |
99 | result += "\t" + (config.isChainedNameIV() ? "1" : "0")
100 | + "\n";
101 |
102 | result += "\t"
103 | + (config.isSupportedExternalIVChaining() ? "1" : "0")
104 | + "\n";
105 |
106 | result += "\t"
107 | + Integer
108 | .toString(config.getNumberOfMACBytesForEachFileBlock())
109 | + "\n";
110 | result += "\t"
111 | + Integer.toString(config
112 | .getNumberOfRandomBytesInEachMACHeader())
113 | + "\n";
114 |
115 | result += "\t"
116 | + (config.isHolesAllowedInFiles() ? "1" : "0")
117 | + "\n";
118 |
119 | result += "\t"
120 | + Integer.toString(config.getEncodedKeyLengthInBytes())
121 | + "\n";
122 | result += "\t" + config.getBase64EncodedVolumeKey()
123 | + "\n\n";
124 |
125 | result += "\t" + Integer.toString(config.getSaltLengthBytes())
126 | + "\n";
127 | result += "\t" + config.getBase64Salt() + "\n\n";
128 |
129 | result += "\t"
130 | + Integer.toString(config
131 | .getIterationForPasswordKeyDerivationCount())
132 | + "\n";
133 |
134 | // XXX: We don't support custom KDF durations
135 | result += "\t500\n";
136 |
137 | result += " \n";
138 | result += "\n";
139 |
140 | return result;
141 | }
142 |
143 | /**
144 | * Create a configuration file from the given EncFSConfig and write it to
145 | * the root directory of the given EncFSFileProvider
146 | */
147 | public static void writeConfig(EncFSFileProvider fileProvider,
148 | EncFSConfig config) throws EncFSUnsupportedException, IOException {
149 | String configFileName = fileProvider.getFilesystemRootPath()
150 | + EncFSVolume.CONFIG_FILE_NAME;
151 |
152 | if (fileProvider.exists(configFileName)) {
153 | throw new EncFSUnsupportedException("Config file already exists");
154 | }
155 |
156 | String configFileContents = createConfigFileContents(config);
157 |
158 | OutputStream os = fileProvider.openOutputStream(configFileName,
159 | configFileContents.length());
160 |
161 | os.write(configFileContents.getBytes());
162 | os.close();
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSCorruptDataException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | public class EncFSCorruptDataException extends EncFSException {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | public EncFSCorruptDataException(String message) {
23 | super(message);
24 | }
25 |
26 | public EncFSCorruptDataException(Throwable cause) {
27 | super(cause);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | public abstract class EncFSException extends Exception {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | EncFSException(String message) {
23 | super(message);
24 | }
25 |
26 | EncFSException(Throwable cause) {
27 | super(cause);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSFile.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | import java.io.IOException;
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | /**
23 | * Object representing a file in an EncFS volume.
24 | *
25 | * Useful for decryption of file names as well as performing file operations
26 | * such as copying, moving, deletion etc.
27 | */
28 | public class EncFSFile {
29 |
30 | /**
31 | * Size in bytes of file header when file IV's are used (uniqueIV)
32 | */
33 | public static final int HEADER_SIZE = 8;
34 |
35 | // Volume hosting this file
36 | private final EncFSVolume volume;
37 |
38 | // Information about the plaintext file (decoded names etc.)
39 | private final EncFSFileInfo plainFileInfo;
40 |
41 | // Information about the ciphertext file (encrypted names etc.)
42 | private final EncFSFileInfo cipherFileInfo;
43 |
44 | /**
45 | * Create a new object representing a file in an EncFS volume
46 | *
47 | * @param volume
48 | * The volume that contains the file
49 | * @param plainFileInfo
50 | * EncFSFileInfo representing the cleartext file (decoded)
51 | * @param cipherFileInfo
52 | * EncFSFileInfo representing the ciphertext file (encoded)
53 | */
54 | public EncFSFile(EncFSVolume volume, EncFSFileInfo plainFileInfo,
55 | EncFSFileInfo cipherFileInfo) {
56 | this.volume = volume;
57 | this.plainFileInfo = plainFileInfo;
58 | this.cipherFileInfo = cipherFileInfo;
59 | }
60 |
61 | /**
62 | * Returns the volume path of this file
63 | *
64 | * @return Absolute volume path of the file
65 | */
66 | public String getPath() {
67 | return plainFileInfo.getPath();
68 | }
69 |
70 | /**
71 | * Returns the encrypted volume path of this file
72 | *
73 | * @return Encrypted volume path of the file
74 | */
75 | public String getEncryptedPath() {
76 | return cipherFileInfo.getPath();
77 | }
78 |
79 | /**
80 | * Returns the volume path of the parent directory hosting this file
81 | *
82 | * This is the plaintext path starting from the volume's root up until the
83 | * parent directory hosting the current file
84 | *
85 | * @return Volume path of this file's parent directory
86 | */
87 | public String getParentPath() {
88 | return plainFileInfo.getParentPath();
89 | }
90 |
91 | /**
92 | * Returns the encrypted volume path of the parent directory hosting this
93 | * file
94 | *
95 | * @return Encrypted volume path of this file's parent directory
96 | */
97 | public String getEncryptedParentPath() {
98 | return cipherFileInfo.getParentPath();
99 | }
100 |
101 | /**
102 | * Returns the plaintext name of this file
103 | *
104 | * @return decrypted name of this EncFS file
105 | */
106 | public String getName() {
107 | return plainFileInfo.getName();
108 | }
109 |
110 | /**
111 | * Returns the ciphertext name of this file
112 | *
113 | * @return encrypted name of this EncFS file
114 | */
115 | public String getEncrytedName() {
116 | return cipherFileInfo.getName();
117 | }
118 |
119 | /**
120 | * Returns the length of decrypted contents for this file
121 | *
122 | * @return Length of decrypted file contents
123 | */
124 | public long getLength() {
125 | return plainFileInfo.getSize();
126 | }
127 |
128 | /**
129 | * Returns the last modification time for this file
130 | *
131 | * @return last modification time for the file
132 | */
133 | public long getLastModified() {
134 | return plainFileInfo.getLastModified();
135 | }
136 |
137 | /**
138 | * Returns the volume containing this file
139 | *
140 | * @return Volume containing the EncFS file
141 | */
142 | public EncFSVolume getVolume() {
143 | return volume;
144 | }
145 |
146 | /**
147 | * Checks whether this EncFSFile represents a directory
148 | *
149 | * @return true if directory, false otherwise
150 | */
151 | public boolean isDirectory() {
152 | return plainFileInfo.isDirectory();
153 | }
154 |
155 | /**
156 | * Checks whether the file is readable
157 | *
158 | * @return true if the file is readable, false otherwise
159 | */
160 | public boolean isReadable() {
161 | return plainFileInfo.isReadable();
162 | }
163 |
164 | /**
165 | * Checks whether the file is writable
166 | *
167 | * @return true if the file is writable, false otherwise
168 | */
169 | public boolean isWritable() {
170 | return plainFileInfo.isWritable();
171 | }
172 |
173 | /**
174 | * Checks whether the file is executable
175 | *
176 | * @return true if the file is executable, false otherwise
177 | */
178 | public boolean isExecutable() {
179 | return plainFileInfo.isExecutable();
180 | }
181 |
182 | /**
183 | * List files/directory names contained by the directory represented by this
184 | * EncFSFile object.
185 | */
186 | public String[] list() throws IOException {
187 | EncFSFile[] files = listFiles();
188 |
189 | String[] fileNames = null;
190 | if (files != null) {
191 | fileNames = new String[files.length];
192 |
193 | for (int i = 0; i < files.length; i++) {
194 | EncFSFile file = files[i];
195 | fileNames[i] = file.getName();
196 | }
197 | }
198 |
199 | return fileNames;
200 | }
201 |
202 | /**
203 | * Get list of EncFSFile's under this directory
204 | *
205 | * @return list of EncFSFile under the given directory
206 | */
207 | public EncFSFile[] listFiles() throws IOException {
208 |
209 | if (!isDirectory()) {
210 | return null;
211 | }
212 |
213 | String encDirName;
214 | if (this == volume.getRootDir()) {
215 | encDirName = EncFSVolume.ROOT_PATH;
216 | } else {
217 | encDirName = getEncryptedPath();
218 | }
219 | String dirName = getPath();
220 |
221 | List fileInfos = volume.getFileProvider().listFiles(
222 | encDirName);
223 | List result = new ArrayList(fileInfos.size());
224 |
225 | for (EncFSFileInfo fileInfo : fileInfos) {
226 | String decodedFileName;
227 | try {
228 | decodedFileName = EncFSCrypto.decodeName(volume,
229 | fileInfo.getName(), dirName);
230 | } catch (EncFSCorruptDataException e) {
231 | decodedFileName = null;
232 | } catch (EncFSChecksumException e) {
233 | decodedFileName = null;
234 | }
235 |
236 | if (decodedFileName != null) {
237 | EncFSFileInfo decEncFileInfo = EncFSFileInfo
238 | .getDecodedFileInfo(volume, dirName, decodedFileName,
239 | fileInfo);
240 |
241 | result.add(new EncFSFile(volume, decEncFileInfo, fileInfo));
242 | }
243 | }
244 |
245 | return result.toArray(new EncFSFile[result.size()]);
246 | }
247 |
248 | /**
249 | * Delete this file
250 | *
251 | * @return true if deletion succeeds, false otherwise
252 | */
253 | public boolean delete() throws IOException {
254 | return volume.getFileProvider().delete(getEncryptedPath());
255 | }
256 |
257 | /**
258 | * Opens the file as an EncFSInputStream that decodes the file contents
259 | * automatically
260 | *
261 | * @return EncFSInputStream that decodes file contents
262 | */
263 | public EncFSInputStream openInputStream() throws EncFSCorruptDataException,
264 | EncFSUnsupportedException, IOException {
265 | return new EncFSInputStream(volume, volume.getFileProvider()
266 | .openInputStream(getEncryptedPath()), getPath());
267 | }
268 |
269 | /**
270 | * Opens the file as an EncFSOutputStream that encrypts the file contents
271 | * automatically
272 | *
273 | * @param inputLength
274 | * Length of the input file that will be written to this output
275 | * stream. Note that this parameter is optional if using
276 | * EncFSLocalFileProvider, but some network based storage API's
277 | * require knowing the file length in advance.
278 | * @return EncFSOutputStream that encrypts file contents
279 | */
280 | public EncFSOutputStream openOutputStream(long inputLength)
281 | throws EncFSUnsupportedException, EncFSCorruptDataException,
282 | IOException {
283 | return new EncFSOutputStream(volume, volume.getFileProvider()
284 | .openOutputStream(getEncryptedPath(),
285 | volume.getEncryptedFileLength(inputLength)), getPath());
286 | }
287 |
288 | /**
289 | * Copies this file/dir to a target file or directory
290 | *
291 | * @param dstPath
292 | * EncFSFile representing the target file or directory
293 | * @return true if copy succeeds, false otherwise
294 | */
295 | public boolean copy(EncFSFile dstPath) throws IOException {
296 | if (isDirectory()) {
297 | // Recursive copy of this directory to the target path
298 | try {
299 | return volume.copyPath(getPath(), dstPath.getPath());
300 | } catch (EncFSCorruptDataException e) {
301 | throw new IOException(e);
302 | }
303 | } else if (dstPath.isDirectory()) {
304 | /*
305 | * Trying to copy a file to a directory, copy it UNDER that
306 | * directory instead
307 | */
308 | EncFSFile realDstPath;
309 | try {
310 | realDstPath = volume.createFile(dstPath.getPath(), getName());
311 | } catch (EncFSCorruptDataException e) {
312 | throw new IOException(e);
313 | }
314 | return copy(realDstPath);
315 | } else {
316 | // Trying to copy a file into a file
317 | if (volume.getConfig().isSupportedExternalIVChaining()) {
318 | /*
319 | * Need to re-encrypt the file since external IV chaining is
320 | * used.
321 | */
322 | try {
323 | EncFSUtil.copyWholeStreamAndClose(openInputStream(),
324 | dstPath.openOutputStream(getLength()));
325 | } catch (EncFSException e) {
326 | throw new IOException(e);
327 | }
328 | return true;
329 | } else {
330 | // Simply copy the file using the file provider
331 | return volume.getFileProvider().copy(getEncryptedPath(),
332 | dstPath.getEncryptedPath());
333 | }
334 | }
335 | }
336 | }
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSFileInfo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | /**
19 | * Class representing information about an underlying file
20 | */
21 | public class EncFSFileInfo {
22 | // Name of the file
23 | private final String name;
24 |
25 | // Volume path of the parent directory hosting the file
26 | private final String parentPath;
27 |
28 | // Whether the file is a directory
29 | private final boolean directory;
30 |
31 | // Last modification time of the file
32 | private final long lastModified;
33 |
34 | // Raw size of the underlying file
35 | private final long size;
36 |
37 | // Whether the file is readable
38 | private final boolean readable;
39 |
40 | // Whether the file is writable
41 | private final boolean writable;
42 |
43 | // Whether the file is executable
44 | private final boolean executable;
45 |
46 | /**
47 | * Create a new EncFSFileInfo
48 | *
49 | * @param name
50 | * Name of the file
51 | * @param parentPath
52 | * Volume path of the parent directory hosting the file
53 | * @param directory
54 | * Whether the file is a directory
55 | * @param lastModified
56 | * Last modification time of the file
57 | * @param size
58 | * Raw size of the underlying file
59 | * @param readable
60 | * Whether the file is readable
61 | * @param writable
62 | * Whether the file is writable
63 | * @param executable
64 | * Whether the file is executable
65 | */
66 | public EncFSFileInfo(String name, String parentPath, boolean directory,
67 | long lastModified, long size, boolean readable, boolean writable,
68 | boolean executable) {
69 | if (name.startsWith(EncFSVolume.PATH_SEPARATOR)
70 | && (!name.equals(EncFSVolume.ROOT_PATH))) {
71 | throw new IllegalArgumentException("Invalid name " + name);
72 | }
73 |
74 | this.name = name;
75 | this.parentPath = parentPath;
76 | this.directory = directory;
77 | this.lastModified = lastModified;
78 | this.size = size;
79 | this.readable = readable;
80 | this.writable = writable;
81 | this.executable = executable;
82 | }
83 |
84 | /**
85 | * Returns the name of the file
86 | *
87 | * @return name of the file
88 | */
89 | public String getName() {
90 | return name;
91 | }
92 |
93 | /**
94 | * Returns the volume path of the parent directory hosting the file
95 | *
96 | * @return volume path of the parent directory hosting the file
97 | */
98 | public String getParentPath() {
99 | return parentPath;
100 | }
101 |
102 | /**
103 | * Returns the volume path of the file
104 | *
105 | * @return volume path of the file
106 | */
107 | public String getPath() {
108 | String result;
109 |
110 | if (parentPath.endsWith(EncFSVolume.PATH_SEPARATOR)
111 | || name.startsWith(EncFSVolume.PATH_SEPARATOR)) {
112 | result = parentPath + name;
113 | } else {
114 | result = EncFSVolume.combinePath(parentPath, name);
115 | }
116 |
117 | return result;
118 | }
119 |
120 | /**
121 | * Returns the last modification time of the file
122 | *
123 | * @return last modification time of the file
124 | */
125 | public long getLastModified() {
126 | return lastModified;
127 | }
128 |
129 | /**
130 | * Returns the raw size of the underlying file
131 | *
132 | * @return raw size of the underlying file
133 | */
134 | public long getSize() {
135 | return size;
136 | }
137 |
138 | /**
139 | * Returns whether the file is a directory
140 | *
141 | * @return whether the file is a directory
142 | */
143 | public boolean isDirectory() {
144 | return directory;
145 | }
146 |
147 | /**
148 | * Returns whether the file is readable
149 | *
150 | * @return whether the file is readable
151 | */
152 | public boolean isReadable() {
153 | return readable;
154 | }
155 |
156 | /**
157 | * Returns whether the file is writable
158 | *
159 | * @return whether the file is writable
160 | */
161 | public boolean isWritable() {
162 | return writable;
163 | }
164 |
165 | /**
166 | * Returns whether the file is executable
167 | *
168 | * @return whether the file is executable
169 | */
170 | public boolean isExecutable() {
171 | return executable;
172 | }
173 |
174 | /**
175 | * Produces an EncFSFileInfo for the decoded version of the file represented
176 | * by this object
177 | *
178 | * @param volume
179 | * Volume hosting this file
180 | * @param decodedParentPath
181 | * Decoded path of the parent directory for the output file
182 | * @param decodedFileName
183 | * Decoded file name of the output file
184 | * @param fileInfo
185 | * EncFSFileInfo for the file to be decoded
186 | * @return EncFSFileInfo for the decoded file
187 | */
188 | public static EncFSFileInfo getDecodedFileInfo(EncFSVolume volume,
189 | String decodedParentPath, String decodedFileName,
190 | EncFSFileInfo fileInfo) {
191 | long size;
192 | if (fileInfo.isDirectory()) {
193 | size = 0;
194 | } else {
195 | size = volume.getDecryptedFileLength(fileInfo.getSize());
196 | }
197 |
198 | return new EncFSFileInfo(decodedFileName, decodedParentPath,
199 | fileInfo.isDirectory(), fileInfo.getLastModified(), size,
200 | fileInfo.isReadable(), fileInfo.isWritable(),
201 | fileInfo.isExecutable());
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSFileInputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | import java.io.FilterInputStream;
19 | import java.io.IOException;
20 |
21 | /**
22 | * FileInputStream abstraction that allows decrypted data to be read from a file
23 | * on an EncFS volume.
24 | */
25 | public class EncFSFileInputStream extends FilterInputStream {
26 |
27 | /**
28 | * Creates an EncFSFileInputStream to read decrypted data from a file under
29 | * and EncFS volume
30 | *
31 | * @param encfsFile
32 | * EncFSFile to open an input stream for
33 | *
34 | *
35 | * Filename encoding failed
36 | *
37 | * File header uses an unsupported IV length
38 | *
39 | * File provider returned I/O error
40 | */
41 | public EncFSFileInputStream(EncFSFile encfsFile)
42 | throws EncFSCorruptDataException, EncFSUnsupportedException,
43 | IOException {
44 | super(encfsFile.openInputStream());
45 | }
46 | }
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSFileOutputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | import java.io.FilterOutputStream;
18 | import java.io.IOException;
19 |
20 | /**
21 | * FilterOutputStream abstraction that allows writing encrypted data to a file
22 | * on an EncFS volume.
23 | */
24 | public class EncFSFileOutputStream extends FilterOutputStream {
25 |
26 | /**
27 | * Creates an EncFSFileOutputStream to write encrypted data to a file under
28 | * and EncFS volume
29 | *
30 | * @param encfsFile
31 | * EncFSFile to open an output stream to
32 | * @param inputLength
33 | * Length of the input file that will be written to this output
34 | * stream. Note that this parameter is optional if using
35 | * EncFSLocalFileProvider, but some network based storage API's
36 | * require knowing the file length in advance.
37 | */
38 | public EncFSFileOutputStream(EncFSFile encfsFile, long inputLength)
39 | throws IOException, EncFSUnsupportedException,
40 | EncFSCorruptDataException {
41 | super(encfsFile.openOutputStream(inputLength));
42 | }
43 | }
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSFileProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | import java.io.IOException;
19 | import java.io.InputStream;
20 | import java.io.OutputStream;
21 | import java.util.List;
22 |
23 | /**
24 | * An EncFSFileProvider provides an abstraction for accessing file contents and
25 | * information in their encrypted form on a local disk or any other storage
26 | * type. This class can be extended to implement EncFS functionality on
27 | * non-local storage. For local storage access, see the built-in file provider
28 | * class EncFSLocalFileProvider.
29 | */
30 | public interface EncFSFileProvider {
31 |
32 | /**
33 | * Returns whether the given source path represents a directory in the
34 | * underlying filesystem
35 | *
36 | * @param srcPath
37 | * Path of the source file or directory
38 | *
39 | * @return true if path represents a directory, false otherwise
40 | *
41 | * @throws IOException
42 | * Source file/dir doesn't exist or misc. I/O error
43 | */
44 | boolean isDirectory(String srcPath) throws IOException;
45 |
46 | /**
47 | * Returns whether the file or directory exists
48 | *
49 | * @param srcPath
50 | * Path of the file or directory
51 | *
52 | * @return true if file or directory exists, false otherwise
53 | *
54 | * @throws IOException
55 | * Misc. I/O error
56 | */
57 | boolean exists(String srcPath) throws IOException;
58 |
59 | /**
60 | * Returns the root path for the underlying filesystem
61 | *
62 | * @return String representing the root path
63 | */
64 | String getFilesystemRootPath();
65 |
66 | /**
67 | * Return EncFSFileInfo for the given file or directory
68 | *
69 | * @param srcPath
70 | * Path of the file or directory
71 | *
72 | * @return EncFSFileInfo for the given file or directory
73 | *
74 | * @throws IOException
75 | * Path doesn't exist or misc. I/O error
76 | */
77 | EncFSFileInfo getFileInfo(String srcPath) throws IOException;
78 |
79 | /**
80 | * Returns the list of files under the given directory path
81 | *
82 | * @param dirPath
83 | * Path of the directory to list files from
84 | *
85 | * @return a List of EncFSFileInfo representing files under the dir
86 | *
87 | * @throws IOException
88 | * Path not a directory or misc. I/O error
89 | */
90 | List listFiles(String dirPath) throws IOException;
91 |
92 | /**
93 | * Move a file/directory to a different location
94 | *
95 | * @param srcPath
96 | * Path to the source file or directory
97 | * @param dstPath
98 | * Path for the destination file or directory
99 | *
100 | * @return true if the move is successful, false otherwise
101 | *
102 | * @throws IOException
103 | * Source file/dir doesn't exist or misc. I/O error
104 | */
105 | boolean move(String srcPath, String dstPath) throws IOException;
106 |
107 | /**
108 | * Delete the file or directory with the given path
109 | *
110 | * @param srcPath
111 | * Path of the source file or directory
112 | *
113 | * @return true if deletion is successful, false otherwise
114 | *
115 | * @throws IOException
116 | * Source file/dir doesn't exist or misc. I/O error
117 | */
118 | boolean delete(String srcPath) throws IOException;
119 |
120 | /**
121 | * Create a directory with the given path
122 | *
123 | * Note that all path elements except the last one must exist for this
124 | * method. If that is not true mkdirs should be used instead
125 | */
126 | boolean mkdir(String dirPath) throws IOException;
127 |
128 | /**
129 | * Create a directory with the given path
130 | *
131 | * Intermediate directories are also created by this method
132 | */
133 | boolean mkdirs(String dirPath) throws IOException;
134 |
135 | /**
136 | * Create a file with the given path
137 | *
138 | * @param dstFilePath
139 | * Path for the file to create
140 | *
141 | * @return EncFSFileInfo for the created file
142 | *
143 | * @throws IOException
144 | * File already exists or misc. I/O error
145 | */
146 | EncFSFileInfo createFile(String dstFilePath) throws IOException;
147 |
148 | /**
149 | * Copy the file with the given path to another destination
150 | *
151 | * @param srcFilePath
152 | * Path to the file to copy
153 | * @param dstFilePath
154 | * Path to the destination file
155 | *
156 | * @return true if copy was successful, false otherwise
157 | *
158 | * @throws IOException
159 | * Destination file already exists, source file doesn't exist or
160 | * misc. I/O error
161 | */
162 | boolean copy(String srcFilePath, String dstFilePath) throws IOException;
163 |
164 | /**
165 | * Open an InputStream to the given file
166 | *
167 | * @param srcFilePath
168 | * Path to the source file
169 | *
170 | * @return InputStream to read from the file
171 | *
172 | * @throws IOException
173 | * Source file doesn't exist or misc. I/O error
174 | */
175 | InputStream openInputStream(String srcFilePath) throws IOException;
176 |
177 | /**
178 | * Open an OutputStream to the given file
179 | *
180 | * @param dstFilePath
181 | * Path to the destination file
182 | * @param outputLength
183 | * Length in bytes of the stream that will be written to this
184 | * stream. It is up to the file provider to determine whether
185 | * this parameter is optional or required.
186 | *
187 | * @return OutputStream to write to the file
188 | *
189 | * @throws IOException
190 | * Misc. I/O error
191 | */
192 | OutputStream openOutputStream(String dstFilePath, long outputLength)
193 | throws IOException;
194 | }
195 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSFilenameEncryptionAlgorithm.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | /**
18 | * Enum representing the filename encryption algorithms used in EncFS
19 | */
20 | public enum EncFSFilenameEncryptionAlgorithm {
21 | BLOCK("nameio/block", 3, 0), STREAM("nameio/stream", 2, 1), NULL(
22 | "nameio/null", 1, 0);
23 |
24 | private final String identifier;
25 | private final int major;
26 | private final int minor;
27 |
28 | EncFSFilenameEncryptionAlgorithm(String identifier, int major, int minor) {
29 | this.identifier = identifier;
30 | this.major = major;
31 | this.minor = minor;
32 | }
33 |
34 | /**
35 | * Parse the given string and return the corresponding algorithm value
36 | *
37 | * @param identifier
38 | * String to parse
39 | *
40 | * @return EncFSFileNameEncryptionAlgorithm corresponding to the string.
41 | */
42 | public static EncFSFilenameEncryptionAlgorithm parse(String identifier) {
43 | for (EncFSFilenameEncryptionAlgorithm a : values()) {
44 | if (a.identifier.equals(identifier)) {
45 | return a;
46 | }
47 | }
48 | throw new IllegalArgumentException("could not parse: " + identifier);
49 | }
50 |
51 | public int getMajor() {
52 | return major;
53 | }
54 |
55 | public int getMinor() {
56 | return minor;
57 | }
58 |
59 | public String getIdentifier() {
60 | return identifier;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSInputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | import javax.crypto.BadPaddingException;
19 | import javax.crypto.IllegalBlockSizeException;
20 | import java.io.FilterInputStream;
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 | import java.security.InvalidAlgorithmParameterException;
24 |
25 | /**
26 | * FilterInputStream extension that allows decrypted data to be read from a file
27 | * on an EncFS volume.
28 | */
29 | public class EncFSInputStream extends FilterInputStream {
30 |
31 | // Volume that underlying file belongs to
32 | private final EncFSVolume volume;
33 |
34 | // Volume configuration for this file
35 | private final EncFSConfig config;
36 |
37 | // Cached block size for this volume
38 | private final int blockSize;
39 |
40 | // Number of MAC bytes for each block
41 | private final int numMACBytes;
42 |
43 | // Size of the block header for each block
44 | private final int blockHeaderSize;
45 |
46 | // Current block number for generating block IV
47 | private int blockNum;
48 |
49 | // Buffer containing decrypted data from the current block
50 | private byte[] blockBuf;
51 |
52 | // Cursor into blockBuf denoting current stream position
53 | private int bufCursor;
54 |
55 | // File IV computed from the first 8 bytes of the file
56 | private byte[] fileIv;
57 |
58 | /**
59 | * Create a new EncFSInputStream for reading decrypted data off a file on an
60 | * EncFS volume
61 | *
62 | * @param volume
63 | * Volume hosting the file to read
64 | * @param in
65 | * Input stream to access the raw (encrypted) file contents
66 | * @param volumePath
67 | * Volume path of the file being decrypted (needed for
68 | * externalIVChaining)
69 | */
70 | public EncFSInputStream(EncFSVolume volume, InputStream in,
71 | String volumePath) throws EncFSCorruptDataException,
72 | EncFSUnsupportedException {
73 | super(in);
74 | this.volume = volume;
75 | this.config = volume.getConfig();
76 | this.blockSize = config.getEncryptedFileBlockSizeInBytes();
77 | this.numMACBytes = config.getNumberOfMACBytesForEachFileBlock();
78 | int numRandBytes = config.getNumberOfRandomBytesInEachMACHeader();
79 | this.blockHeaderSize = this.numMACBytes + numRandBytes;
80 | this.blockBuf = null;
81 | this.bufCursor = 0;
82 | this.blockNum = 0;
83 |
84 | if (config.isUseUniqueIV()) {
85 | // Compute file IV
86 | byte[] fileHeader = new byte[EncFSFile.HEADER_SIZE];
87 | try {
88 | in.read(fileHeader);
89 | } catch (IOException e) {
90 | throw new EncFSCorruptDataException("Could't read file IV");
91 | }
92 |
93 | byte[] initIv;
94 | if (config.isSupportedExternalIVChaining()) {
95 | /*
96 | * When using external IV chaining we compute initIv based on
97 | * the file path.
98 | */
99 | initIv = StreamCrypto.computeChainIv(volume, volumePath);
100 | } else {
101 | // When not using external IV chaining initIv is just zero's.
102 | initIv = new byte[8];
103 | }
104 |
105 | try {
106 | this.fileIv = StreamCrypto.streamDecrypt(volume, initIv,
107 | fileHeader);
108 | } catch (InvalidAlgorithmParameterException e) {
109 | e.printStackTrace();
110 | } catch (IllegalBlockSizeException e) {
111 | throw new EncFSCorruptDataException(e);
112 | } catch (BadPaddingException e) {
113 | throw new EncFSCorruptDataException(e);
114 | }
115 | } else {
116 | // No unique IV per file, just use 0
117 | this.fileIv = new byte[EncFSFile.HEADER_SIZE];
118 | }
119 | }
120 |
121 | /*
122 | * (non-Javadoc)
123 | *
124 | * @see java.io.FileInputStream#read()
125 | */
126 | @Override
127 | public int read() throws IOException {
128 | byte[] oneByte = new byte[1];
129 | int ret = this.read(oneByte, 0, 1);
130 | if (ret == 1) {
131 | return oneByte[0] & 0xFF;
132 | }
133 | return -1;
134 | }
135 |
136 | /*
137 | * (non-Javadoc)
138 | *
139 | * @see java.io.FileInputStream#read(byte[])
140 | */
141 | @Override
142 | public int read(byte[] b) throws IOException {
143 | return read(b, 0, b.length);
144 | }
145 |
146 | /*
147 | * (non-Javadoc)
148 | *
149 | * @see java.io.InputStream#read(byte[], int, int)
150 | */
151 | @Override
152 | public int read(byte[] output, int offset, int size) throws IOException {
153 | int bytesRead = 0;
154 | int destOffset = offset;
155 | int bytesToCopy;
156 | int ret;
157 |
158 | while (bytesRead < size) {
159 |
160 | // Read more data if the data buffer is out
161 | if ((blockBuf == null) || (bufCursor == (blockBuf.length))) {
162 | try {
163 | ret = readBlock();
164 | } catch (EncFSCorruptDataException e) {
165 | throw new IOException(e);
166 | } catch (EncFSUnsupportedException e) {
167 | throw new IOException(e);
168 | }
169 |
170 | if (ret < 0) {
171 | if (bytesRead == 0) {
172 | return -1;
173 | } else {
174 | return bytesRead;
175 | }
176 | }
177 | }
178 |
179 | bytesToCopy = Math.min(blockBuf.length - bufCursor, size
180 | - bytesRead);
181 | System.arraycopy(blockBuf, bufCursor, output, destOffset,
182 | bytesToCopy);
183 |
184 | bufCursor += bytesToCopy;
185 | bytesRead += bytesToCopy;
186 | destOffset += bytesToCopy;
187 | }
188 |
189 | return bytesRead;
190 | }
191 |
192 | /*
193 | * (non-Javadoc)
194 | *
195 | * @see java.io.FileInputStream#skip(long)
196 | */
197 | @Override
198 | public long skip(long n) throws IOException {
199 | long bytesSkipped = 0;
200 | int toSkip;
201 | int bytesRead;
202 |
203 | byte[] skipBuf = new byte[config.getEncryptedFileBlockSizeInBytes()];
204 |
205 | if (n < 0) {
206 | throw new IOException("Negative skip count");
207 | }
208 |
209 | while (bytesSkipped < n) {
210 | toSkip = (int) Math.min(n - bytesSkipped,
211 | config.getEncryptedFileBlockSizeInBytes());
212 | bytesRead = this.read(skipBuf, 0, toSkip);
213 | bytesSkipped += bytesRead;
214 | if (bytesRead == -1) {
215 | return -1; // Already at EOF
216 | } else if (bytesRead < toSkip) {
217 | return bytesSkipped; // Hit EOF now
218 | }
219 | }
220 |
221 | return bytesSkipped;
222 | }
223 |
224 | /*
225 | * (non-Javadoc)
226 | *
227 | * @see java.io.InputStream#markSupported()
228 | */
229 | @Override
230 | public boolean markSupported() {
231 | // TODO: could support mark()/reset()
232 | return false;
233 | }
234 |
235 | // Return the block IV for the current block
236 | private byte[] getBlockIV() {
237 | long fileIvLong = EncFSUtil.convertByteArrayToLong(fileIv);
238 | return EncFSUtil.convertLongToByteArrayBigEndian(blockNum ^ fileIvLong);
239 | }
240 |
241 | /*
242 | * Read one block (blockSize bytes) of data from the underlying
243 | * FileInputStream, decrypt it and store it in blockBuf for consumption via
244 | * read() methods
245 | */
246 | private int readBlock() throws IOException, EncFSCorruptDataException,
247 | EncFSUnsupportedException {
248 | byte[] cipherBuf = new byte[blockSize];
249 | boolean zeroBlock = false;
250 |
251 | int bytesRead = 0;
252 | int lastBytesRead;
253 |
254 | // Read until we read a whole block or we reach the end of the input
255 | while (bytesRead < blockSize) {
256 | lastBytesRead = in
257 | .read(cipherBuf, bytesRead, blockSize - bytesRead);
258 | if (lastBytesRead > 0) {
259 | bytesRead += lastBytesRead;
260 | } else if (lastBytesRead < 0) {
261 | /*
262 | * If we read some bytes return that, if not then we're at the
263 | * end of the stream
264 | */
265 | if (bytesRead == 0) {
266 | bytesRead = -1;
267 | }
268 | break;
269 | }
270 | }
271 |
272 | if (bytesRead == blockSize) { // block decode
273 | /*
274 | * If file holes are allowed then we need to test whether the whole
275 | * block is made up of 0's. If not (which is going to be the case
276 | * for MAC header by default), we will do block decryption.
277 | */
278 | if (config.isHolesAllowedInFiles()) {
279 | zeroBlock = true;
280 | for (byte aCipherBuf : cipherBuf)
281 | if (aCipherBuf != 0) {
282 | zeroBlock = false;
283 | break;
284 | }
285 | }
286 |
287 | try {
288 | if (zeroBlock) {
289 | blockBuf = cipherBuf;
290 | } else {
291 | blockBuf = BlockCrypto.blockDecrypt(volume, getBlockIV(),
292 | cipherBuf);
293 | }
294 | } catch (InvalidAlgorithmParameterException e) {
295 | e.printStackTrace();
296 | } catch (IllegalBlockSizeException e) {
297 | throw new EncFSCorruptDataException(e);
298 | } catch (BadPaddingException e) {
299 | throw new EncFSCorruptDataException(e);
300 | }
301 |
302 | bufCursor = blockHeaderSize;
303 | blockNum++;
304 | } else if (bytesRead > 0) { // stream decode
305 | try {
306 | blockBuf = StreamCrypto.streamDecrypt(volume, getBlockIV(),
307 | cipherBuf, 0, bytesRead);
308 | } catch (InvalidAlgorithmParameterException e) {
309 | e.printStackTrace();
310 | } catch (IllegalBlockSizeException e) {
311 | throw new EncFSCorruptDataException(e);
312 | } catch (BadPaddingException e) {
313 | throw new EncFSCorruptDataException(e);
314 | }
315 | bufCursor = blockHeaderSize;
316 | blockNum++;
317 | }
318 |
319 | // Verify the block header
320 | if ((bytesRead > 0) && (blockHeaderSize > 0) && (!zeroBlock)) {
321 | byte mac[] = EncFSCrypto.mac64(volume.getMAC(), blockBuf,
322 | numMACBytes);
323 | for (int i = 0; i < numMACBytes; i++) {
324 | if (mac[7 - i] != blockBuf[i]) {
325 | throw new EncFSCorruptDataException("Block MAC mismatch");
326 | }
327 | }
328 | }
329 |
330 | return bytesRead;
331 | }
332 | }
333 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSInvalidConfigException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | public class EncFSInvalidConfigException extends EncFSException {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | public EncFSInvalidConfigException(String message) {
23 | super(message);
24 | }
25 |
26 | public EncFSInvalidConfigException(Throwable cause) {
27 | super(cause);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSInvalidPasswordException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | public class EncFSInvalidPasswordException extends EncFSException {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | public EncFSInvalidPasswordException(Throwable cause) {
23 | super(cause);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSLocalFileProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | import java.io.*;
19 | import java.nio.channels.FileChannel;
20 | import java.util.ArrayList;
21 | import java.util.List;
22 |
23 | /**
24 | * Class implementing an EncFSFileProvider for accessing the local filesystem
25 | *
26 | * Note that all path parameters are relative to the rootPath provided to the
27 | * constructor. Thus, if one instantiates an EncFSFileProvider("/home/jdoe"),
28 | * the proper way to refer to /home/jdoe/dir/file.ext is by "dir/file.ext".
29 | */
30 | public class EncFSLocalFileProvider implements EncFSFileProvider {
31 |
32 | private final String separator;
33 |
34 | private final File rootPath;
35 |
36 | public EncFSLocalFileProvider(File rootPath) {
37 | this.rootPath = rootPath;
38 | this.separator = File.separator;
39 | }
40 |
41 | /**
42 | * Returns whether the given source path represents a directory in the
43 | * underlying filesystem
44 | *
45 | * @param srcPath
46 | * Path of the source file or directory
47 | */
48 | public boolean isDirectory(String srcPath) {
49 | File file = new File(rootPath.getAbsoluteFile(), srcPath);
50 | return file.isDirectory();
51 | }
52 |
53 | /**
54 | * Get a File object representing the given path
55 | *
56 | * @param path
57 | * Path of the file or directory
58 | */
59 | File getFile(String path) {
60 | return new File(rootPath.getAbsoluteFile(), path);
61 | }
62 |
63 | /**
64 | * Returns the path separator for the underlying filesystem
65 | *
66 | * @return String representing the path separator
67 | */
68 | public final String getSeparator() {
69 | return separator;
70 | }
71 |
72 | /**
73 | * Returns the root path for the underlying filesystem
74 | *
75 | * @return String representing the root path
76 | */
77 | public final String getFilesystemRootPath() {
78 | return "/";
79 | }
80 |
81 | /**
82 | * Returns whether the file or directory exists
83 | *
84 | * @param srcPath
85 | * Path of the file or directory
86 | */
87 | public boolean exists(String srcPath) {
88 | return new File(rootPath.getAbsoluteFile(), srcPath).exists();
89 | }
90 |
91 | /**
92 | * Return EncFSFileInfo for the given file or directory
93 | *
94 | * @param srcPath
95 | * Path of the file or directory
96 | */
97 | public EncFSFileInfo getFileInfo(String srcPath) {
98 | File sourceFile = new File(rootPath.getAbsoluteFile(), srcPath);
99 | return convertToFileInfo(sourceFile);
100 | }
101 |
102 | /**
103 | * Returns the list of files under the given directory path
104 | *
105 | * @param dirPath
106 | * Path of the directory to list files from
107 | */
108 | public List listFiles(String dirPath) throws IOException {
109 | File srcDir = new File(rootPath.getAbsoluteFile(), dirPath);
110 | if (!srcDir.isDirectory()) {
111 | throw new IOException("Path: " + dirPath + " not a directory!");
112 | }
113 |
114 | File[] files = srcDir.listFiles();
115 | if (files == null) {
116 | /*
117 | * It's possible for a race condition to occur and srcDir to be
118 | * renamed or deleted between the isDirectory() check above and the
119 | * listFiles() call after it. We throw an exception in this case.
120 | */
121 | throw new IOException("Path: " + dirPath + " was removed!");
122 | }
123 |
124 | List results = new ArrayList(files.length);
125 | for (File file : files) {
126 | results.add(convertToFileInfo(file));
127 | }
128 | return results;
129 | }
130 |
131 | /**
132 | * Move a file/directory to a different location
133 | *
134 | * @param srcPath
135 | * Path to the source file or directory
136 | * @param dstPath
137 | * Path for the destination file or directory
138 | */
139 | public boolean move(String srcPath, String dstPath) throws IOException {
140 | File sourceFile = new File(rootPath.getAbsoluteFile(), srcPath);
141 | File destFile = new File(rootPath.getAbsoluteFile(), dstPath);
142 |
143 | if (!sourceFile.exists()) {
144 | throw new FileNotFoundException("Path '" + srcPath
145 | + "' doesn't exist!");
146 | }
147 |
148 | return sourceFile.renameTo(destFile);
149 | }
150 |
151 | /*
152 | * Recursive delete function
153 | */
154 | private void recursiveDelete(File file) throws IOException {
155 | if (file.isDirectory()) {
156 | for (File childFile : file.listFiles()) {
157 | recursiveDelete(childFile);
158 | }
159 | }
160 | if (!file.delete()) {
161 | throw new IOException("Failed to delete file " + file);
162 | }
163 | }
164 |
165 | /**
166 | * Delete the file or directory with the given path
167 | *
168 | * @param srcPath
169 | * Path of the source file or directory
170 | * @return true if deletion is successful, false otherwise
171 | */
172 | public boolean delete(String srcPath) {
173 | File toEncFile = new File(rootPath.getAbsoluteFile(), srcPath);
174 |
175 | try {
176 | recursiveDelete(toEncFile);
177 | } catch (IOException e) {
178 | return false;
179 | }
180 |
181 | return true;
182 | }
183 |
184 | /**
185 | * Create a directory with the given path
186 | *
187 | * Note that all path elements except the last one must exist for this
188 | * method. If that is not true mkdirs should be used instead
189 | *
190 | * @param dirPath
191 | * Path to create a directory under
192 | */
193 | public boolean mkdir(String dirPath) throws IOException {
194 | File file = new File(rootPath.getAbsoluteFile(), dirPath);
195 | File parentFile = file.getParentFile();
196 | if (!parentFile.exists()) {
197 | throw new FileNotFoundException("Path '"
198 | + parentFile.getAbsolutePath() + "' doesn't exist!");
199 | }
200 | return file.mkdir();
201 | }
202 |
203 | /**
204 | * Create a directory with the given path
205 | *
206 | * Intermediate directories are also created by this method
207 | *
208 | * @param dirPath
209 | * Path to create a directory under
210 | */
211 | public boolean mkdirs(String dirPath) {
212 | File toEncFile = new File(rootPath.getAbsoluteFile(), dirPath);
213 | return toEncFile.mkdirs();
214 | }
215 |
216 | /**
217 | * Create a file with the given path
218 | *
219 | * @param dstFilePath
220 | * Path for the file to create
221 | * @return EncFSFileInfo for the created file
222 | */
223 | public EncFSFileInfo createFile(String dstFilePath) throws IOException {
224 | if (exists(dstFilePath)) {
225 | throw new IOException("File already exists");
226 | }
227 |
228 | File targetFile = getFile(dstFilePath);
229 | if (!targetFile.createNewFile()) {
230 | throw new IOException("failed to create new file");
231 | }
232 |
233 | return convertToFileInfo(targetFile);
234 | }
235 |
236 | /**
237 | * Copy the file with the given path to another destination
238 | *
239 | * @param srcFilePath
240 | * Path to the file to copy
241 | * @param dstFilePath
242 | * Path to the destination file
243 | */
244 | public boolean copy(String srcFilePath, String dstFilePath)
245 | throws IOException {
246 |
247 | File sourceFile = new File(rootPath.getAbsoluteFile(), srcFilePath);
248 | File destFile = new File(rootPath.getAbsoluteFile(), dstFilePath);
249 |
250 | if (!sourceFile.exists()) {
251 | throw new FileNotFoundException("Source file '" + srcFilePath
252 | + "' doesn't exist!");
253 | }
254 |
255 | if (!destFile.exists()) {
256 | destFile.createNewFile();
257 | }
258 |
259 | FileChannel source = null;
260 | FileChannel destination = null;
261 |
262 | try {
263 | source = new FileInputStream(sourceFile).getChannel();
264 | destination = new FileOutputStream(destFile).getChannel();
265 | destination.transferFrom(source, 0, source.size());
266 | } finally {
267 | if (source != null) {
268 | source.close();
269 | }
270 | if (destination != null) {
271 | destination.close();
272 | }
273 | }
274 |
275 | return true;
276 | }
277 |
278 | /**
279 | * Open an InputStream to the given file
280 | *
281 | * @param srcFilePath
282 | * Path to the source file
283 | * @return InputStream to read from the file
284 | */
285 | public InputStream openInputStream(String srcFilePath)
286 | throws FileNotFoundException {
287 | File srcF = new File(rootPath.getAbsoluteFile(), srcFilePath);
288 | return new FileInputStream(srcF);
289 | }
290 |
291 | /**
292 | * Open an OutputStream to the given file
293 | *
294 | * @param dstFilePath
295 | * Path to the destination file
296 | */
297 | public OutputStream openOutputStream(String dstFilePath) throws IOException {
298 | return openOutputStream(dstFilePath, 0);
299 | }
300 |
301 | /**
302 | * Open an OutputStream to the given file
303 | *
304 | * @param dstFilePath
305 | * Path to the destination file
306 | * @param outputLength
307 | * Length in bytes of the stream that will be written to this
308 | * stream. It is ignored by this class.
309 | */
310 | public OutputStream openOutputStream(String dstFilePath, long outputLength)
311 | throws IOException {
312 | File srcF = new File(rootPath.getAbsoluteFile(), dstFilePath);
313 | if (!srcF.exists()) {
314 | try {
315 | srcF.createNewFile();
316 | } catch (Exception e) {
317 | throw new IOException(e);
318 | }
319 | }
320 | return new FileOutputStream(srcF);
321 | }
322 |
323 | // Convert the given File to an EncFSFileInfo
324 | private EncFSFileInfo convertToFileInfo(File file) {
325 | String relativePath;
326 | if (file.equals(rootPath.getAbsoluteFile())) {
327 | // we're dealing with the root dir
328 | relativePath = separator;
329 | } else if (file.getParentFile().equals(rootPath.getAbsoluteFile())) {
330 | // File is child of the root path
331 | relativePath = separator;
332 | } else {
333 | relativePath = file.getParentFile().getAbsolutePath()
334 | .substring(rootPath.getAbsoluteFile().toString().length());
335 | }
336 |
337 | String name = file.getName();
338 | return new EncFSFileInfo(name, relativePath, file.isDirectory(),
339 | file.lastModified(), file.length(), file.canRead(),
340 | file.canWrite(), file.canExecute());
341 | }
342 |
343 | }
344 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSOutputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | import javax.crypto.BadPaddingException;
19 | import javax.crypto.Cipher;
20 | import javax.crypto.IllegalBlockSizeException;
21 | import java.io.FilterOutputStream;
22 | import java.io.IOException;
23 | import java.io.OutputStream;
24 | import java.security.InvalidAlgorithmParameterException;
25 | import java.security.SecureRandom;
26 | import java.util.Arrays;
27 |
28 | /**
29 | * FilterOutputStream extension that allows encrypted data to be written to a
30 | * file on an EncFS volume.
31 | */
32 | public class EncFSOutputStream extends FilterOutputStream {
33 |
34 | // SecureRandom instance for random data generation
35 | private static final SecureRandom secureRandom = new SecureRandom();
36 |
37 | // Underlying volume
38 | private final EncFSVolume volume;
39 |
40 | // Volume configuration
41 | private final EncFSConfig config;
42 |
43 | // IV used for this file
44 | private byte[] fileIv;
45 |
46 | // Buffer to hold file header contents (uniqueIV)
47 | private byte[] fileHeader;
48 |
49 | // Buffer to hold the currently cached data contents to be written
50 | private final byte dataBuf[];
51 |
52 | // Count of the cached data bytes about to be written
53 | private int dataBytes;
54 |
55 | // Size of the block header for this file
56 | private int blockHeaderSize;
57 |
58 | // Number of random bytes per block header
59 | private int blockMACRandLen;
60 |
61 | // Number of MAC bytes per block header
62 | private int blockMACLen;
63 |
64 | // Index of the current block to be written
65 | private int curBlockIndex;
66 |
67 | /**
68 | * Create a new EncFSOutputStream for writing encrypted data to a file on an
69 | * EncFS volume
70 | *
71 | * @param volume
72 | * Volume hosting the file to write
73 | * @param out
74 | * Output stream for writing the encrypted (raw) data
75 | * @param volumePath
76 | * Volume path of the file being encrypted (needed for
77 | * externalIVChaining)
78 | *
79 | *
80 | * File data is corrupt
81 | *
82 | * Unsupported EncFS configuration
83 | */
84 | public EncFSOutputStream(EncFSVolume volume, OutputStream out,
85 | String volumePath) throws EncFSUnsupportedException,
86 | EncFSCorruptDataException {
87 | super(out);
88 | this.volume = volume;
89 | this.config = volume.getConfig();
90 | int blockSize = config.getEncryptedFileBlockSizeInBytes();
91 | this.blockHeaderSize = config.getNumberOfMACBytesForEachFileBlock()
92 | + config.getNumberOfRandomBytesInEachMACHeader();
93 | this.dataBytes = this.blockHeaderSize;
94 | this.blockMACLen = config.getNumberOfMACBytesForEachFileBlock();
95 | this.blockMACRandLen = config.getNumberOfRandomBytesInEachMACHeader();
96 |
97 | if (config.isUseUniqueIV()) {
98 | // Compute file IV
99 | this.fileHeader = new byte[8];
100 |
101 | secureRandom.nextBytes(fileHeader);
102 |
103 | byte[] initIv;
104 | if (config.isSupportedExternalIVChaining()) {
105 | /*
106 | * When using external IV chaining we compute initIv based on
107 | * the file path.
108 | */
109 | initIv = StreamCrypto.computeChainIv(volume, volumePath);
110 | } else {
111 | // When not using external IV chaining initIv is just zero's.
112 | initIv = new byte[8];
113 | }
114 |
115 | try {
116 | this.fileIv = StreamCrypto.streamDecrypt(volume, initIv,
117 | Arrays.copyOf(fileHeader, fileHeader.length));
118 | } catch (InvalidAlgorithmParameterException e) {
119 | e.printStackTrace();
120 | } catch (IllegalBlockSizeException e) {
121 | throw new EncFSCorruptDataException(e);
122 | } catch (BadPaddingException e) {
123 | throw new EncFSCorruptDataException(e);
124 | }
125 | } else {
126 | // No unique IV per file, just use 0
127 | this.fileIv = new byte[8];
128 | }
129 |
130 | Cipher blockCipher = BlockCrypto.newBlockCipher();
131 | try {
132 | EncFSCrypto.cipherInit(volume, Cipher.ENCRYPT_MODE, blockCipher,
133 | fileIv);
134 | } catch (InvalidAlgorithmParameterException e) {
135 | throw new EncFSCorruptDataException(e);
136 | }
137 | Cipher streamCipher = StreamCrypto.newStreamCipher();
138 | try {
139 | EncFSCrypto.cipherInit(volume, Cipher.ENCRYPT_MODE, streamCipher,
140 | fileIv);
141 | } catch (InvalidAlgorithmParameterException e) {
142 | throw new EncFSCorruptDataException(e);
143 | }
144 |
145 | // blockSize = blockHeaderSize + blockDataLen
146 | dataBuf = new byte[blockSize];
147 | }
148 |
149 | // Flush the internal buffer
150 | private void writeBuffer(boolean isFinal) throws IOException {
151 |
152 | if (!isFinal && dataBytes != dataBuf.length) {
153 | throw new IllegalStateException("Buffer not full");
154 | }
155 |
156 | if (curBlockIndex == 0 && config.isUseUniqueIV()) {
157 | out.write(this.fileHeader);
158 | }
159 |
160 | // Fill in the block header
161 | if (blockHeaderSize > 0) {
162 |
163 | // Add random bytes to the buffer
164 | if (blockMACRandLen > 0) {
165 | byte randomBytes[] = new byte[blockMACRandLen];
166 | secureRandom.nextBytes(randomBytes);
167 | System.arraycopy(randomBytes, 0, dataBuf, blockMACLen,
168 | blockMACRandLen);
169 | }
170 |
171 | // Compute MAC bytes and add them to the buffer
172 | byte mac[] = EncFSCrypto.mac64(volume.getMAC(), dataBuf,
173 | blockMACLen, dataBytes - blockMACLen);
174 | for (int i = 0; i < blockMACLen; i++) {
175 | dataBuf[i] = mac[7 - i];
176 | }
177 | }
178 |
179 | byte[] encBuffer;
180 | try {
181 | if (dataBytes == dataBuf.length) {
182 | /*
183 | * If allowHoles is configured, we scan the buffer to determine
184 | * whether we should pass this block through as a zero block.
185 | * Note that it is intended for the presence of a MAC header to
186 | * cause this check to fail.
187 | */
188 | boolean zeroBlock = false;
189 | if (config.isHolesAllowedInFiles()) {
190 | zeroBlock = true;
191 | for (byte aDataBuf : dataBuf) {
192 | if (aDataBuf != 0) {
193 | zeroBlock = false;
194 | break;
195 | }
196 | }
197 | }
198 |
199 | if (zeroBlock) {
200 | encBuffer = dataBuf;
201 | } else {
202 | encBuffer = BlockCrypto.blockEncrypt(volume,
203 | getBlockIV(), dataBuf);
204 | }
205 | } else {
206 | encBuffer = StreamCrypto.streamEncrypt(volume,
207 | getBlockIV(), dataBuf, 0, dataBytes);
208 | }
209 | } catch (IllegalBlockSizeException e) {
210 | throw new IOException(e);
211 | } catch (BadPaddingException e) {
212 | throw new IOException(e);
213 | } catch (InvalidAlgorithmParameterException e) {
214 | throw new IOException(e);
215 | } catch (EncFSUnsupportedException e) {
216 | throw new IOException(e);
217 | }
218 |
219 | out.write(encBuffer);
220 | dataBytes = blockHeaderSize;
221 | curBlockIndex++;
222 | }
223 |
224 | // Return the block IV for the current block
225 | private byte[] getBlockIV() {
226 | long fileIvLong = EncFSUtil.convertByteArrayToLong(fileIv);
227 | return EncFSUtil.convertLongToByteArrayBigEndian(curBlockIndex
228 | ^ fileIvLong);
229 | }
230 |
231 | // Flush the internal buffer
232 | private void writeBuffer() throws IOException {
233 | writeBuffer(false);
234 | }
235 |
236 | /*
237 | * (non-Javadoc)
238 | *
239 | * @see java.io.FilterOutputStream#write(int)
240 | */
241 | @Override
242 | public synchronized void write(int b) throws IOException {
243 | dataBuf[dataBytes++] = (byte) b;
244 |
245 | if (dataBytes == dataBuf.length) {
246 | writeBuffer();
247 | }
248 | }
249 |
250 | /*
251 | * (non-Javadoc)
252 | *
253 | * @see java.io.FilterOutputStream#write(int)
254 | */
255 | @Override
256 | public synchronized void write(byte b[], int off, int len)
257 | throws IOException {
258 | if (dataBytes + len <= dataBuf.length) {
259 | System.arraycopy(b, off, dataBuf, dataBytes, len);
260 | dataBytes += len;
261 |
262 | if (dataBytes == dataBuf.length) {
263 | writeBuffer();
264 | }
265 | } else {
266 | int tmpOff = off;
267 | int remaining = len;
268 | while (remaining > 0) {
269 | int chunk = Math.min(remaining, dataBuf.length - dataBytes);
270 |
271 | write(b, tmpOff, chunk);
272 |
273 | remaining -= chunk;
274 | tmpOff += chunk;
275 | }
276 | }
277 | }
278 |
279 | /*
280 | * (non-Javadoc)
281 | *
282 | * @see java.io.FilterOutputStream#write(int)
283 | */
284 | @Override
285 | public void close() throws IOException {
286 | writeBuffer(true);
287 | super.close();
288 | }
289 | }
290 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSPBKDF2Provider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | /**
19 | * Abstract class for providing a custom PBKDF2 implementation
20 | */
21 | public abstract class EncFSPBKDF2Provider {
22 |
23 | /**
24 | * @param passwordLen
25 | * Length of the password provided in 'password'
26 | * @param password
27 | * Password to hash
28 | * @param saltLen
29 | * Length of the salt provided in 'salt'
30 | * @param salt
31 | * Salt data
32 | * @param iterations
33 | * Number of PBKDF2 iterations to perform
34 | * @param keyLen
35 | * Desired length of the resulting key material in bytes
36 | * @return Byte array containing the result of the PBKDF2 computation. null
37 | * if the computation failed.
38 | */
39 | public abstract byte[] doPBKDF2(String password, int saltLen, byte[] salt,
40 | int iterations, int keyLen);
41 |
42 | }
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSProgressListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | /**
19 | * Class representing a progress listener for long running operations
20 | */
21 | public abstract class EncFSProgressListener {
22 |
23 | /**
24 | * Event notifying that the number of affected files/directories have been
25 | * counted.
26 | */
27 | public static final int FILES_COUNTED_EVENT = 0;
28 |
29 | /**
30 | * Event notifying that a new file has started to be processed
31 | */
32 | public static final int NEW_FILE_EVENT = 1;
33 |
34 | /**
35 | * Event notifying that a single file or directory has been processed.
36 | */
37 | public static final int FILE_PROCESS_EVENT = 2;
38 |
39 | /**
40 | * Event notifying completion of the whole operation.
41 | */
42 | public static final int OP_COMPLETE_EVENT = 3;
43 |
44 | // Name of the current file being operated on
45 | private String currentFile = null;
46 |
47 | // Number of files being operated on
48 | private int numFiles = 0;
49 |
50 | /**
51 | * Method that must be overridden by extending class to handle events posted
52 | * to the event listener
53 | *
54 | * @param eventType
55 | * Type of the event that just occured
56 | */
57 | public abstract void handleEvent(int eventType);
58 |
59 | /**
60 | * Get the name of the current file being operated on
61 | *
62 | * @return name of the current file being operated on
63 | */
64 | public String getCurrentFile() {
65 | return currentFile;
66 | }
67 |
68 | /**
69 | * Get the total number of files that the operation will proceed on. Note
70 | * that this value is undefined until a FILES_COUNTED_EVENT is posted first
71 | *
72 | * @return total number of files that the operation will proceed on
73 | */
74 | public int getNumFiles() {
75 | return numFiles;
76 | }
77 |
78 | // Post an event to the progress listener
79 | void postEvent(int eventType) {
80 | handleEvent(eventType);
81 | }
82 |
83 | // Set the current file
84 | void setCurrentFile(String fileName) {
85 | currentFile = fileName;
86 | postEvent(NEW_FILE_EVENT);
87 | }
88 |
89 | // Set the total number of files being operated on
90 | void setNumFiles(int numFiles) {
91 | this.numFiles = numFiles;
92 | postEvent(FILES_COUNTED_EVENT);
93 | }
94 | }
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSUnsupportedException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | public class EncFSUnsupportedException extends EncFSException {
19 |
20 | private static final long serialVersionUID = 1L;
21 |
22 | public EncFSUnsupportedException(String message) {
23 | super(message);
24 | }
25 |
26 | public EncFSUnsupportedException(Throwable cause) {
27 | super(cause);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011 Mark R. Pariente
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs;
17 |
18 | import java.io.IOException;
19 | import java.io.InputStream;
20 | import java.io.OutputStream;
21 | import java.nio.ByteBuffer;
22 |
23 | /**
24 | * Class containing static methods implementing misc. functionality for the rest
25 | * of the library
26 | */
27 | public final class EncFSUtil {
28 |
29 | private static final int EIGHT = 8;
30 | private static final int EIGHT_KILO = 8192;
31 |
32 | EncFSUtil() {
33 | }
34 |
35 | /**
36 | * Convert the given byte array to 'int'
37 | *
38 | * @param b
39 | * A 4-byte array
40 | *
41 | * @return int value of the array contents
42 | */
43 | public static int convertBigEndianByteArrayToInt(byte[] b) {
44 | int capacity = Integer.SIZE / EIGHT;
45 | if (b.length > capacity) {
46 | return -1;
47 | }
48 | return ByteBuffer.wrap(b).getInt();
49 | }
50 |
51 | /**
52 | * Convert the given int to a 4-byte array
53 | *
54 | * @param i
55 | * An 'int'
56 | *
57 | * @return A 4-byte array in big endian (MSB) ordering
58 | */
59 | public static byte[] convertIntToByteArrayBigEndian(int i) {
60 | return ByteBuffer.allocate(Integer.SIZE / EIGHT).putInt(i).array();
61 | }
62 |
63 | /**
64 | * Convert the given byte array to 'long'
65 | *
66 | * @param b
67 | * An 8-byte array
68 | * @return long value of the array contents
69 | */
70 | public static long convertByteArrayToLong(byte[] b) {
71 | int capacity = Long.SIZE / EIGHT;
72 | if (b.length > capacity) {
73 | return -1;
74 | }
75 | return ByteBuffer.wrap(b).getLong();
76 | }
77 |
78 | /**
79 | * Convert the given long to an 8-byte array
80 | *
81 | * @param l
82 | * A 'long'
83 | *
84 | * @return An 8-byte array in big endian (MSB) ordering
85 | */
86 | public static byte[] convertLongToByteArrayBigEndian(long l) {
87 | return ByteBuffer.allocate(Long.SIZE / EIGHT).putLong(l).array();
88 | }
89 |
90 | /**
91 | * Copy the entire content of an InputStream into an OutputStream and close
92 | * only the input stream.
93 | *
94 | * @param in
95 | * The InputStream to read data from
96 | * @param out
97 | * The OutputStream to write data to
98 | *
99 | * @throws IOException
100 | * I/O exception from read or write
101 | */
102 | public static void copyWholeStreamAndCloseInput(InputStream in,
103 | OutputStream out) throws IOException {
104 | try {
105 | readFromAndWriteTo(in, out);
106 | } finally {
107 | in.close();
108 | }
109 | }
110 |
111 | /**
112 | * Copy the entire content of an InputStream into an OutputStream and close
113 | * both streams.
114 | *
115 | * @param in
116 | * The InputStream to read data from
117 | * @param out
118 | * The OutputStream to write data to
119 | *
120 | * @throws IOException
121 | * I/O exception from read or write
122 | */
123 | public static void copyWholeStreamAndClose(InputStream in, OutputStream out)
124 | throws IOException {
125 | try {
126 | copyWholeStreamAndCloseInput(in, out);
127 | } finally {
128 | out.close();
129 | }
130 | }
131 |
132 | private static void readFromAndWriteTo(InputStream in, OutputStream out)
133 | throws IOException {
134 | byte[] buf = new byte[EIGHT_KILO];
135 | int bytesRead = in.read(buf);
136 | while (bytesRead >= 0) {
137 | out.write(buf, 0, bytesRead);
138 | bytesRead = in.read(buf);
139 | }
140 | }
141 | }
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/EncFSVolumeBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | import java.io.File;
18 | import java.io.IOException;
19 | import java.security.SecureRandom;
20 |
21 | /**
22 | * Class for building EncFSVolume objects and writing new volume files to file
23 | * providers.
24 | *
25 | * Usage (in order):
26 | *
27 | * [Required] .withFileProvider(provider) OR .withRootPath(rootPath)
28 | *
29 | * [Optional] .withConfig(config) AND/OR .withPbkdfProvider(pbkdf2provider)
30 | *
31 | * [Required] .withPassword(password)
32 | *
33 | *
34 | * Volume building methods:
35 | * .writeVolumeConfig() - Write volume configuration file to the file provider
36 | * .buildVolume() - Return an EncFSVolume
37 | */
38 | public final class EncFSVolumeBuilder {
39 |
40 | public static class FileProviderBuilder {
41 |
42 | private final EncFSVolume volume;
43 |
44 | public FileProviderBuilder(EncFSVolume volume, String rootPath) {
45 | this(volume, new EncFSLocalFileProvider(new File(rootPath)));
46 | }
47 |
48 | public FileProviderBuilder(EncFSVolume volume,
49 | EncFSFileProvider fileProvider) {
50 | this.volume = volume;
51 | volume.setFileProvider(fileProvider);
52 | }
53 |
54 | public ConfigBuilder withConfig(EncFSConfig config) {
55 | return new ConfigBuilder(volume, config);
56 | }
57 |
58 | public Pbkdf2ProviderBuilder withPbkdf2Provider(
59 | EncFSPBKDF2Provider pbkdf2Provider)
60 | throws EncFSUnsupportedException, IOException,
61 | EncFSInvalidConfigException {
62 | return new ConfigBuilder(volume).withPbkdf2Provider(pbkdf2Provider);
63 | }
64 |
65 | public PasswordBuilder withPassword(String password)
66 | throws EncFSUnsupportedException, IOException,
67 | EncFSInvalidConfigException, EncFSCorruptDataException,
68 | EncFSInvalidPasswordException {
69 | return withPbkdf2Provider(null).withPassword(password);
70 | }
71 |
72 | public PasswordBuilder withDerivedKeyData(byte[] derivedKeyData)
73 | throws EncFSUnsupportedException, IOException,
74 | EncFSInvalidConfigException, EncFSCorruptDataException,
75 | EncFSInvalidPasswordException {
76 | return withPbkdf2Provider(null).withDerivedKeyData(derivedKeyData);
77 | }
78 | }
79 |
80 | public static class ConfigBuilder {
81 |
82 | private final EncFSVolume volume;
83 |
84 | public ConfigBuilder(EncFSVolume volume, EncFSConfig config) {
85 | this.volume = volume;
86 | volume.setVolumeConfig(config);
87 | }
88 |
89 | public ConfigBuilder(EncFSVolume volume)
90 | throws EncFSUnsupportedException, IOException,
91 | EncFSInvalidConfigException {
92 | this.volume = volume;
93 | EncFSFileProvider fileProvider = volume.getFileProvider();
94 | EncFSConfig volumeConfiguration = EncFSConfigParser.parseConfig(
95 | fileProvider, EncFSVolume.CONFIG_FILE_NAME);
96 | volume.setVolumeConfig(volumeConfiguration);
97 | }
98 |
99 | public Pbkdf2ProviderBuilder withPbkdf2Provider(
100 | EncFSPBKDF2Provider provider) {
101 | return new Pbkdf2ProviderBuilder(volume, provider);
102 | }
103 |
104 | public PasswordBuilder withPassword(String password)
105 | throws EncFSCorruptDataException,
106 | EncFSInvalidPasswordException, EncFSInvalidConfigException,
107 | EncFSUnsupportedException, IOException {
108 | return withPbkdf2Provider(null).withPassword(password);
109 | }
110 |
111 | public PasswordBuilder withDerivedKeyData(byte[] derivedKeyData)
112 | throws EncFSUnsupportedException, IOException,
113 | EncFSInvalidConfigException, EncFSCorruptDataException,
114 | EncFSInvalidPasswordException {
115 | return withPbkdf2Provider(null).withDerivedKeyData(derivedKeyData);
116 | }
117 | }
118 |
119 | public static class Pbkdf2ProviderBuilder {
120 |
121 | private final EncFSVolume volume;
122 | private final EncFSPBKDF2Provider provider;
123 |
124 | public Pbkdf2ProviderBuilder(EncFSVolume volume,
125 | EncFSPBKDF2Provider provider) {
126 | this.volume = volume;
127 | this.provider = provider;
128 | }
129 |
130 | public PasswordBuilder withPassword(String password) {
131 | return new PasswordBuilder(volume, password, provider);
132 | }
133 |
134 | public PasswordBuilder withDerivedKeyData(byte[] derivedKeyData) {
135 | return new PasswordBuilder(volume, derivedKeyData);
136 | }
137 | }
138 |
139 | public static class PasswordBuilder {
140 |
141 | private final EncFSVolume volume;
142 | private final EncFSPBKDF2Provider provider;
143 | private final String password;
144 |
145 | public PasswordBuilder(EncFSVolume volume, byte[] derivedPassword) {
146 | this.volume = volume;
147 | this.provider = null;
148 | this.password = null;
149 | volume.setDerivedKeyData(derivedPassword);
150 |
151 | }
152 |
153 | public PasswordBuilder(EncFSVolume volume, String password,
154 | EncFSPBKDF2Provider provider) {
155 | this.volume = volume;
156 | this.password = password;
157 | this.provider = provider;
158 | }
159 |
160 | /**
161 | * Creates a new object representing an existing EncFS volume
162 | *
163 | * @throws EncFSInvalidPasswordException
164 | * Given password is incorrect
165 | * @throws EncFSCorruptDataException
166 | * Corrupt data detected (checksum error)
167 | * @throws EncFSInvalidConfigException
168 | * Configuration file format not recognized
169 | * @throws EncFSUnsupportedException
170 | * Unsupported EncFS version or options
171 | * @throws IOException
172 | * File provider returned I/O error
173 | */
174 | public EncFSVolume buildVolume() throws EncFSUnsupportedException,
175 | IOException, EncFSInvalidConfigException,
176 | EncFSInvalidPasswordException, EncFSCorruptDataException {
177 | EncFSConfig config = volume.getConfig();
178 | if (password != null) {
179 | byte[] derivedKeyData = VolumeKey.deriveKeyDataFromPassword(
180 | config, password, provider);
181 | volume.setDerivedKeyData(derivedKeyData);
182 | }
183 | volume.readConfigAndInitVolume();
184 | return volume;
185 | }
186 |
187 | /**
188 | * Writes EncFS volume configuration to the file provider
189 | *
190 | * @throws EncFSInvalidPasswordException
191 | * Given password is incorrect
192 | * @throws EncFSCorruptDataException
193 | * Corrupt data detected (checksum error)
194 | * @throws EncFSInvalidConfigException
195 | * Configuration file format not recognized
196 | * @throws EncFSUnsupportedException
197 | * Unsupported EncFS version or options
198 | * @throws IOException
199 | * File provider returned I/O error
200 | */
201 | public void writeVolumeConfig() throws EncFSUnsupportedException,
202 | IOException, EncFSInvalidConfigException,
203 | EncFSCorruptDataException {
204 | EncFSConfig config = volume.getConfig();
205 | EncFSFileProvider fileProvider = volume.getFileProvider();
206 |
207 | // Create a random volume VolumeCryptKey + IV pair
208 | byte[] randVolKey = new byte[config.getVolumeKeySizeInBits() / 8
209 | + EncFSVolume.IV_LENGTH_IN_BYTES];
210 | new SecureRandom().nextBytes(randVolKey);
211 |
212 | VolumeKey.encodeVolumeKey(config, password, randVolKey, provider);
213 | EncFSConfigWriter.writeConfig(fileProvider, config);
214 | }
215 | }
216 |
217 | public FileProviderBuilder withRootPath(String rootPath) {
218 | return new FileProviderBuilder(new EncFSVolume(), rootPath);
219 | }
220 |
221 | public FileProviderBuilder withFileProvider(EncFSFileProvider fileProvider) {
222 | return new FileProviderBuilder(new EncFSVolume(), fileProvider);
223 | }
224 | }
225 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/FilenameDecryptionStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | // Common class for all filename decryption strategies
18 | abstract class FilenameDecryptionStrategy {
19 |
20 | private final EncFSVolume volume;
21 | private final String volumePath;
22 | private final EncFSFilenameEncryptionAlgorithm algorithm;
23 |
24 | String getVolumePath() {
25 | return volumePath;
26 | }
27 |
28 | EncFSVolume getVolume() {
29 | return volume;
30 | }
31 |
32 | FilenameDecryptionStrategy(EncFSVolume volume, String volumePath,
33 | EncFSFilenameEncryptionAlgorithm algorithm) {
34 | this.volume = volume;
35 | this.volumePath = volumePath;
36 | this.algorithm = algorithm;
37 | }
38 |
39 | // Decryption implementation to be provided by subclass
40 | protected abstract String decryptImpl(String fileName)
41 | throws EncFSCorruptDataException, EncFSChecksumException;
42 |
43 | // Decrypt the given filename
44 | public String decrypt(String filename) throws EncFSChecksumException,
45 | EncFSCorruptDataException {
46 | if (volume.getConfig().getFilenameAlgorithm() != algorithm) {
47 | throw new IllegalStateException(
48 | "only accessable when algorithm is " + algorithm);
49 | }
50 |
51 | return decryptImpl(filename);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/FilenameEncryptionStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | // Common class for all filename encryption strategies
18 | abstract class FilenameEncryptionStrategy {
19 |
20 | private final EncFSVolume volume;
21 | private final String volumePath;
22 | private final EncFSFilenameEncryptionAlgorithm algorithm;
23 |
24 | String getVolumePath() {
25 | return volumePath;
26 | }
27 |
28 | EncFSVolume getVolume() {
29 | return volume;
30 | }
31 |
32 | FilenameEncryptionStrategy(EncFSVolume volume, String volumePath,
33 | EncFSFilenameEncryptionAlgorithm algorithm) {
34 | this.volume = volume;
35 | this.volumePath = volumePath;
36 | this.algorithm = algorithm;
37 | }
38 |
39 | // Encryption implementation to be provided by subclass
40 | protected abstract String encryptImpl(String fileName)
41 | throws EncFSCorruptDataException;
42 |
43 | // Encrypt the given filename
44 | public String encrypt(String filename) throws EncFSCorruptDataException {
45 | if (volume.getConfig().getFilenameAlgorithm() != algorithm) {
46 | throw new IllegalStateException(
47 | "only accessable when algorithm is " + algorithm);
48 | }
49 |
50 | return encryptImpl(filename);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/NullFilenameDecryptionStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | // Class implementing the NULL decryption strategy
18 | public class NullFilenameDecryptionStrategy extends FilenameDecryptionStrategy {
19 |
20 | public NullFilenameDecryptionStrategy(EncFSVolume volume, String volumePath) {
21 | super(volume, volumePath, EncFSFilenameEncryptionAlgorithm.NULL);
22 | }
23 |
24 | @Override
25 | protected String decryptImpl(String fileName)
26 | throws EncFSCorruptDataException, EncFSChecksumException {
27 | EncFSFile rootDir = getVolume().getRootDir();
28 | // Filter out config file
29 | if (getVolumePath().equals(rootDir.getPath())
30 | && fileName.equals(EncFSVolume.CONFIG_FILE_NAME)) {
31 | return null;
32 | }
33 | return fileName;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/NullFilenameEncryptionStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | // Class implementing the NULL encryption strategy
18 | public class NullFilenameEncryptionStrategy extends FilenameEncryptionStrategy {
19 |
20 | public NullFilenameEncryptionStrategy(EncFSVolume volume, String volumePath) {
21 | super(volume, volumePath, EncFSFilenameEncryptionAlgorithm.NULL);
22 | }
23 |
24 | @Override
25 | protected String encryptImpl(String fileName) {
26 | return fileName;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/StreamCrypto.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | import javax.crypto.BadPaddingException;
18 | import javax.crypto.Cipher;
19 | import javax.crypto.IllegalBlockSizeException;
20 | import javax.crypto.Mac;
21 | import java.security.InvalidAlgorithmParameterException;
22 | import java.security.Key;
23 | import java.util.Arrays;
24 | import java.util.StringTokenizer;
25 |
26 | // Static methods for stream cryptography
27 | public class StreamCrypto {
28 |
29 | // Returns a stream cipher
30 | public static Cipher newStreamCipher() throws EncFSUnsupportedException {
31 | return EncFSCrypto.getCipher(EncFSCrypto.STREAM_CIPHER);
32 | }
33 |
34 | // Stream decryption implementation
35 | private static byte[] streamDecrypt(Cipher cipher, Mac mac, Key key,
36 | byte[] iv, byte[] ivSeed, byte[] data, int offset, int len)
37 | throws EncFSUnsupportedException,
38 | InvalidAlgorithmParameterException, IllegalBlockSizeException,
39 | BadPaddingException {
40 | // First round uses IV seed + 1 for IV generation
41 | byte[] ivSeedPlusOne = EncFSCrypto.incrementIvSeedByOne(ivSeed);
42 |
43 | EncFSCrypto.cipherInit(key, mac, Cipher.DECRYPT_MODE, cipher, iv,
44 | ivSeedPlusOne);
45 | byte[] firstDecResult = cipher.doFinal(data, offset, len);
46 |
47 | EncFSCrypto.unshuffleBytes(firstDecResult);
48 |
49 | byte[] flipBytesResult = EncFSCrypto.flipBytes(firstDecResult);
50 |
51 | // Second round of decryption with IV seed itself used for IV generation
52 | EncFSCrypto.cipherInit(key, mac, Cipher.DECRYPT_MODE, cipher, iv,
53 | ivSeed);
54 | byte[] result = cipher.doFinal(flipBytesResult);
55 |
56 | EncFSCrypto.unshuffleBytes(result);
57 |
58 | return result;
59 | }
60 |
61 | // Stream decryption implementation
62 | static byte[] streamDecrypt(Cipher cipher, Mac mac, Key key, byte[] iv,
63 | byte[] ivSeed, byte[] data) throws EncFSUnsupportedException,
64 | InvalidAlgorithmParameterException, IllegalBlockSizeException,
65 | BadPaddingException {
66 | return streamDecrypt(cipher, mac, key, iv, ivSeed, data, 0, data.length);
67 | }
68 |
69 | // Stream decryption implementation
70 | public static byte[] streamDecrypt(EncFSVolume volume, byte[] ivSeed,
71 | byte[] data) throws EncFSUnsupportedException,
72 | InvalidAlgorithmParameterException, IllegalBlockSizeException,
73 | BadPaddingException {
74 | Cipher streamCipher = volume.getStreamCipher();
75 | return streamDecrypt(streamCipher, volume.getMAC(), volume.getKey(),
76 | volume.getIV(), ivSeed, data);
77 | }
78 |
79 | // Stream decryption implementation
80 | public static byte[] streamDecrypt(EncFSVolume volume, byte[] ivSeed,
81 | byte[] data, int offset, int len) throws EncFSUnsupportedException,
82 | InvalidAlgorithmParameterException, IllegalBlockSizeException,
83 | BadPaddingException {
84 | return streamDecrypt(volume.getStreamCipher(), volume.getMAC(),
85 | volume.getKey(), volume.getIV(), ivSeed, data, offset, len);
86 | }
87 |
88 | // Stream encryption implementation
89 | private static byte[] streamEncrypt(Cipher cipher, Mac mac, Key key,
90 | byte[] iv, byte[] ivSeed, byte[] data, int offset, int len)
91 | throws EncFSUnsupportedException,
92 | InvalidAlgorithmParameterException, IllegalBlockSizeException,
93 | BadPaddingException {
94 | // First round uses IV seed + 1 for IV generation
95 | byte[] ivSeedPlusOne = EncFSCrypto.incrementIvSeedByOne(ivSeed);
96 |
97 | byte[] encBuf = Arrays.copyOfRange(data, offset, offset + len);
98 | EncFSCrypto.shuffleBytes(encBuf);
99 |
100 | EncFSCrypto.cipherInit(key, mac, Cipher.ENCRYPT_MODE, cipher, iv,
101 | ivSeed);
102 | byte[] firstEncResult = cipher.doFinal(encBuf);
103 |
104 | byte[] flipBytesResult = EncFSCrypto.flipBytes(firstEncResult);
105 |
106 | EncFSCrypto.shuffleBytes(flipBytesResult);
107 |
108 | // Second round of encryption with IV seed itself used for IV generation
109 | EncFSCrypto.cipherInit(key, mac, Cipher.ENCRYPT_MODE, cipher, iv,
110 | ivSeedPlusOne);
111 |
112 | return cipher.doFinal(flipBytesResult);
113 | }
114 |
115 | // Stream encryption implementation
116 | static byte[] streamEncrypt(Cipher cipher, Mac mac, Key key, byte[] iv,
117 | byte[] ivSeed, byte[] data) throws EncFSUnsupportedException,
118 | InvalidAlgorithmParameterException, IllegalBlockSizeException,
119 | BadPaddingException {
120 | return streamEncrypt(cipher, mac, key, iv, ivSeed, data, 0, data.length);
121 | }
122 |
123 | // Stream encryption implementation
124 | public static byte[] streamEncrypt(EncFSVolume volume, byte[] ivSeed,
125 | byte[] data) throws EncFSUnsupportedException,
126 | InvalidAlgorithmParameterException, IllegalBlockSizeException,
127 | BadPaddingException {
128 | return streamEncrypt(volume.getStreamCipher(), volume.getMAC(),
129 | volume.getKey(), volume.getIV(), ivSeed, data);
130 | }
131 |
132 | // Stream encryption implementation
133 | public static byte[] streamEncrypt(EncFSVolume volume, byte[] ivSeed,
134 | byte[] data, int offset, int len) throws EncFSUnsupportedException,
135 | InvalidAlgorithmParameterException, IllegalBlockSizeException,
136 | BadPaddingException {
137 | return streamEncrypt(volume.getStreamCipher(), volume.getMAC(),
138 | volume.getKey(), volume.getIV(), ivSeed, data, offset, len);
139 | }
140 |
141 | /**
142 | * Compute chain IV for the given volume path
143 | *
144 | * @param volume
145 | * Volume to compute chain IV for
146 | * @param volumePath
147 | * Volume path to compute chain IV for
148 | * @return Computed chain IV
149 | */
150 | public static byte[] computeChainIv(EncFSVolume volume, String volumePath) {
151 | byte[] chainIv = new byte[8];
152 | StringTokenizer st = new StringTokenizer(volumePath,
153 | EncFSVolume.PATH_SEPARATOR);
154 | while (st.hasMoreTokens()) {
155 | String curPath = st.nextToken();
156 | if ((curPath.length() > 0)
157 | && (!curPath.equals(EncFSVolume.PATH_SEPARATOR))) {
158 | byte[] encodeBytes;
159 | if (volume.getConfig().getFilenameAlgorithm() == EncFSFilenameEncryptionAlgorithm.BLOCK) {
160 | encodeBytes = EncFSCrypto
161 | .getBytesForBlockAlgorithm(curPath);
162 | } else {
163 | encodeBytes = curPath.getBytes();
164 | }
165 |
166 | // Update chain IV
167 | EncFSCrypto.mac64(volume.getMAC(), encodeBytes, chainIv);
168 | }
169 | }
170 |
171 | return chainIv;
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/StreamFilenameDecryptionStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | import javax.crypto.BadPaddingException;
18 | import javax.crypto.IllegalBlockSizeException;
19 | import java.security.InvalidAlgorithmParameterException;
20 |
21 | // Class implementing stream filename decryption strategy
22 | public class StreamFilenameDecryptionStrategy extends
23 | BasicFilenameDecryptionStrategy {
24 |
25 | public StreamFilenameDecryptionStrategy(EncFSVolume volume,
26 | String volumePath) {
27 | super(volume, volumePath, EncFSFilenameEncryptionAlgorithm.STREAM);
28 | }
29 |
30 | // Stream decryption
31 | protected byte[] decryptConcrete(EncFSVolume volume, byte[] encFileName,
32 | byte[] fileIv) throws EncFSCorruptDataException {
33 | try {
34 | return StreamCrypto.streamDecrypt(volume, fileIv, encFileName);
35 | } catch (InvalidAlgorithmParameterException e) {
36 | throw new EncFSCorruptDataException(e);
37 | } catch (IllegalBlockSizeException e) {
38 | throw new EncFSCorruptDataException(e);
39 | } catch (BadPaddingException e) {
40 | throw new EncFSCorruptDataException(e);
41 | } catch (EncFSUnsupportedException e) {
42 | throw new EncFSCorruptDataException(e);
43 | }
44 | }
45 |
46 | public String decryptPost(byte[] fileName) {
47 | return new String(fileName);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/StreamFilenameEncryptionStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | import javax.crypto.BadPaddingException;
18 | import javax.crypto.IllegalBlockSizeException;
19 | import java.security.InvalidAlgorithmParameterException;
20 |
21 | //Implementation of block filename decryption strategy
22 | public class StreamFilenameEncryptionStrategy extends
23 | BasicFilenameEncryptionStrategy {
24 |
25 | public StreamFilenameEncryptionStrategy(EncFSVolume volume,
26 | String volumePath) {
27 | super(volume, volumePath, EncFSFilenameEncryptionAlgorithm.STREAM);
28 | }
29 |
30 | // Stream encryption
31 | @Override
32 | protected byte[] encryptConcrete(EncFSVolume volume,
33 | byte[] paddedDecFileName, byte[] fileIv)
34 | throws EncFSCorruptDataException {
35 | try {
36 | return StreamCrypto.streamEncrypt(volume, fileIv,
37 | paddedDecFileName);
38 | } catch (InvalidAlgorithmParameterException e) {
39 | throw new EncFSCorruptDataException(e);
40 | } catch (IllegalBlockSizeException e) {
41 | throw new EncFSCorruptDataException(e);
42 | } catch (BadPaddingException e) {
43 | throw new EncFSCorruptDataException(e);
44 | } catch (EncFSUnsupportedException e) {
45 | throw new EncFSCorruptDataException(e);
46 | }
47 | }
48 |
49 | protected byte[] getPaddedDecFilename(byte[] decFileName) {
50 | return decFileName;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/org/mrpdaemon/sec/encfs/VolumeKey.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs;
16 |
17 | import javax.crypto.*;
18 | import javax.crypto.spec.PBEKeySpec;
19 | import java.io.IOException;
20 | import java.security.*;
21 | import java.security.spec.InvalidKeySpecException;
22 | import java.security.spec.KeySpec;
23 | import java.util.Arrays;
24 |
25 | // Class containing static methods implementing volume key functionality
26 | class VolumeKey {
27 |
28 | // Derive volume key for the given config and password-based key/IV data
29 | private static byte[] encryptVolumeKey(EncFSConfig config,
30 | byte[] pbkdf2Data, byte[] volKeyData)
31 | throws EncFSUnsupportedException, EncFSInvalidConfigException,
32 | EncFSCorruptDataException {
33 | // Prepare key/IV for decryption
34 | int keySizeInBytes = config.getVolumeKeySizeInBits() / 8;
35 | byte[] passKeyData = Arrays.copyOfRange(pbkdf2Data, 0, keySizeInBytes);
36 | byte[] passIvData = Arrays.copyOfRange(pbkdf2Data, keySizeInBytes,
37 | keySizeInBytes + EncFSVolume.IV_LENGTH_IN_BYTES);
38 |
39 | Key passKey = EncFSCrypto.newKey(passKeyData);
40 |
41 | // Encrypt the volume key data
42 | Mac mac = encryptVolumeKeyData(passKey);
43 |
44 | // Calculate MAC for the key
45 | byte[] mac32 = EncFSCrypto.mac32(mac, volKeyData, new byte[0]);
46 | byte[] cipherVolKeyData = EncFSCrypto.encryptKeyData(volKeyData,
47 | passIvData, passKey, mac, mac32);
48 |
49 | // Combine MAC with key data
50 | byte[] result = new byte[mac32.length + cipherVolKeyData.length];
51 |
52 | System.arraycopy(mac32, 0, result, 0, mac32.length);
53 | System.arraycopy(cipherVolKeyData, 0, result, mac32.length,
54 | cipherVolKeyData.length);
55 |
56 | return result;
57 | }
58 |
59 | private static Mac encryptVolumeKeyData(Key passKey)
60 | throws EncFSUnsupportedException, EncFSInvalidConfigException {
61 | Mac mac;
62 | try {
63 | mac = EncFSCrypto.newMac(passKey);
64 | } catch (InvalidKeyException e) {
65 | throw new EncFSInvalidConfigException(e);
66 | }
67 | return mac;
68 | }
69 |
70 | // Derive volume key for the given config and password-based key/IV data
71 | protected static byte[] decryptVolumeKey(EncFSConfig config,
72 | byte[] pbkdf2Data) throws EncFSChecksumException,
73 | EncFSInvalidConfigException, EncFSCorruptDataException,
74 | EncFSUnsupportedException {
75 | // Decode Base64 encoded ciphertext data
76 | // TODO: validate key/IV lengths
77 | byte[] cipherVolKeyData;
78 | try {
79 | cipherVolKeyData = EncFSBase64.decode(config
80 | .getBase64EncodedVolumeKey());
81 | } catch (IOException e) {
82 | throw new EncFSInvalidConfigException("Corrupt key data in config");
83 | }
84 |
85 | byte[] encryptedVolKey = Arrays.copyOfRange(cipherVolKeyData, 4,
86 | cipherVolKeyData.length);
87 |
88 | // Prepare key/IV for decryption
89 | int keySizeInBytes = config.getVolumeKeySizeInBits() / 8;
90 | byte[] passKeyData = Arrays.copyOfRange(pbkdf2Data, 0, keySizeInBytes);
91 | byte[] passIvData = Arrays.copyOfRange(pbkdf2Data, keySizeInBytes,
92 | keySizeInBytes + EncFSVolume.IV_LENGTH_IN_BYTES);
93 |
94 | Key passKey = EncFSCrypto.newKey(passKeyData);
95 | byte[] ivSeed = Arrays.copyOfRange(cipherVolKeyData, 0, 4);
96 |
97 | // Decrypt the volume key data
98 | Mac mac = encryptVolumeKeyData(passKey);
99 | byte[] clearVolKeyData = decryptVolumeKeyData(encryptedVolKey,
100 | passIvData, passKey, ivSeed, mac);
101 |
102 | // Perform checksum computation
103 | byte[] mac32 = EncFSCrypto.mac32(mac, clearVolKeyData, new byte[0]);
104 |
105 | if (!Arrays.equals(ivSeed, mac32)) {
106 | throw new EncFSChecksumException("Volume key checksum mismatch");
107 | }
108 |
109 | return clearVolKeyData;
110 | }
111 |
112 | // Decrypt volume key data
113 | private static byte[] decryptVolumeKeyData(byte[] encryptedVolKey,
114 | byte[] passIvData, Key passKey, byte[] ivSeed, Mac mac)
115 | throws EncFSUnsupportedException, EncFSInvalidConfigException,
116 | EncFSCorruptDataException {
117 | byte[] clearVolKeyData;
118 | try {
119 | clearVolKeyData = StreamCrypto.streamDecrypt(
120 | StreamCrypto.newStreamCipher(), mac, passKey, passIvData,
121 | ivSeed, encryptedVolKey);
122 | } catch (InvalidAlgorithmParameterException e) {
123 | throw new EncFSInvalidConfigException(e);
124 | } catch (IllegalBlockSizeException e) {
125 | throw new EncFSCorruptDataException(e);
126 | } catch (BadPaddingException e) {
127 | throw new EncFSCorruptDataException(e);
128 | }
129 | return clearVolKeyData;
130 | }
131 |
132 | // Derive password-based key from input/config parameters using PBKDF2
133 | protected static byte[] deriveKeyDataFromPassword(EncFSConfig config,
134 | String password, EncFSPBKDF2Provider pbkdf2Provider)
135 | throws EncFSInvalidConfigException, EncFSUnsupportedException {
136 | // Decode base 64 salt data
137 | byte[] cipherSaltData;
138 | try {
139 | cipherSaltData = EncFSBase64.decode(config.getBase64Salt());
140 | } catch (IOException e) {
141 | throw new EncFSInvalidConfigException("Corrupt salt data in config");
142 | }
143 |
144 | if (pbkdf2Provider == null) {
145 | // Execute PBKDF2 to derive key data from the password
146 | SecretKeyFactory f;
147 | try {
148 | f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
149 | } catch (NoSuchAlgorithmException e) {
150 | throw new EncFSUnsupportedException(e);
151 | }
152 | KeySpec ks = new PBEKeySpec(password.toCharArray(), cipherSaltData,
153 | config.getIterationForPasswordKeyDerivationCount(),
154 | config.getVolumeKeySizeInBits()
155 | + EncFSVolume.IV_LENGTH_IN_BYTES * 8);
156 | SecretKey pbkdf2Key;
157 | try {
158 | pbkdf2Key = f.generateSecret(ks);
159 | } catch (InvalidKeySpecException e) {
160 | throw new EncFSInvalidConfigException(e);
161 | }
162 |
163 | return pbkdf2Key.getEncoded();
164 | } else {
165 | return pbkdf2Provider.doPBKDF2(password, cipherSaltData.length,
166 | cipherSaltData,
167 | config.getIterationForPasswordKeyDerivationCount(),
168 | (config.getVolumeKeySizeInBits() / 8)
169 | + EncFSVolume.IV_LENGTH_IN_BYTES);
170 | }
171 | }
172 |
173 | // Encodes the given volume key using the supplied password parameters
174 | protected static void encodeVolumeKey(EncFSConfig config, String password,
175 | byte[] volKey, EncFSPBKDF2Provider pbkdf2Provider)
176 | throws EncFSInvalidConfigException, EncFSUnsupportedException,
177 | EncFSCorruptDataException {
178 | SecureRandom random = new SecureRandom();
179 | config.setSaltLengthBytes(20);
180 |
181 | // Generate random salt
182 | byte[] salt = new byte[20];
183 | random.nextBytes(salt);
184 | config.setBase64Salt(EncFSBase64.encodeBytes(salt));
185 |
186 | // Get password key data
187 | byte[] pbkdf2Data = deriveKeyDataFromPassword(config, password,
188 | pbkdf2Provider);
189 |
190 | // Encode volume key
191 | byte[] encodedVolKey = encryptVolumeKey(config, pbkdf2Data, volKey);
192 |
193 | config.setEncodedKeyLengthInBytes(encodedVolKey.length);
194 | config.setBase64EncodedVolumeKey(EncFSBase64.encodeBytes(encodedVolKey));
195 | }
196 | }
197 |
--------------------------------------------------------------------------------
/src/main/resources/org/mrpdaemon/sec/encfs/library.properties:
--------------------------------------------------------------------------------
1 | library.version=${pom.version}
2 |
--------------------------------------------------------------------------------
/src/test/java/org/mrpdaemon/sec/encfs/tests/EncFSBase64Test.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs.tests;
17 |
18 | import org.junit.Assert;
19 | import org.junit.Test;
20 | import org.mrpdaemon.sec.encfs.*;
21 |
22 | import javax.crypto.BadPaddingException;
23 | import javax.crypto.IllegalBlockSizeException;
24 | import java.io.IOException;
25 | import java.security.InvalidAlgorithmParameterException;
26 |
27 | public class EncFSBase64Test {
28 |
29 | @Test
30 | public void testDecodeEncodeEncfs() throws EncFSInvalidPasswordException,
31 | EncFSInvalidConfigException, EncFSCorruptDataException,
32 | EncFSUnsupportedException, EncFSChecksumException, IOException,
33 | InvalidAlgorithmParameterException, IllegalBlockSizeException,
34 | BadPaddingException {
35 |
36 | byte[] in = new byte[] { 87, 51, 103, 76, 111, 85, 113, 76, 45, 48, 89,
37 | 122, 85, 104, 56, 117, 100, 80, 56 };
38 | byte[] out = new byte[] { 98, -63, 94, 52, 104, 95, -127, 64, -2, 96,
39 | -85, -24, -23, -90 };
40 |
41 | byte[] out1 = EncFSBase64.decodeEncfs(in);
42 | Assert.assertArrayEquals(out, out1);
43 |
44 | byte[] in1 = EncFSBase64.encodeEncfs(out);
45 |
46 | Assert.assertArrayEquals(in, in1);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/test/java/org/mrpdaemon/sec/encfs/tests/EncFSComparer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs.tests;
17 |
18 | import org.mrpdaemon.sec.encfs.*;
19 | import org.slf4j.Logger;
20 | import org.slf4j.LoggerFactory;
21 |
22 | import java.io.*;
23 | import java.util.Arrays;
24 | import java.util.Comparator;
25 |
26 | /**
27 | * Simple tool that takes a raw encfs volume (& uses encfs-java to unencrypt it)
28 | * and compares it to a the same mounted encfs volume to check they are the
29 | * same.
30 | */
31 | public class EncFSComparer {
32 | private static final Logger logger = LoggerFactory
33 | .getLogger(EncFSComparer.class);
34 |
35 | public static void main(String[] args) throws Exception {
36 | if (args == null || args.length != 3)
37 | throw new IllegalArgumentException("Missing required args");
38 |
39 | File rawEncFSVolume = new File(args[0]);
40 | String password = args[1];
41 | File decodedEncFSOutput = new File(args[2]);
42 |
43 | EncFSComparer encFSComparer = new EncFSComparer(rawEncFSVolume,
44 | password, decodedEncFSOutput);
45 | int result = encFSComparer.compare();
46 | System.exit(result);
47 | }
48 |
49 | private final File rawEncFSVolume;
50 | private final String password;
51 | private final File decodedEncFSOutput;
52 |
53 | private EncFSComparer(File rawEncFSVolume, String password,
54 | File decodedEncFSOutput) {
55 | this.rawEncFSVolume = rawEncFSVolume;
56 | this.password = password;
57 | this.decodedEncFSOutput = decodedEncFSOutput;
58 | }
59 |
60 | private int compare() throws EncFSInvalidPasswordException,
61 | EncFSInvalidConfigException, EncFSCorruptDataException,
62 | EncFSUnsupportedException, EncFSChecksumException, IOException {
63 | logger.info(
64 | "Performing compare between encfs raw volume at {} and output files at {}",
65 | rawEncFSVolume, decodedEncFSOutput);
66 |
67 | EncFSVolume volume = new EncFSVolumeBuilder()
68 | .withRootPath(rawEncFSVolume.getAbsolutePath())
69 | .withPassword(password).buildVolume();
70 | EncFSFile rootDir = volume.getRootDir();
71 | int result = compare(rootDir, decodedEncFSOutput);
72 |
73 | if (result == 0) {
74 | logger.info("All files / folders match");
75 | } else {
76 | logger.info("Errors between files / folders found");
77 | }
78 |
79 | return result;
80 | }
81 |
82 | private int compare(EncFSFile encFsDir, File decodedFsDir)
83 | throws EncFSUnsupportedException, IOException,
84 | EncFSCorruptDataException {
85 | logger.info("Comparing directory {}", decodedFsDir.getAbsoluteFile());
86 |
87 | EncFSFile[] encFsFiles = encFsDir.listFiles();
88 | File[] decodedFsFiles = decodedFsDir.listFiles();
89 |
90 | Arrays.sort(encFsFiles, SimpleEncFSFileComparator.getInstance());
91 | Arrays.sort(decodedFsFiles, SimpleFileComparator.getInstance());
92 |
93 | if (encFsFiles.length != decodedFsFiles.length) {
94 | logger.error("File count miss match in directory {}",
95 | decodedFsDir.getAbsoluteFile());
96 | return -1;
97 | } else {
98 | for (int i = 0; i < encFsFiles.length; i++) {
99 | EncFSFile encFsFile = encFsFiles[i];
100 | File decodedFsFile = decodedFsFiles[i];
101 |
102 | if (!encFsFile.getName().equals(decodedFsFile.getName())) {
103 | logger.error("File name miss match ({}, {}, {})",
104 | new Object[] { i, encFsFile.getName(),
105 | decodedFsFile.getName() });
106 | return -1;
107 | }
108 |
109 | String reEncEncfsName = EncFSCrypto.encodeName(
110 | encFsFile.getVolume(), encFsFile.getName(),
111 | encFsFile.getParentPath());
112 | String rawFileName = encFsFile.getEncrytedName();
113 | if (!rawFileName.equals(reEncEncfsName)) {
114 | logger.error("Re-encoded name miss match ({}, {}, {}, {})",
115 | new Object[] { i, encFsFile.getName(), rawFileName,
116 | reEncEncfsName });
117 | return -1;
118 | }
119 |
120 | if (encFsFile.getLastModified() != decodedFsFile.lastModified()) {
121 | logger.error("File {} lastModified miss match",
122 | decodedFsFile.getName());
123 | return -1;
124 | }
125 |
126 | if (encFsFile.getLength() != decodedFsFile.length()) {
127 | logger.error(
128 | "File {} size miss match ({}, {})",
129 | new Object[] { decodedFsFile.getName(),
130 | encFsFile.getLength(),
131 | decodedFsFile.length() });
132 | return -1;
133 | }
134 |
135 | if (decodedFsFile.isDirectory()) {
136 | int subResult = compare(encFsFile, decodedFsFile);
137 | if (subResult != 0) {
138 | return subResult;
139 | }
140 | } else {
141 | // Check that the EncFSFileInputStream reads the file the
142 | // same as
143 | // reading the file directly from the mounted encfs volume
144 |
145 | EncFSFileInputStream encfsIs = new EncFSFileInputStream(
146 | encFsFile);
147 | try {
148 | BufferedInputStream decFsIs = new BufferedInputStream(
149 | new FileInputStream(decodedFsFile));
150 | String decodedFsFileName = decodedFsFile
151 | .getAbsoluteFile().getName();
152 | try {
153 | int streamresult = compareInputStreams(encfsIs,
154 | decFsIs, decodedFsFileName);
155 | if (streamresult != 0) {
156 | return streamresult;
157 | }
158 | } finally {
159 | decFsIs.close();
160 | }
161 | } finally {
162 | encfsIs.close();
163 | }
164 |
165 | // Copy the file via input/output streams & then check that
166 | // the file is the same
167 | File t = File.createTempFile(this.getClass().getName(),
168 | ".tmp");
169 | try {
170 | EncFSUtil.copyWholeStreamAndClose(
171 | new EncFSFileInputStream(encFsFile),
172 | new EncFSOutputStream(encFsDir.getVolume(),
173 | new BufferedOutputStream(
174 | new FileOutputStream(t)),
175 | encFsFile.getPath()));
176 |
177 | FileInputStream reEncFSIs = new FileInputStream(t);
178 | try {
179 | InputStream origEncFSIs = encFsFile
180 | .getVolume()
181 | .getFileProvider()
182 | .openInputStream(
183 | encFsFile.getEncryptedPath());
184 | try {
185 | int streamresult = compareInputStreams(
186 | origEncFSIs, reEncFSIs,
187 | encFsFile.getPath());
188 | if (streamresult != 0) {
189 | return streamresult;
190 | }
191 | } finally {
192 | origEncFSIs.close();
193 | }
194 | } finally {
195 | reEncFSIs.close();
196 | }
197 |
198 | } finally {
199 | if (t.exists()) {
200 | t.delete();
201 | }
202 | }
203 | }
204 | }
205 | }
206 |
207 | return 0;
208 | }
209 |
210 | private int compareInputStreams(InputStream encfsIs, InputStream decFsIs,
211 | String decodedFsFileName) throws IOException {
212 | int bytesRead = 0;
213 | int bytesRead2;
214 | while (bytesRead >= 0) {
215 | byte[] readBuf = new byte[128];
216 | byte[] readBuf2 = new byte[128];
217 |
218 | bytesRead = encfsIs.read(readBuf);
219 | bytesRead2 = decFsIs.read(readBuf2);
220 |
221 | if (bytesRead != bytesRead2) {
222 | logger.error(
223 | "File bytes read missmatch {} ({}, {})",
224 | new Object[] { decodedFsFileName, bytesRead, bytesRead2 });
225 | return -1;
226 | }
227 |
228 | if (!Arrays.equals(readBuf, readBuf2)) {
229 | logger.error("File bytes missmatch {}", decodedFsFileName);
230 | return -1;
231 | }
232 | }
233 | return 0;
234 | }
235 |
236 | private static class SimpleEncFSFileComparator implements
237 | Comparator {
238 | private static final SimpleEncFSFileComparator instance = new SimpleEncFSFileComparator();
239 |
240 | public static SimpleEncFSFileComparator getInstance() {
241 | return instance;
242 | }
243 |
244 | public int compare(EncFSFile arg0, EncFSFile arg1) {
245 | if (arg0.isDirectory() != arg1.isDirectory()) {
246 | if (arg0.isDirectory()) {
247 | return -1;
248 | } else {
249 | return 1;
250 | }
251 | } else {
252 | return arg0.getName().compareTo(arg1.getName());
253 | }
254 | }
255 | }
256 |
257 | private static class SimpleFileComparator implements Comparator {
258 | private static final SimpleFileComparator instance = new SimpleFileComparator();
259 |
260 | public static SimpleFileComparator getInstance() {
261 | return instance;
262 | }
263 |
264 | public int compare(File arg0, File arg1) {
265 | if (arg0.isDirectory() != arg1.isDirectory()) {
266 | if (arg0.isDirectory()) {
267 | return -1;
268 | } else {
269 | return 1;
270 | }
271 | } else {
272 | return arg0.getName().compareTo(arg1.getName());
273 | }
274 | }
275 | }
276 | }
277 |
--------------------------------------------------------------------------------
/src/test/java/org/mrpdaemon/sec/encfs/tests/EncFSCryptoTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs.tests;
17 |
18 | import org.junit.Assert;
19 | import org.junit.Test;
20 | import org.mrpdaemon.sec.encfs.EncFSVolume;
21 | import org.mrpdaemon.sec.encfs.EncFSVolumeBuilder;
22 | import org.mrpdaemon.sec.encfs.StreamCrypto;
23 |
24 | import java.io.File;
25 | import java.util.Arrays;
26 |
27 | public class EncFSCryptoTest {
28 | private final static String password = "test";
29 | private final static String pathname = "test/encfs_samples/boxcryptor_1";
30 |
31 | @Test
32 | public void testStreamEncodeDecode() throws Exception {
33 | EncFSVolume volume = getEncFSVolume();
34 | byte[] orig = new byte[] { 116, 101, 115, 116, 102, 105, 108, 101, 46,
35 | 116, 120, 116 };
36 | byte[] ivSeed = new byte[] { 0, 0, 0, 0, 0, 0, 98, -63 };
37 |
38 | byte[] b1 = StreamCrypto.streamEncrypt(volume, ivSeed,
39 | Arrays.copyOf(orig, orig.length));
40 | byte[] b2 = StreamCrypto.streamDecrypt(volume, ivSeed,
41 | Arrays.copyOf(b1, b1.length));
42 |
43 | Assert.assertArrayEquals(orig, b2);
44 | }
45 |
46 | @Test
47 | public void testStreamEncodeDecode2() throws Exception {
48 | EncFSVolume volume = getEncFSVolume();
49 | byte[] orig = "test file\r".getBytes();
50 | byte[] ivSeed = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
51 |
52 | byte[] b1 = StreamCrypto.streamEncrypt(volume, ivSeed,
53 | Arrays.copyOf(orig, orig.length));
54 | byte[] b2 = StreamCrypto.streamDecrypt(volume, ivSeed,
55 | Arrays.copyOf(b1, b1.length));
56 |
57 | Assert.assertArrayEquals(orig, b2);
58 | }
59 |
60 | private static EncFSVolume getEncFSVolume() throws Exception {
61 | File encFSDir = assertExistingPath(EncFSCryptoTest.pathname);
62 | return new EncFSVolumeBuilder()
63 | .withRootPath(encFSDir.getAbsolutePath())
64 | .withPassword(EncFSCryptoTest.password).buildVolume();
65 | }
66 |
67 | private static File assertExistingPath(String pathname) {
68 | File encFSDir = new File(pathname);
69 | Assert.assertTrue(encFSDir.exists());
70 | return encFSDir;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/test/java/org/mrpdaemon/sec/encfs/tests/EncFSFilenameEncryptionAlgorithmTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2013 encfs-java authors
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 | package org.mrpdaemon.sec.encfs.tests;
16 |
17 | import org.junit.Test;
18 |
19 | import org.mrpdaemon.sec.encfs.EncFSFilenameEncryptionAlgorithm;
20 |
21 | public class EncFSFilenameEncryptionAlgorithmTest {
22 | @Test(expected = IllegalArgumentException.class)
23 | public void testParse() throws Exception {
24 | EncFSFilenameEncryptionAlgorithm.parse("nameio/sstream");
25 | }
26 | }
--------------------------------------------------------------------------------
/src/test/java/org/mrpdaemon/sec/encfs/tests/EncFSUtilTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * EncFS Java Library
3 | * Copyright (C) 2011
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Lesser General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Lesser General Public License for more details.
14 | */
15 |
16 | package org.mrpdaemon.sec.encfs.tests;
17 |
18 | import org.junit.Assert;
19 | import org.junit.Test;
20 | import org.mrpdaemon.sec.encfs.EncFSUtil;
21 |
22 | import java.nio.ByteBuffer;
23 | import java.util.Random;
24 |
25 | public class EncFSUtilTest {
26 | @Test
27 | public void testInt_99() {
28 | int testInt = 99;
29 | ByteBuffer b = ByteBuffer.allocate(Integer.SIZE / 8).putInt(testInt);
30 |
31 | Assert.assertArrayEquals(b.array(),
32 | EncFSUtil.convertIntToByteArrayBigEndian(testInt));
33 | Assert.assertEquals(testInt,
34 | EncFSUtil.convertBigEndianByteArrayToInt(b.array()));
35 | }
36 |
37 | @Test
38 | public void testLong_1198() {
39 | long testLong = 1198;
40 | ByteBuffer b = ByteBuffer.allocate(Long.SIZE / 8).putLong(testLong);
41 |
42 | Assert.assertArrayEquals(b.array(),
43 | EncFSUtil.convertLongToByteArrayBigEndian(testLong));
44 | Assert.assertEquals(testLong,
45 | EncFSUtil.convertByteArrayToLong(b.array()));
46 | }
47 |
48 | @Test
49 | public void testRandomIntToBytesAndBack() {
50 | Random random = new Random();
51 | for (int i = 0; i < 100; i++) {
52 | int iIn = random.nextInt();
53 |
54 | int iOut1 = toBytesAndBack(iIn);
55 | int iOut2 = toBytesAndBack(-1 * iIn);
56 |
57 | Assert.assertEquals(iIn, iOut1);
58 | Assert.assertEquals(-1 * iIn, iOut2);
59 | }
60 | }
61 |
62 | @Test
63 | public void testRandomLongToBytesAndBack() {
64 | Random random = new Random();
65 | for (int i = 0; i < 100; i++) {
66 | long lIn = random.nextLong();
67 |
68 | long lOut1 = toBytesAndBack(lIn);
69 | long lOut2 = toBytesAndBack(-1 * lIn);
70 |
71 | Assert.assertEquals(lIn, lOut1);
72 | Assert.assertEquals(-1 * lIn, lOut2);
73 | }
74 | }
75 |
76 | private long toBytesAndBack(long lIn) {
77 | byte[] b = EncFSUtil.convertLongToByteArrayBigEndian(lIn);
78 | return EncFSUtil.convertByteArrayToLong(b);
79 | }
80 |
81 | private int toBytesAndBack(int iIn) {
82 | byte[] b = EncFSUtil.convertIntToByteArrayBigEndian(iIn);
83 | return EncFSUtil.convertBigEndianByteArrayToInt(b);
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/src/test/java/org/mrpdaemon/sec/encfs/tests/EncFSVolumeFileTest.java:
--------------------------------------------------------------------------------
1 | package org.mrpdaemon.sec.encfs.tests;
2 |
3 | import org.junit.After;
4 | import org.junit.Before;
5 | import org.mrpdaemon.sec.encfs.EncFSLocalFileProvider;
6 |
7 | import java.io.File;
8 |
9 | public class EncFSVolumeFileTest extends EncFSVolumeTest {
10 |
11 | private File tempDir;
12 |
13 | @Before
14 | public void setUp() throws Exception {
15 | tempDir = EncFSVolumeTestCommon.createTempDir();
16 | EncFSLocalFileProvider fileProvider = new EncFSLocalFileProvider(
17 | tempDir);
18 | setFileProvider(fileProvider);
19 | }
20 |
21 | private void recursiveDelete(File file) {
22 | if (file.isDirectory()) {
23 | for (File subFile : file.listFiles()) {
24 | recursiveDelete(subFile);
25 | }
26 | } else {
27 | file.delete();
28 | }
29 | }
30 |
31 | @After
32 | public void tearDown() throws Exception {
33 | recursiveDelete(tempDir);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/test/java/org/mrpdaemon/sec/encfs/tests/EncFSVolumeTest.java:
--------------------------------------------------------------------------------
1 | package org.mrpdaemon.sec.encfs.tests;
2 |
3 | import junit.framework.Assert;
4 | import org.junit.Test;
5 | import org.mrpdaemon.sec.encfs.*;
6 |
7 | public abstract class EncFSVolumeTest {
8 | private EncFSFileProvider fileProvider;
9 |
10 | void setFileProvider(EncFSFileProvider encFSFileProvider) {
11 | this.fileProvider = encFSFileProvider;
12 | }
13 |
14 | EncFSFileProvider getFileProvider() {
15 | return fileProvider;
16 | }
17 |
18 | @Test
19 | public void testNoExistingConfigFile() throws Exception {
20 | try {
21 | new EncFSVolumeBuilder().withFileProvider(fileProvider)
22 | .withDerivedKeyData(new byte[] {});
23 | } catch (EncFSInvalidConfigException e) {
24 | Assert.assertEquals("No EncFS configuration file found",
25 | e.getMessage());
26 | }
27 | }
28 |
29 | @Test
30 | public void testVolumeCreation() throws Exception {
31 | EncFSConfig config = EncFSConfigFactory.createDefault();
32 |
33 | EncFSVolume volume = EncFSVolumeTestCommon.createVolume(config,
34 | fileProvider);
35 | Assert.assertNotNull(volume);
36 | Assert.assertEquals(1,
37 | fileProvider.listFiles(fileProvider.getFilesystemRootPath())
38 | .size());
39 | Assert.assertTrue(fileProvider.exists(fileProvider
40 | .getFilesystemRootPath() + ".encfs6.xml"));
41 | }
42 |
43 | @Test
44 | public void testDefaultVolume() throws Exception {
45 | EncFSConfig config = EncFSConfigFactory.createDefault();
46 |
47 | testFileOperations(config);
48 | }
49 |
50 | @Test
51 | public void testNoUniqueIV() throws Exception {
52 | EncFSConfig config = EncFSConfigFactory.createDefault();
53 | config.setUseUniqueIV(false);
54 |
55 | testFileOperations(config);
56 | }
57 |
58 | @Test
59 | public void testNoChainedIV() throws Exception {
60 | EncFSConfig config = EncFSConfigFactory.createDefault();
61 | config.setChainedNameIV(false);
62 |
63 | testFileOperations(config);
64 | }
65 |
66 | @Test
67 | public void testNoUniqueOrChainedIV() throws Exception {
68 | EncFSConfig config = EncFSConfigFactory.createDefault();
69 | config.setChainedNameIV(false);
70 | config.setUseUniqueIV(false);
71 |
72 | testFileOperations(config);
73 | }
74 |
75 | @Test
76 | public void testNoHolesWithZeroBlockPassThrough() throws Exception {
77 | EncFSConfig config = EncFSConfigFactory.createDefault();
78 | config.setHolesAllowedInFiles(false);
79 |
80 | testFileOperations(config);
81 | }
82 |
83 | @Test
84 | public void test256BitKey() throws Exception {
85 | EncFSConfig config = EncFSConfigFactory.createDefault();
86 | config.setVolumeKeySizeInBits(256);
87 |
88 | testFileOperations(config);
89 | }
90 |
91 | @Test
92 | public void test128BitKey() throws Exception {
93 | EncFSConfig config = EncFSConfigFactory.createDefault();
94 | config.setVolumeKeySizeInBits(128);
95 |
96 | testFileOperations(config);
97 | }
98 |
99 | @Test
100 | public void test4096ByteBlocks() throws Exception {
101 | EncFSConfig config = EncFSConfigFactory.createDefault();
102 | config.setEncryptedFileBlockSizeInBytes(4096);
103 |
104 | testFileOperations(config);
105 | }
106 |
107 | @Test
108 | public void testStreamNameAlg() throws Exception {
109 | EncFSConfig config = EncFSConfigFactory.createDefault();
110 | config.setFilenameAlgorithm(EncFSFilenameEncryptionAlgorithm.STREAM);
111 |
112 | testFileOperations(config);
113 | }
114 |
115 | @Test
116 | public void testBlockMAC() throws Exception {
117 | EncFSConfig config = EncFSConfigFactory.createDefault();
118 | config.setNumberOfMACBytesForEachFileBlock(8);
119 |
120 | testFileOperations(config);
121 | }
122 |
123 | @Test
124 | public void testBlockMACWithRandBytes() throws Exception {
125 | EncFSConfig config = EncFSConfigFactory.createDefault();
126 | config.setNumberOfMACBytesForEachFileBlock(8);
127 | config.setNumberOfRandomBytesInEachMACHeader(8);
128 |
129 | testFileOperations(config);
130 | }
131 |
132 | private void testFileOperations(EncFSConfig config) throws Exception {
133 | EncFSVolume volume = EncFSVolumeTestCommon.createVolume(config,
134 | fileProvider);
135 | EncFSVolumeTestCommon.testFileOperations(volume);
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/test/java/org/mrpdaemon/sec/encfs/tests/EncFSVolumeTestCommon.java:
--------------------------------------------------------------------------------
1 | package org.mrpdaemon.sec.encfs.tests;
2 |
3 | import junit.framework.Assert;
4 | import org.mrpdaemon.sec.encfs.*;
5 |
6 | import java.io.File;
7 | import java.io.FileNotFoundException;
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.util.*;
11 |
12 | class EncFSVolumeTestCommon {
13 | private final static String password = "testPassword";
14 |
15 | public static File createTempDir() throws IOException {
16 | File temp;
17 |
18 | temp = File.createTempFile("encfs-java-tmp",
19 | Long.toString(System.nanoTime()));
20 | if (!temp.delete()) {
21 | throw new IOException("Could not delete temporary file "
22 | + temp.getAbsolutePath());
23 | }
24 |
25 | if (!temp.mkdir()) {
26 | throw new IOException("Could not create temporary directory");
27 | }
28 |
29 | return temp;
30 | }
31 |
32 | public static EncFSVolume createVolume(EncFSConfig config,
33 | EncFSFileProvider fileProvider) throws Exception {
34 | try {
35 | new EncFSVolumeBuilder().withFileProvider(fileProvider)
36 | .withConfig(config).withPassword(password)
37 | .writeVolumeConfig();
38 | // EncFSVolume.createVolume(fileProvider, config, password);
39 | return new EncFSVolumeBuilder().withFileProvider(fileProvider)
40 | .withConfig(config).withPassword(password).buildVolume();
41 | } catch (Exception e) {
42 | Assert.fail(e.getMessage());
43 | throw e;
44 | }
45 | }
46 |
47 | private static class EncFSFileInfoComparator implements
48 | Comparator {
49 | @Override
50 | public int compare(EncFSFileInfo info1, EncFSFileInfo info2) {
51 | return info1.getName().compareTo(info2.getName());
52 | }
53 | }
54 |
55 | private static class EncFSFileComparator implements Comparator {
56 | @Override
57 | public int compare(EncFSFile file1, EncFSFile file2) {
58 | return file1.getName().compareTo(file2.getName());
59 | }
60 | }
61 |
62 | public static void testFileOperations(EncFSVolume volume)
63 | throws EncFSCorruptDataException, EncFSUnsupportedException,
64 | IOException {
65 | // Create a file
66 | Assert.assertFalse(volume.pathExists("/test.txt"));
67 | Assert.assertEquals(0,
68 | volume.listFilesForPath(EncFSVolume.ROOT_PATH).length);
69 | EncFSFile outFile = volume.createFile("/test.txt");
70 | EncFSOutputStream os = outFile.openOutputStream(11);
71 | try {
72 | os.write("hello\nworld".getBytes());
73 | } finally {
74 | os.close();
75 | }
76 |
77 | // Check the file got created
78 | Assert.assertEquals(1,
79 | volume.listFilesForPath(EncFSVolume.ROOT_PATH).length);
80 | Assert.assertEquals(
81 | 2,
82 | volume.getFileProvider()
83 | .listFiles(
84 | volume.getFileProvider()
85 | .getFilesystemRootPath()).size()); // 1
86 | // for
87 | // the
88 | // config
89 | // file & 1
90 | // data file
91 | EncFSFile encFsFile = volume.getFile("/test.txt");
92 | Assert.assertNotNull(encFsFile);
93 | Assert.assertEquals("test.txt", encFsFile.getName());
94 | Assert.assertEquals("/test.txt", encFsFile.getPath());
95 | Assert.assertTrue(encFsFile.getLength() > 0);
96 | long contentsLength = encFsFile.getLength();
97 |
98 | // Check that it's name is encrypted
99 | List fileList = volume.getFileProvider().listFiles(
100 | volume.getFileProvider().getFilesystemRootPath());
101 | Collections.sort(fileList, new EncFSFileInfoComparator());
102 | if (fileList.get(0).getName().equals(EncFSVolume.CONFIG_FILE_NAME)) {
103 | Assert.assertFalse(fileList.get(1).getName().equals("test.txt"));
104 | } else {
105 | Assert.assertEquals(EncFSVolume.CONFIG_FILE_NAME, fileList.get(1)
106 | .getName());
107 | Assert.assertFalse(fileList.get(1).getName().equals("test.txt"));
108 | }
109 |
110 | String encFileName = fileList.get(1).getName();
111 |
112 | // Now rename / move the file
113 | boolean moveResult = volume.movePath(encFsFile.getPath(), "/test2.txt");
114 | Assert.assertTrue(moveResult);
115 |
116 | // Check that the file name has changed
117 | List fileList2 = volume.getFileProvider().listFiles(
118 | volume.getFileProvider().getFilesystemRootPath());
119 | Collections.sort(fileList2, new EncFSFileInfoComparator());
120 | if (fileList2.get(0).getName().equals(EncFSVolume.CONFIG_FILE_NAME)) {
121 | // File at index 1 must have changed
122 | Assert.assertFalse(fileList2.get(1).getName().equals("test.txt"));
123 | Assert.assertFalse(fileList2.get(1).getName().equals(encFileName));
124 | } else {
125 | Assert.assertEquals(EncFSVolume.CONFIG_FILE_NAME, fileList2.get(1)
126 | .getName());
127 | // File at index 0 must have changed
128 | Assert.assertFalse(fileList2.get(0).getName().equals("test.txt"));
129 | Assert.assertFalse(fileList2.get(0).getName().equals(encFileName));
130 | }
131 |
132 | // Try re-moving the original file (should fail as we just moved it)
133 | try {
134 | boolean moveResult2 = volume.movePath(encFsFile.getPath(),
135 | "/test3.txt");
136 | Assert.assertFalse(moveResult2);
137 | } catch (FileNotFoundException e) {
138 | // Some file providers throw exceptions instead of returning false
139 | }
140 |
141 | // now get the proper file (that we moved the orig to)
142 | encFsFile = volume.getFile("/test2.txt");
143 | Assert.assertEquals("test2.txt", encFsFile.getName());
144 | Assert.assertEquals("/test2.txt", encFsFile.getPath());
145 |
146 | // Try moving to a non-existant directory
147 | try {
148 | boolean moveResult3 = volume.movePath(encFsFile.getPath(),
149 | "/dir1/t.txt");
150 | Assert.assertFalse(moveResult3);
151 | } catch (FileNotFoundException e) {
152 | // Some file providers throw exceptions instead of returning false
153 | }
154 |
155 | // Make dir1
156 | boolean mkdirResult = volume.makeDir("/dir1");
157 | Assert.assertTrue(mkdirResult);
158 |
159 | // Check the dir got created
160 | ArrayList volumeFileList = new ArrayList(
161 | Arrays.asList(volume.listFilesForPath(EncFSVolume.ROOT_PATH)));
162 | Collections.sort(volumeFileList, new EncFSFileComparator());
163 | Assert.assertEquals(2, volumeFileList.size());
164 | Assert.assertEquals(true, volumeFileList.get(0).isDirectory());
165 | Assert.assertEquals(false, volumeFileList.get(1).isDirectory());
166 |
167 | // Try to make the same dir again (it should fail)
168 | try {
169 | boolean mkdirResult2 = volume.makeDir("/dir1");
170 | Assert.assertFalse(mkdirResult2);
171 | } catch (FileNotFoundException e) {
172 | // Some file providers throw exceptions instead of returning false
173 | }
174 |
175 | // Try to make a dir where the parent doesn't exist (it should fail)
176 | try {
177 | boolean mkdirResult3 = volume.makeDir("/dir2/def");
178 | Assert.assertFalse(mkdirResult3);
179 | } catch (FileNotFoundException e) {
180 | // Some file providers throw exceptions instead of returning false
181 | }
182 |
183 | // Move the file we created in to this sub directory
184 | boolean moveToDirResult = volume.movePath(encFsFile.getPath(),
185 | "/dir1/test.txt");
186 | Assert.assertTrue(moveToDirResult);
187 | encFsFile = volume.getFile("/dir1/test.txt");
188 | Assert.assertEquals("test.txt", encFsFile.getName());
189 | Assert.assertEquals("/dir1/test.txt", encFsFile.getPath());
190 | Assert.assertEquals(contentsLength, encFsFile.getLength());
191 |
192 | // Check the file was moved
193 | volumeFileList = new ArrayList(Arrays.asList(volume
194 | .listFilesForPath(EncFSVolume.ROOT_PATH)));
195 | Collections.sort(volumeFileList, new EncFSFileComparator());
196 | Assert.assertEquals(1, volumeFileList.size());
197 | Assert.assertEquals("dir1", volumeFileList.get(0).getName());
198 | volumeFileList = new ArrayList(Arrays.asList(volume
199 | .listFilesForPath("/dir1")));
200 | Collections.sort(volumeFileList, new EncFSFileComparator());
201 | Assert.assertEquals(1, volumeFileList.size());
202 | Assert.assertEquals("test.txt", volumeFileList.get(0).getName());
203 |
204 | // Now do a copy to a new nested directory
205 | boolean mkdirsResult = volume.makeDirs("/dir2/dir3");
206 | Assert.assertTrue(mkdirsResult);
207 | boolean copyResult = volume.copyPath("/dir1/test.txt", "/dir2/dir3");
208 | Assert.assertTrue(copyResult);
209 | volumeFileList = new ArrayList(Arrays.asList(volume
210 | .listFilesForPath("/dir1")));
211 | Collections.sort(volumeFileList, new EncFSFileComparator());
212 | Assert.assertEquals("test.txt", volumeFileList.get(0).getName());
213 | volumeFileList = new ArrayList(Arrays.asList(volume
214 | .listFilesForPath("/dir2/dir3")));
215 | Collections.sort(volumeFileList, new EncFSFileComparator());
216 | Assert.assertEquals("test.txt", volumeFileList.get(0).getName());
217 | Assert.assertEquals(contentsLength, volume.getFile("/dir1/test.txt")
218 | .getLength());
219 | Assert.assertEquals(contentsLength,
220 | volume.getFile("/dir2/dir3/test.txt").getLength());
221 |
222 | // Try to recursively copy a directory
223 | boolean recursiveCopyResult = volume.copyPath("/dir1", "/dir2");
224 | Assert.assertTrue(recursiveCopyResult);
225 | recursiveCopyResult = volume.pathExists("/dir2/dir1");
226 | Assert.assertTrue(recursiveCopyResult);
227 | recursiveCopyResult = volume.pathExists("/dir2/dir1/test.txt");
228 | Assert.assertTrue(recursiveCopyResult);
229 | // Delete the recursively copied directory
230 | recursiveCopyResult = volume.deletePath("/dir2/dir1", true);
231 | Assert.assertTrue(recursiveCopyResult);
232 |
233 | // Delete the src file
234 | boolean deleteFileResult = volume.deletePath("/dir1/test.txt", false);
235 | Assert.assertTrue(deleteFileResult);
236 |
237 | // Check the file has been removed
238 | Assert.assertEquals(2,
239 | volume.listFilesForPath(EncFSVolume.ROOT_PATH).length);
240 | volumeFileList = new ArrayList(Arrays.asList(volume
241 | .listFilesForPath(EncFSVolume.ROOT_PATH)));
242 | Collections.sort(volumeFileList, new EncFSFileComparator());
243 | Assert.assertEquals("dir1", volumeFileList.get(0).getName());
244 | Assert.assertEquals("dir2", volumeFileList.get(1).getName());
245 | Assert.assertEquals(0, volume.listFilesForPath("/dir1").length);
246 | Assert.assertEquals(1, volume.listFilesForPath("/dir2").length);
247 | Assert.assertEquals(1, volume.listFilesForPath("/dir2/dir3").length);
248 | volumeFileList = new ArrayList(Arrays.asList(volume
249 | .listFilesForPath("/dir2/dir3")));
250 | Collections.sort(volumeFileList, new EncFSFileComparator());
251 | Assert.assertEquals("test.txt", volumeFileList.get(0).getName());
252 |
253 | // now delete the empty directory
254 | boolean deleteEmptyDirResult = volume.deletePath("/dir1", false);
255 | Assert.assertTrue(deleteEmptyDirResult);
256 |
257 | // recreate the directory
258 | mkdirResult = volume.makeDir("/dir1");
259 | Assert.assertTrue(mkdirResult);
260 |
261 | // Copy the file back under it
262 | copyResult = volume.copyPath("/dir2/dir3/test.txt", "/dir1");
263 | Assert.assertTrue(copyResult);
264 |
265 | // Create a few more directories to test recursive deletion
266 | mkdirsResult = volume.makeDirs("/dir1/dir4/dir5/dir6/dir7");
267 | Assert.assertTrue(mkdirsResult);
268 |
269 | // Attempt to recursively delete the directory - should succeed
270 | boolean deleteRecursiveResult = volume.deletePath("/dir1", true);
271 | Assert.assertTrue(deleteRecursiveResult);
272 |
273 | // Check the directory has been removed
274 | Assert.assertEquals(1,
275 | volume.listFilesForPath(EncFSVolume.ROOT_PATH).length);
276 | Assert.assertEquals("dir2",
277 | volume.listFilesForPath(EncFSVolume.ROOT_PATH)[0].getName());
278 | Assert.assertEquals(1, volume.listFilesForPath("/dir2").length);
279 | Assert.assertEquals(1, volume.listFilesForPath("/dir2/dir3").length);
280 | volumeFileList = new ArrayList(Arrays.asList(volume
281 | .listFilesForPath("/dir2/dir3")));
282 | Collections.sort(volumeFileList, new EncFSFileComparator());
283 | Assert.assertEquals("test.txt", volumeFileList.get(0).getName());
284 |
285 | // Read the contents of the file to check that it's been copied / moved
286 | // around OK
287 | InputStream is = volume.openInputStreamForPath("/dir2/dir3/test.txt");
288 | try {
289 | StringBuilder sb = new StringBuilder();
290 | int bytesRead = 0;
291 | while (bytesRead >= 0) {
292 | byte[] readBuf = new byte[128];
293 | bytesRead = is.read(readBuf);
294 | if (bytesRead > 0) {
295 | sb.append(new String(readBuf, 0, bytesRead));
296 | }
297 | }
298 |
299 | String readContents = sb.toString();
300 | Assert.assertEquals("hello\nworld", readContents);
301 | } finally {
302 | is.close();
303 | }
304 |
305 | }
306 | }
307 |
--------------------------------------------------------------------------------
/src/test/java/org/mrpdaemon/sec/encfs/tests/EncFSVolumeVFSTest.java:
--------------------------------------------------------------------------------
1 | package org.mrpdaemon.sec.encfs.tests;
2 |
3 | import org.junit.After;
4 | import org.junit.Before;
5 | import org.mrpdaemon.sec.encfs.tests.vfs.CommonsVFSRamFileProvider;
6 |
7 | public class EncFSVolumeVFSTest extends EncFSVolumeTest {
8 |
9 | @Before
10 | public void setUp() throws Exception {
11 | CommonsVFSRamFileProvider fileProvider = new CommonsVFSRamFileProvider();
12 | fileProvider.init();
13 | setFileProvider(fileProvider);
14 | }
15 |
16 | @After
17 | public void tearDown() throws Exception {
18 | ((CommonsVFSRamFileProvider) getFileProvider()).close();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/test/java/org/mrpdaemon/sec/encfs/tests/vfs/CommonsVFSFileProvider.java:
--------------------------------------------------------------------------------
1 | package org.mrpdaemon.sec.encfs.tests.vfs;
2 |
3 | import org.apache.commons.vfs2.*;
4 | import org.mrpdaemon.sec.encfs.EncFSFileInfo;
5 | import org.mrpdaemon.sec.encfs.EncFSFileProvider;
6 | import org.mrpdaemon.sec.encfs.EncFSVolume;
7 |
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.io.OutputStream;
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | public class CommonsVFSFileProvider implements EncFSFileProvider {
15 |
16 | private final String separator;
17 |
18 | final FileSystemManager fileSystemManager;
19 |
20 | CommonsVFSFileProvider(FileSystemManager fileSystemManager) {
21 | this.fileSystemManager = fileSystemManager;
22 | this.separator = FileName.SEPARATOR;
23 | }
24 |
25 | public final String getSeparator() {
26 | return separator;
27 | }
28 |
29 | public final String getFilesystemRootPath() {
30 | return FileName.ROOT_PATH;
31 | }
32 |
33 | public boolean move(String encOrigFileName, String encNewFileName)
34 | throws IOException {
35 | FileObject origFile = resolveFile(encOrigFileName);
36 | if (!origFile.exists())
37 | return false;
38 |
39 | FileObject newFile = resolveFile(encNewFileName);
40 | if (encNewFileName.lastIndexOf(separator) > 0) {
41 | if (!newFile.getParent().exists()) {
42 | return false;
43 | }
44 | }
45 | origFile.moveTo(newFile);
46 | return true;
47 | }
48 |
49 | private FileObject resolveFile(String encOrigFileName)
50 | throws FileSystemException {
51 | return fileSystemManager.resolveFile(fileSystemManager.getSchemes()[0]
52 | + ":" + encOrigFileName);
53 | }
54 |
55 | public boolean isDirectory(String encFileName) throws IOException {
56 | FileObject file = resolveFile(encFileName);
57 | return file.getType() == FileType.FOLDER;
58 | }
59 |
60 | public boolean delete(String encFileName) throws IOException {
61 | FileObject file = resolveFile(encFileName);
62 | return file.delete();
63 | }
64 |
65 | public boolean mkdir(String encDirName) throws IOException {
66 | FileObject file = resolveFile(encDirName);
67 | if (file.exists()) {
68 | return false;
69 | } else {
70 | if (encDirName.lastIndexOf(separator) != 0) {
71 | if (!file.getParent().exists()) {
72 | return false;
73 | }
74 | }
75 | file.createFolder();
76 | return true;
77 | }
78 | }
79 |
80 | public boolean mkdirs(String encDirName) throws IOException {
81 | String[] dirNameParts = encDirName.split(separator);
82 |
83 | String tmpDirName = "";
84 | for (String dirNamePart : dirNameParts) {
85 | if (!tmpDirName.endsWith(separator)) {
86 | tmpDirName += separator;
87 | }
88 | tmpDirName += dirNamePart;
89 |
90 | FileObject tmpDirFile = resolveFile(tmpDirName);
91 | boolean partResult = true;
92 | if (!tmpDirFile.exists()) {
93 | partResult = mkdir(tmpDirName);
94 | } else if (tmpDirFile.getType() == FileType.FILE) {
95 | partResult = false;
96 | }
97 |
98 | if (!partResult) {
99 | return false;
100 | }
101 | }
102 |
103 | return true;
104 | }
105 |
106 | public boolean copy(String encSrcFileName, String encTargetFileName)
107 | throws IOException {
108 | FileObject srcFile = resolveFile(encSrcFileName);
109 | FileObject targetFile = resolveFile(encTargetFileName);
110 |
111 | FileUtil.copyContent(srcFile, targetFile);
112 | return true;
113 | }
114 |
115 | public List listFiles(String encDirName) throws IOException {
116 | FileObject srcDir = resolveFile(encDirName);
117 | FileObject[] children = srcDir.getChildren();
118 |
119 | List result = new ArrayList(
120 | children.length);
121 | for (FileObject aChildren : children) {
122 | result.add(getFileInfo(aChildren));
123 | }
124 |
125 | return result;
126 | }
127 |
128 | public InputStream openInputStream(String encSrcFile) throws IOException {
129 | FileObject srcFile = resolveFile(encSrcFile);
130 | return srcFile.getContent().getInputStream();
131 | }
132 |
133 | public OutputStream openOutputStream(String encSrcFile, long outputLength)
134 | throws IOException {
135 | FileObject srcFile = resolveFile(encSrcFile);
136 | return srcFile.getContent().getOutputStream();
137 | }
138 |
139 | public EncFSFileInfo getFileInfo(String encSrcFile) throws IOException {
140 | FileObject srcFile = resolveFile(encSrcFile);
141 | return getFileInfo(srcFile);
142 | }
143 |
144 | public boolean exists(String encSrcFile) throws IOException {
145 | FileObject srcFile = resolveFile(encSrcFile);
146 | return srcFile.exists();
147 | }
148 |
149 | private EncFSFileInfo getFileInfo(FileObject fileObject) throws IOException {
150 | String name = fileObject.getName().getBaseName();
151 | String volumePath = fileObject.getName().getPath();
152 | volumePath = volumePath.substring(0,
153 | volumePath.length() - (name.length() + 1));
154 | if (volumePath.equals("")) {
155 | volumePath = EncFSVolume.ROOT_PATH;
156 | }
157 |
158 | boolean isDirectory = fileObject.getType() == FileType.FOLDER;
159 | long modified = fileObject.getContent().getLastModifiedTime();
160 | long size = (isDirectory ? 0 : fileObject.getContent().getSize());
161 | boolean canRead = fileObject.isReadable();
162 | boolean canWrite = fileObject.isWriteable();
163 | boolean canExecute = false;
164 |
165 | return new EncFSFileInfo(name, volumePath, isDirectory, modified, size,
166 | canRead, canWrite, canExecute);
167 | }
168 |
169 | public EncFSFileInfo createFile(String encTargetFile) throws IOException {
170 | if (exists(encTargetFile)) {
171 | throw new IOException("File already exists");
172 | }
173 |
174 | FileObject targetFile = resolveFile(encTargetFile);
175 | targetFile.createFile();
176 |
177 | return getFileInfo(targetFile);
178 | }
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/src/test/java/org/mrpdaemon/sec/encfs/tests/vfs/CommonsVFSRamFileProvider.java:
--------------------------------------------------------------------------------
1 | package org.mrpdaemon.sec.encfs.tests.vfs;
2 |
3 | import org.apache.commons.vfs2.FileSystemException;
4 | import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
5 | import org.apache.commons.vfs2.provider.ram.RamFileProvider;
6 |
7 | import java.io.IOException;
8 |
9 | public class CommonsVFSRamFileProvider extends CommonsVFSFileProvider {
10 |
11 | private DefaultFileSystemManager fileSystemManager;
12 |
13 | public CommonsVFSRamFileProvider() {
14 | super(createFileSystemManager());
15 | this.fileSystemManager = (DefaultFileSystemManager) super.fileSystemManager;
16 | }
17 |
18 | private static DefaultFileSystemManager createFileSystemManager() {
19 | RamFileProvider ramFileProvider = new RamFileProvider();
20 | DefaultFileSystemManager fileSystemManager = new DefaultFileSystemManager();
21 | // this.fileSystemManager.setLogger(log);
22 | try {
23 | fileSystemManager.addProvider("ram", ramFileProvider);
24 | fileSystemManager.setDefaultProvider(ramFileProvider);
25 | } catch (FileSystemException e) {
26 | throw new IllegalStateException(e);
27 | }
28 |
29 | return fileSystemManager;
30 | }
31 |
32 | public void init() throws IOException {
33 | fileSystemManager.init();
34 | }
35 |
36 | public void close() {
37 | fileSystemManager.close();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/test/encfs_samples/Samples.txt:
--------------------------------------------------------------------------------
1 | Volumes created via EncFS 1.7.4:
2 |
3 | testvol-default -- Default parameters (non-expert mode)
4 | Enter password: test
5 | / > ls
6 | longfile.txt
7 | test.txt
8 | zerofile.bin
9 | / > cat test.txt
10 | This is a test file.
11 |
12 | testvol-nouniqueiv -- Test volume without unique IV (no per-file IV header)
13 | Enter password: test
14 | / > ls
15 | longfile.txt
16 | testfile.txt
17 | / > cat testfile.txt
18 | Test file for non-unique-IV file.
19 |
20 | testvol-blockmac -- Test volume using block-level MAC to verify file contents
21 | Enter password: test
22 | / > ls
23 | longfile.txt
24 | / > cat longfile.txt
25 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
26 |
27 | testvol-streamname - Test volume for nameio/stream name algorithm
28 | Enter password: test
29 | / > ls
30 | dir/
31 | / > cd dir
32 | /dir > ls
33 | testfile.txt
34 | /dir > cat testfile.txt
35 | stream name algorithm
36 |
37 | testvol-extivchn - Test volume with external IV chaining (paranoia mode w/ encfs)
38 | Enter password: test
39 | / > ls
40 | directory/
41 | test.txt
42 | / > cat test.txt
43 | this is a test file with external IV chaining
44 | / > cd directory
45 | /directory > ls
46 | another-test-file.txt
47 | /directory > cat another-test-file.txt
48 | this is another test file with external IV chaining
49 |
50 | Volumes created via BoxCryptor:
51 |
52 | boxcryptor_1 -- A simple encfs sample with a single test file
53 | Enter password: test
54 | / > ls
55 | .encfs6.xml
56 | testfile.txt
57 | / > cat testfile.txt
58 | test file
59 |
60 | boxcryptor_2 -- Another sample with a different password & a nested folder
61 | Enter password: test2
62 | / > ls
63 | .encfs6.xml
64 | Dir1/
65 | file1.txt
66 | / > cat file1.txt
67 | Some contents for file
68 |
69 | boxcryptor_3 -- raw files contains a file that doens't belong to the encfs_volume (in this case desktop.ini from windows folder customisation)
70 | Enter password: test
71 | / > ls
72 | .encfs6.xml
73 | testFileAlpha.txt.txt
74 | / > cat testFileAlpha.txt.txt
75 | Contents for test fileAlpha.tx
76 |
77 | boxcryptor_null -- volume using nameio/null filename encoding
78 | Enter password: test
79 | / > ls
80 | testfile.txt
81 | / > cat testfile.txt
82 | Contents for test fileAlpha.txt
--------------------------------------------------------------------------------
/test/encfs_samples/boxcryptor_1/.encfs6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 20100713
6 | BoxCryptor 1.0.0.0
7 |
8 | ssl/aes
9 | 3
10 | 0
11 |
12 |
13 | nameio/stream
14 | 2
15 | 1
16 |
17 | 256
18 | 4096
19 | 0
20 | 0
21 | 0
22 | 0
23 | 0
24 | 1
25 | 52
26 | p8hapetrpqIyAxe/9mLE/nNGFFWugkLiTn1g+bAA1NMOwnD4YhcI6xc3ObQ8df1NoFVh8A==
27 | 20
28 | 106QqKPzGADnhiVHOYtgv0PbiUs=
29 | 5000
30 | 500
31 |
32 |
--------------------------------------------------------------------------------
/test/encfs_samples/boxcryptor_1/W3gLoUqL-0YzUh8udP8:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/boxcryptor_1/W3gLoUqL-0YzUh8udP8
--------------------------------------------------------------------------------
/test/encfs_samples/boxcryptor_2/.encfs6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 20100713
6 | BoxCryptor 1.0.0.0
7 |
8 | ssl/aes
9 | 3
10 | 0
11 |
12 |
13 | nameio/stream
14 | 2
15 | 1
16 |
17 | 256
18 | 4096
19 | 0
20 | 0
21 | 0
22 | 0
23 | 0
24 | 1
25 | 52
26 | Vagdpbqb98kWpbqPdKRZFewX6bKy+WXg7cd325/ea6oaA+cav69Wlvc8uL++0W1ZiRJGOg==
27 | 20
28 | GlHva0+8s0Izdez0a2Zy4+zYq1U=
29 | 5000
30 | 500
31 |
32 |
--------------------------------------------------------------------------------
/test/encfs_samples/boxcryptor_2/Z4Qzgr-iwj-1dgA:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/boxcryptor_2/Z4Qzgr-iwj-1dgA
--------------------------------------------------------------------------------
/test/encfs_samples/boxcryptor_2/hc2yatLg/lcgwUaXICbCjBW4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/boxcryptor_2/hc2yatLg/lcgwUaXICbCjBW4
--------------------------------------------------------------------------------
/test/encfs_samples/boxcryptor_3/.encfs6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 20100713
6 | BoxCryptor 1.0.0.0
7 |
8 | ssl/aes
9 | 3
10 | 0
11 |
12 |
13 | nameio/stream
14 | 2
15 | 1
16 |
17 | 256
18 | 4096
19 | 0
20 | 0
21 | 0
22 | 0
23 | 0
24 | 1
25 | 52
26 | oZxF/rvM3gexO3TNxaAZvBm/nsMzxm+2eLAFR7IfLBuOfziqgjyt4MEjWfGZEQEyhyRUig==
27 | 20
28 | NFehLBmSc50W+R9QPVPDdWU/5AE=
29 | 5000
30 | 500
31 |
32 |
--------------------------------------------------------------------------------
/test/encfs_samples/boxcryptor_3/cJTbxx2GhjzRDYYra4twBcIr0-pPGtD:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/boxcryptor_3/cJTbxx2GhjzRDYYra4twBcIr0-pPGtD
--------------------------------------------------------------------------------
/test/encfs_samples/boxcryptor_3/desktop.ini:
--------------------------------------------------------------------------------
1 | [.ShellClassInfo]
2 | IconResource=C:\Windows\system32\SHELL32.dll,27
3 | [ViewState]
4 | Mode=
5 | Vid=
6 | FolderType=Documents
7 |
--------------------------------------------------------------------------------
/test/encfs_samples/boxcryptor_null/.encfs6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 20100713
6 | BoxCryptor 1.3.2.0
7 |
8 | ssl/aes
9 | 3
10 | 0
11 |
12 |
13 | nameio/null
14 | 1
15 | 0
16 |
17 | 256
18 | 4096
19 | 0
20 | 0
21 | 0
22 | 0
23 | 0
24 | 1
25 | 52
26 | oZxF/rvM3gexO3TNxaAZvBm/nsMzxm+2eLAFR7IfLBuOfziqgjyt4MEjWfGZEQEyhyRUig==
27 | 20
28 | NFehLBmSc50W+R9QPVPDdWU/5AE=
29 | 5000
30 | 500
31 |
32 |
33 |
--------------------------------------------------------------------------------
/test/encfs_samples/boxcryptor_null/testfile.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/boxcryptor_null/testfile.txt
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-blockmac/.encfs6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 20100713
6 | EncFS 1.7.4
7 |
8 | ssl/aes
9 | 3
10 | 0
11 |
12 |
13 | nameio/block
14 | 3
15 | 0
16 |
17 | 192
18 | 1024
19 | 1
20 | 1
21 | 0
22 | 8
23 | 8
24 | 0
25 | 44
26 |
27 | MdcPVgzw5gWQUu5EVFsG8VaxkAWp8xTmSeBCjJwB/nAmJqEwsL4osY7b6Hw=
28 |
29 | 20
30 |
31 | 2R8IMzmv9INhi1VTC1oQwIhNI/s=
32 |
33 | 252483
34 | 500
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-blockmac/85hMcPOogQFKISDxPi,QcvlY:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/testvol-blockmac/85hMcPOogQFKISDxPi,QcvlY
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-default/.encfs6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 20100713
6 | EncFS 1.7.4
7 |
8 | ssl/aes
9 | 3
10 | 0
11 |
12 |
13 | nameio/block
14 | 3
15 | 0
16 |
17 | 192
18 | 1024
19 | 1
20 | 1
21 | 0
22 | 0
23 | 0
24 | 1
25 | 44
26 |
27 | 36hc1JmVocyDYLcIXLcJSVjC5MQ8Ys6mOH5DE2yEIlaHkbp6FaiuLC8rKL4=
28 |
29 | 20
30 |
31 | Li8XSCZeqCgJZPqnP0Ko2/99gQk=
32 |
33 | 253807
34 | 500
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-default/kNmBCW-Coq1CvGZ1EabjsiB4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/testvol-default/kNmBCW-Coq1CvGZ1EabjsiB4
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-default/ko1GW2gcuNSbGWQryepRJpSC:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/testvol-default/ko1GW2gcuNSbGWQryepRJpSC
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-default/qQQTyqU5n10lZYe-YTOfkTo2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/testvol-default/qQQTyqU5n10lZYe-YTOfkTo2
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-extivchn/.encfs6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 20100713
6 | EncFS 1.7.4
7 |
8 | ssl/aes
9 | 3
10 | 0
11 |
12 |
13 | nameio/block
14 | 3
15 | 0
16 |
17 | 256
18 | 1024
19 | 1
20 | 1
21 | 1
22 | 8
23 | 0
24 | 1
25 | 52
26 |
27 | LT6tG7SRgYpVD3bmMAtDs7PAae9NSavH0kBlkMZ/lwBdPw+wrF3LfkbL+eWo4huu00rouA==
28 |
29 | 20
30 |
31 | /7neEwCar1Ipa6AWv566tsDdWT4=
32 |
33 | 1161684
34 | 3000
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-extivchn/CjIsKUMxWNJZJ5mLWPboFUb5/FGSPI4b,efiE-vCHTF5-XAmw7jeS35Jy,EgYsJ7nhxwRN-:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/testvol-extivchn/CjIsKUMxWNJZJ5mLWPboFUb5/FGSPI4b,efiE-vCHTF5-XAmw7jeS35Jy,EgYsJ7nhxwRN-
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-extivchn/pWxw6SiMcDvaieR0K9IS4f0n:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/testvol-extivchn/pWxw6SiMcDvaieR0K9IS4f0n
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-nouniqueiv/.encfs6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 20100713
6 | EncFS 1.7.4
7 |
8 | ssl/aes
9 | 3
10 | 0
11 |
12 |
13 | nameio/block
14 | 3
15 | 0
16 |
17 | 256
18 | 1024
19 | 0
20 | 1
21 | 0
22 | 0
23 | 0
24 | 1
25 | 52
26 |
27 | WDbI6faBNx0YwgjGrOHlK/YSq2jfT56MxvXGyEPGJPmuSgbHNAM/jgauneNuGrrzVYyLCQ==
28 |
29 | 20
30 |
31 | NX9m/gl2B9+if+OHAWM4JRSniVI=
32 |
33 | 169700
34 | 500
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-nouniqueiv/XSuCblFoZx5WZQFkf3O6E8HS:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/testvol-nouniqueiv/XSuCblFoZx5WZQFkf3O6E8HS
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-nouniqueiv/fFHqdbodgs8p5Q1NH,pjhHle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/testvol-nouniqueiv/fFHqdbodgs8p5Q1NH,pjhHle
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-streamname/.encfs6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 20100713
6 | EncFS 1.7.4
7 |
8 | ssl/aes
9 | 3
10 | 0
11 |
12 |
13 | nameio/stream
14 | 2
15 | 1
16 |
17 | 256
18 | 1024
19 | 1
20 | 1
21 | 0
22 | 0
23 | 0
24 | 1
25 | 52
26 |
27 | YEwszW8YpVKtTTDqdjavLVAXt/ILh5hRr6Y+LkADse8j9fgyo3xMB3tPQZoDsLhqbY/k3g==
28 |
29 | 20
30 |
31 | YrRS94/u2lMCDPZE9UZ1lhJHV+A=
32 |
33 | 198018
34 | 500
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/test/encfs_samples/testvol-streamname/7W2,dU4/H-mMw-IyZnf6SdpOZo,:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mrpdaemon/encfs-java/702acc08242314fefe7f921757ea498ff78559cd/test/encfs_samples/testvol-streamname/7W2,dU4/H-mMw-IyZnf6SdpOZo,
--------------------------------------------------------------------------------