1 /********************************************************************************
2 *InternetCafe is a software solution that helps the management of Cybercafes
3 * according with the ITALIAN DECREE LAW ON ANTI-TERROR MEASURES, 27 JULY 2005.
4 * Copyright (C) 2006 Guido Angelo Ingenito
5
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *******************************************************************************/
20 package base.jdbs;
21
22 import java.io.File;
23 import java.io.FileWriter;
24 import java.io.IOException;
25 import java.io.PrintStream;
26
27 import javax.xml.parsers.DocumentBuilderFactory;
28 import javax.xml.transform.Transformer;
29 import javax.xml.transform.TransformerFactory;
30 import javax.xml.transform.dom.DOMSource;
31 import javax.xml.transform.stream.StreamResult;
32
33 import org.apache.log4j.Logger;
34 import org.w3c.dom.Document;
35
36 import base.jdbs.cryptography.asymmetric.KeyPair;
37 import base.jdbs.cryptography.asymmetric.RSAAsymmetricCipher;
38 import base.jdbs.cryptography.symmetric.DESSymmetricCipher;
39 import base.jdbs.cryptography.symmetric.SymmetricKey;
40 import base.util.FileUtil;
41 import base.util.ZipUtil;
42
43 /***
44 * This class provided methods and utils to assembly a backup.
45 * @author Guido Angelo Ingenito
46 */
47 public class BackupArtifactAssembler {
48
49 public static final String ENCRYPTION_DIRECTORY_NAME = "enc";
50 public static final String DECRYPTION_DIRECTORY_NAME = "dec";
51
52 private static final transient Logger logger = Logger.getLogger(BackupArtifactAssembler.class.getName());
53
54 /***
55 * This method builds a new signed backup artifact placing it into a temp directory.
56 * The backup building process is fully described in the JDBS analysis and it consists of some phases:
57 * Phase 1: backup files encryption (only in the case of PRIVATE content).
58 * Phase 2: backup info file creation.
59 * Phase 3: backup compression.
60 * Phase 4: backup CRC32 Checksum, MD5 Digest and X509 certificate file creation.
61 * Phase 5: backup asymmetric signature ( the signature is placed on the MD5 Digest file and a new signed file is created ).
62 * @param symmetricKey The symmetric key to use in the encryption process.
63 * @param keyPair The asymmetric key pair to be used during the signing phase.
64 * @param backup The input backup from which the backup artifact must be created.
65 * @return The directory where the backup has been created and that contains the Compressed and Encrypted Backup Artifact and
66 * some info files. This outputted directory reference should be moved to the local JDBS users'repository.
67 * @throws IOException If something wrong happens with the filesystem.
68 */
69 public static File buildNewBackupArtifact(File repositoryDirectory, SymmetricKey symmetricKey, KeyPair keyPair, Backup backup) throws IOException{
70
71 final String backupArtifactName = backup.getGuId()+"-"+backup.getName();
72
73 final File backupDirectory = new File(repositoryDirectory,backupArtifactName);
74 backupDirectory.mkdir();
75 logger.debug("Backup Directory on local Repository: "+ backupDirectory);
76
77 final File encryptionDir = new File(backupDirectory,ENCRYPTION_DIRECTORY_NAME);
78 final File decryptionDir = new File(backupDirectory,DECRYPTION_DIRECTORY_NAME);
79
80 logger.debug("Backup Encryption Directory: "+ encryptionDir);
81 encryptionDir.mkdir();
82 logger.debug("Backup Decryption Directory: "+ decryptionDir);
83 decryptionDir.mkdir();
84
85
86 logger.debug("Backup's security level: "+backup.getSecurityLevel());
87 if(backup.getSecurityLevel().equals(SecurityLevel.PRIVATE)){
88 logger.debug("Symmetric encryption with key: "+symmetricKey.getValue()+"...");
89
90 DESSymmetricCipher symmetricCipher = new DESSymmetricCipher(symmetricKey);
91
92
93 for(int i=0;i<backup.getFileDescriptor().length;i++){
94 File encFile = new File(encryptionDir, backup.getFileDescriptor()[i].getFile().getAbsolutePath());
95 encFile.getParentFile().mkdirs();
96 encFile.createNewFile();
97 symmetricCipher.encrypt(backup.getFileDescriptor()[i].getFile(),encFile);
98 }
99
100
101 }else{
102 logger.debug("Moving backup's files under the decryption folder, backup has PUBLIC content...");
103
104 for(int i=0;i<backup.getFileDescriptor().length;i++){
105 File decFile = new File(decryptionDir, backup.getFileDescriptor()[i].getFile().getAbsolutePath());
106 decFile.getParentFile().mkdirs();
107 decFile.createNewFile();
108 FileUtil.copyFile(backup.getFileDescriptor()[i].getFile(),decFile);
109 }
110
111 }
112
113 final File compressedFile;
114 if(backup.getSecurityLevel().equals(SecurityLevel.PRIVATE)){
115 logger.debug("Backup has PRIVATE content, compressing the encryption directory...");
116 compressedFile = new File(backupDirectory,backupArtifactName+JDBSConstant.DOTTED_ZIP_EXTENSION);
117 compressedFile.createNewFile();
118 ZipUtil.zipDirectory(encryptionDir,compressedFile);
119 }
120 else{
121 logger.debug("Backup has PUBLIC content, compressing the decryption directory...");
122 compressedFile = new File(backupDirectory,backupArtifactName+JDBSConstant.DOTTED_ZIP_EXTENSION);
123 compressedFile.createNewFile();
124 ZipUtil.zipDirectory(decryptionDir,compressedFile);
125
126 }
127
128
129 logger.debug("Building the backup's xml info file...");
130 final File infoFile = new File(backupDirectory,JDBSConstant.XML_INFO_FILE_NAME);
131 writeBackupXmlInfoFile(backup, infoFile);
132
133
134 logger.debug("Writing backup's CRC32 Checksum...");
135 final File crc32File = new File(backupDirectory,JDBSConstant.CRC32_FILE_NAME);
136 writeBackupCRC32Checksum(crc32File, compressedFile);
137
138
139 logger.debug("Writing backup's MD5 Digest...");
140 final File md5File = new File(backupDirectory,JDBSConstant.MD5_FILE_NAME);
141 writeBackupMD5Digest(md5File, compressedFile);
142
143
144 logger.debug("Signing the backup artifact's MD5 digest...");
145 RSAAsymmetricCipher asymmetricCipher = new RSAAsymmetricCipher();
146 final File signedDigest = new File(md5File+JDBSConstant.DOTTED_SIGNED_EXTENSION);
147 if(keyPair == null)throw new IllegalArgumentException("AFFF1");
148 if(keyPair.getPrivateKey() == null)throw new IllegalArgumentException("AFFF2");
149
150 asymmetricCipher.sign(md5File, signedDigest,keyPair.getPrivateKey() );
151
152
153 logger.debug("Writing the X509Certificate...");
154 File certificateFile = new File(backupDirectory,JDBSConstant.CERTIFICATE_FILE_NAME);
155 writeX509Certificate(keyPair.getCertificate(), certificateFile);
156
157 logger.debug("Encryption Directory Deletion Result: " + FileUtil.deleteDirectory(encryptionDir));
158 logger.debug("Decryption Directory Deletion Result: " + FileUtil.deleteDirectory(decryptionDir));
159
160 logger.debug("Backup artifact successfully created...");
161 return backupDirectory;
162 }
163
164 /***
165 * This method writes to a file the info associated to a backup, in xml format.
166 * @param backup The backup whose info must be stored to the output file.
167 * @param outputInfo The outputFile where the info will be stored.
168 */
169 protected static void writeBackupXmlInfoFile(Backup backup, File outputInfo){
170 try {
171 Document backupInfoDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
172 backupInfoDocument.appendChild(backup.toXml(backupInfoDocument));
173 Transformer transformer = TransformerFactory.newInstance().newTransformer();
174 DOMSource source = new DOMSource(backupInfoDocument);
175 StreamResult streamResult = new StreamResult(new PrintStream(outputInfo));
176 transformer.transform(source, streamResult);
177 } catch (Exception ex) {
178 logger.error(ex.getMessage());
179 ex.printStackTrace();
180 }
181 }
182
183 /***
184 * This method writes a CRC32 Checksum to a file.
185 * @param crc32Output The CRC32 Checksum file to be written.
186 * @param compressedBackup The Compressed Backup Artifact from which the CRC32 must be computed.
187 */
188 protected static void writeBackupCRC32Checksum(File crc32Output, File compressedBackup){
189 FileWriter fileWriter;
190 try {
191 fileWriter = new FileWriter(crc32Output);
192 String backupCRC32 = FileUtil.createCRC32Checksum(compressedBackup).toString();
193 logger.debug("File: "+compressedBackup + " CRC32: "+backupCRC32);
194 fileWriter.write(backupCRC32);
195 fileWriter.close();
196 } catch (IOException ex) {
197 logger.error(ex.getMessage());
198 ex.printStackTrace();
199 }
200 }
201
202 /***
203 * This method writes a MD5 Digest to a file.
204 * @param MD5DigestOutput The MD5 Digest file to be written.
205 * @param compressedBackup The Compressed Backup Artifact from which the CRC32 must be computed.
206 */
207 protected static void writeBackupMD5Digest(File MD5DigestOutput, File compressedBackup){
208 FileWriter fileWriter;
209 try {
210 fileWriter = new FileWriter(MD5DigestOutput);
211 String backupMD5Digest = FileUtil.createMD5Digest(compressedBackup);
212 logger.debug("File: "+compressedBackup + " MD5: "+backupMD5Digest);
213 fileWriter.write(backupMD5Digest);
214 fileWriter.close();
215 } catch (IOException ex) {
216 logger.error(ex.getMessage());
217 ex.printStackTrace();
218 }
219 }
220
221
222 /***
223 * This method writes to a file an X509Certificate.
224 * @param certificate The certificate that must be saved.
225 * @param certificateFile The output file where the certificate must be stored.
226 */
227 protected static void writeX509Certificate(java.security.cert.X509Certificate certificate, File certificateFile){
228 FileWriter fileWriter;
229 try {
230 fileWriter = new FileWriter(certificateFile);
231 logger.debug("Certificate: \n"+ certificate + "\nSaved in file: "+certificateFile);
232 fileWriter.write(certificate.toString());
233 fileWriter.close();
234 } catch (IOException ex) {
235 logger.error(ex.getMessage());
236 ex.printStackTrace();
237 }
238 }
239 }