| Line | Hits | Source |
|---|---|---|
| 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 | 0 | public class BackupArtifactAssembler { |
| 48 | ||
| 49 | public static final String ENCRYPTION_DIRECTORY_NAME = "enc"; | |
| 50 | public static final String DECRYPTION_DIRECTORY_NAME = "dec"; | |
| 51 | ||
| 52 | 0 | private static final transient Logger logger = Logger.getLogger(BackupArtifactAssembler.class.getName()); |
| 53 | ||
| 54 | 0 | /** |
| 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 | 0 | final String backupArtifactName = backup.getGuId()+"-"+backup.getName(); |
| 72 | //This is the backup directory under the local Repository | |
| 73 | 0 | final File backupDirectory = new File(repositoryDirectory,backupArtifactName); |
| 74 | 0 | backupDirectory.mkdir(); |
| 75 | 0 | logger.debug("Backup Directory on local Repository: "+ backupDirectory); |
| 76 | 0 | |
| 77 | 0 | final File encryptionDir = new File(backupDirectory,ENCRYPTION_DIRECTORY_NAME); |
| 78 | 0 | final File decryptionDir = new File(backupDirectory,DECRYPTION_DIRECTORY_NAME); |
| 79 | 0 | |
| 80 | 0 | logger.debug("Backup Encryption Directory: "+ encryptionDir); |
| 81 | 0 | encryptionDir.mkdir(); |
| 82 | 0 | logger.debug("Backup Decryption Directory: "+ decryptionDir); |
| 83 | 0 | decryptionDir.mkdir(); |
| 84 | 0 | |
| 85 | 0 | //Each backups' file must be encrypted preserving the directory structure on the filesystem... |
| 86 | 0 | logger.debug("Backup's security level: "+backup.getSecurityLevel()); |
| 87 | 0 | if(backup.getSecurityLevel().equals(SecurityLevel.PRIVATE)){ |
| 88 | 0 | logger.debug("Symmetric encryption with key: "+symmetricKey.getValue()+"..."); |
| 89 | 0 | |
| 90 | 0 | DESSymmetricCipher symmetricCipher = new DESSymmetricCipher(symmetricKey); |
| 91 | ||
| 92 | //Here starts the file encryption | |
| 93 | 0 | for(int i=0;i<backup.getFileDescriptor().length;i++){ |
| 94 | 0 | File encFile = new File(encryptionDir, backup.getFileDescriptor()[i].getFile().getAbsolutePath()); |
| 95 | 0 | encFile.getParentFile().mkdirs(); |
| 96 | 0 | encFile.createNewFile(); |
| 97 | 0 | symmetricCipher.encrypt(backup.getFileDescriptor()[i].getFile(),encFile); |
| 98 | } | |
| 99 | 0 | |
| 100 | 0 | |
| 101 | 0 | }else{ |
| 102 | 0 | logger.debug("Moving backup's files under the decryption folder, backup has PUBLIC content..."); |
| 103 | 0 | //Here starts the file copy |
| 104 | 0 | for(int i=0;i<backup.getFileDescriptor().length;i++){ |
| 105 | 0 | File decFile = new File(decryptionDir, backup.getFileDescriptor()[i].getFile().getAbsolutePath()); |
| 106 | 0 | decFile.getParentFile().mkdirs(); |
| 107 | 0 | decFile.createNewFile(); |
| 108 | 0 | FileUtil.copyFile(backup.getFileDescriptor()[i].getFile(),decFile); |
| 109 | } | |
| 110 | ||
| 111 | 0 | } |
| 112 | 0 | |
| 113 | 0 | final File compressedFile; |
| 114 | 0 | if(backup.getSecurityLevel().equals(SecurityLevel.PRIVATE)){ |
| 115 | 0 | logger.debug("Backup has PRIVATE content, compressing the encryption directory..."); |
| 116 | 0 | compressedFile = new File(backupDirectory,backupArtifactName+JDBSConstant.DOTTED_ZIP_EXTENSION); |
| 117 | 0 | compressedFile.createNewFile(); |
| 118 | 0 | ZipUtil.zipDirectory(encryptionDir,compressedFile); |
| 119 | 0 | } |
| 120 | 0 | else{ |
| 121 | 0 | logger.debug("Backup has PUBLIC content, compressing the decryption directory..."); |
| 122 | 0 | compressedFile = new File(backupDirectory,backupArtifactName+JDBSConstant.DOTTED_ZIP_EXTENSION); |
| 123 | 0 | compressedFile.createNewFile(); |
| 124 | 0 | ZipUtil.zipDirectory(decryptionDir,compressedFile); |
| 125 | ||
| 126 | 0 | } |
| 127 | 0 | |
| 128 | 0 | //Here must be stored in xml the informations relative to the backup content... |
| 129 | 0 | logger.debug("Building the backup's xml info file..."); |
| 130 | 0 | final File infoFile = new File(backupDirectory,JDBSConstant.XML_INFO_FILE_NAME); |
| 131 | 0 | writeBackupXmlInfoFile(backup, infoFile); |
| 132 | ||
| 133 | 0 | //Making a CRC32 for the compressed backup artifact... |
| 134 | 0 | logger.debug("Writing backup's CRC32 Checksum..."); |
| 135 | 0 | final File crc32File = new File(backupDirectory,JDBSConstant.CRC32_FILE_NAME); |
| 136 | 0 | writeBackupCRC32Checksum(crc32File, compressedFile); |
| 137 | ||
| 138 | //Making an MD5 digest for the compressed backup artifact, this will be signed with the users'private key... | |
| 139 | 0 | logger.debug("Writing backup's MD5 Digest..."); |
| 140 | 0 | final File md5File = new File(backupDirectory,JDBSConstant.MD5_FILE_NAME); |
| 141 | 0 | writeBackupMD5Digest(md5File, compressedFile); |
| 142 | ||
| 143 | //In each case, PRIVATE or PUBLIC content the backup MD5 must be signed with the privateKey to check integrity and security... | |
| 144 | 0 | logger.debug("Signing the backup artifact's MD5 digest..."); |
| 145 | 0 | RSAAsymmetricCipher asymmetricCipher = new RSAAsymmetricCipher(); |
| 146 | 0 | final File signedDigest = new File(md5File+JDBSConstant.DOTTED_SIGNED_EXTENSION); |
| 147 | 0 | if(keyPair == null)throw new IllegalArgumentException("AFFF1"); |
| 148 | 0 | if(keyPair.getPrivateKey() == null)throw new IllegalArgumentException("AFFF2"); |
| 149 | 0 | |
| 150 | 0 | asymmetricCipher.sign(md5File, signedDigest,keyPair.getPrivateKey() ); |
| 151 | ||
| 152 | 0 | //The keyPair associated certificate must be stored to the output directory... |
| 153 | 0 | logger.debug("Writing the X509Certificate..."); |
| 154 | 0 | File certificateFile = new File(backupDirectory,JDBSConstant.CERTIFICATE_FILE_NAME); |
| 155 | 0 | writeX509Certificate(keyPair.getCertificate(), certificateFile); |
| 156 | 0 | |
| 157 | 0 | logger.debug("Encryption Directory Deletion Result: " + FileUtil.deleteDirectory(encryptionDir)); |
| 158 | 0 | logger.debug("Decryption Directory Deletion Result: " + FileUtil.deleteDirectory(decryptionDir)); |
| 159 | 0 | |
| 160 | 0 | logger.debug("Backup artifact successfully created..."); |
| 161 | 0 | return backupDirectory; |
| 162 | 0 | } |
| 163 | 0 | |
| 164 | 0 | /** |
| 165 | 0 | * This method writes to a file the info associated to a backup, in xml format. |
| 166 | 0 | * @param backup The backup whose info must be stored to the output file. |
| 167 | 0 | * @param outputInfo The outputFile where the info will be stored. |
| 168 | 0 | */ |
| 169 | protected static void writeBackupXmlInfoFile(Backup backup, File outputInfo){ | |
| 170 | 0 | try { |
| 171 | 0 | Document backupInfoDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); |
| 172 | 0 | backupInfoDocument.appendChild(backup.toXml(backupInfoDocument)); |
| 173 | 0 | Transformer transformer = TransformerFactory.newInstance().newTransformer(); |
| 174 | 0 | DOMSource source = new DOMSource(backupInfoDocument); |
| 175 | 0 | StreamResult streamResult = new StreamResult(new PrintStream(outputInfo)); |
| 176 | 0 | transformer.transform(source, streamResult); |
| 177 | 0 | } catch (Exception ex) { |
| 178 | 0 | logger.error(ex.getMessage()); |
| 179 | 0 | ex.printStackTrace(); |
| 180 | 0 | } |
| 181 | 0 | } |
| 182 | 0 | |
| 183 | 0 | /** |
| 184 | 0 | * This method writes a CRC32 Checksum to a file. |
| 185 | 0 | * @param crc32Output The CRC32 Checksum file to be written. |
| 186 | 0 | * @param compressedBackup The Compressed Backup Artifact from which the CRC32 must be computed. |
| 187 | 0 | */ |
| 188 | 0 | protected static void writeBackupCRC32Checksum(File crc32Output, File compressedBackup){ |
| 189 | 0 | FileWriter fileWriter; |
| 190 | try { | |
| 191 | 0 | fileWriter = new FileWriter(crc32Output); |
| 192 | 0 | String backupCRC32 = FileUtil.createCRC32Checksum(compressedBackup).toString(); |
| 193 | 0 | logger.debug("File: "+compressedBackup + " CRC32: "+backupCRC32); |
| 194 | 0 | fileWriter.write(backupCRC32); |
| 195 | 0 | fileWriter.close(); |
| 196 | 0 | } catch (IOException ex) { |
| 197 | 0 | logger.error(ex.getMessage()); |
| 198 | 0 | ex.printStackTrace(); |
| 199 | 0 | } |
| 200 | 0 | } |
| 201 | 0 | |
| 202 | 0 | /** |
| 203 | 0 | * This method writes a MD5 Digest to a file. |
| 204 | 0 | * @param MD5DigestOutput The MD5 Digest file to be written. |
| 205 | 0 | * @param compressedBackup The Compressed Backup Artifact from which the CRC32 must be computed. |
| 206 | 0 | */ |
| 207 | 0 | protected static void writeBackupMD5Digest(File MD5DigestOutput, File compressedBackup){ |
| 208 | 0 | FileWriter fileWriter; |
| 209 | try { | |
| 210 | 0 | fileWriter = new FileWriter(MD5DigestOutput); |
| 211 | 0 | String backupMD5Digest = FileUtil.createMD5Digest(compressedBackup); |
| 212 | 0 | logger.debug("File: "+compressedBackup + " MD5: "+backupMD5Digest); |
| 213 | 0 | fileWriter.write(backupMD5Digest); |
| 214 | 0 | fileWriter.close(); |
| 215 | 0 | } catch (IOException ex) { |
| 216 | 0 | logger.error(ex.getMessage()); |
| 217 | 0 | ex.printStackTrace(); |
| 218 | 0 | } |
| 219 | 0 | } |
| 220 | 0 | |
| 221 | 0 | |
| 222 | 0 | /** |
| 223 | 0 | * This method writes to a file an X509Certificate. |
| 224 | 0 | * @param certificate The certificate that must be saved. |
| 225 | 0 | * @param certificateFile The output file where the certificate must be stored. |
| 226 | 0 | */ |
| 227 | 0 | protected static void writeX509Certificate(java.security.cert.X509Certificate certificate, File certificateFile){ |
| 228 | FileWriter fileWriter; | |
| 229 | try { | |
| 230 | 0 | fileWriter = new FileWriter(certificateFile); |
| 231 | 0 | logger.debug("Certificate: \n"+ certificate + "\nSaved in file: "+certificateFile); |
| 232 | 0 | fileWriter.write(certificate.toString()); |
| 233 | 0 | fileWriter.close(); |
| 234 | 0 | } catch (IOException ex) { |
| 235 | 0 | logger.error(ex.getMessage()); |
| 236 | 0 | ex.printStackTrace(); |
| 237 | 0 | } |
| 238 | 0 | } |
| 239 | 0 | } |
|
this report was generated by version 1.0.5 of jcoverage. |
copyright © 2003, jcoverage ltd. all rights reserved. |