19 package org.sleuthkit.autopsy.modules.dataSourceIntegrity;
21 import java.security.MessageDigest;
22 import java.security.NoSuchAlgorithmException;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.logging.Level;
26 import java.util.Arrays;
27 import org.apache.commons.codec.binary.Hex;
38 import org.openide.util.NbBundle;
66 computeHashes = settings.shouldComputeHashes();
67 verifyHashes = settings.shouldVerifyHashes();
71 "DataSourceIntegrityIngestModule.startup.noCheckboxesSelected=At least one of the checkboxes must be selected"
78 if (!(computeHashes || verifyHashes)) {
79 throw new IngestModuleException(Bundle.DataSourceIntegrityIngestModule_startup_noCheckboxesSelected());
85 "DataSourceIntegrityIngestModule.process.skipCompute=Not computing new hashes for {0} since the option was disabled",
87 "DataSourceIntegrityIngestModule.process.skipVerify=Not verifying existing hashes for {0} since the option was disabled",
89 "DataSourceIntegrityIngestModule.process.hashAlgorithmError=Error creating message digest for {0} algorithm",
91 "DataSourceIntegrityIngestModule.process.hashMatch=<li>{0} hash verified </li>",
93 "DataSourceIntegrityIngestModule.process.hashNonMatch=<li>{0} hash not verified </li>",
94 "# {0} - calculatedHashValue",
95 "# {1} - storedHashValue",
96 "DataSourceIntegrityIngestModule.process.hashList=<ul><li>Calculated hash: {0} </li><li>Stored hash: {1} </li></ul>",
98 "# {1} - calculatedHashValue",
99 "DataSourceIntegrityIngestModule.process.calcHashWithType=<li>Calculated {0} hash: {1} </li>",
101 "DataSourceIntegrityIngestModule.process.calculateHashDone=<p>Data Source Hash Calculation Results for {0} </p>",
102 "DataSourceIntegrityIngestModule.process.hashesCalculated= hashes calculated",
104 "DataSourceIntegrityIngestModule.process.errorSavingHashes= Error saving hashes for image {0} to the database",
106 "DataSourceIntegrityIngestModule.process.errorLoadingHashes= Error loading hashes for image {0} from the database",
107 "# {0} - hashAlgorithm",
108 "# {1} - calculatedHashValue",
109 "# {2} - storedHashValue",
110 "DataSourceIntegrityIngestModule.process.hashFailedForArtifact={0} hash verification failed:\n Calculated hash: {1}\n Stored hash: {2}\n",
112 "DataSourceIntegrityIngestModule.process.verificationSuccess=Integrity of {0} verified",
114 "DataSourceIntegrityIngestModule.process.verificationFailure={0} failed integrity verification",})
117 String imgName = dataSource.getName();
120 if (!(dataSource instanceof Image)) {
121 logger.log(Level.INFO,
"Skipping non-image {0}", imgName);
123 NbBundle.getMessage(this.getClass(),
124 "DataSourceIntegrityIngestModule.process.skipNonEwf",
128 Image img = (Image) dataSource;
131 long size = img.getSize();
133 logger.log(Level.WARNING,
"Size of image {0} was 0 when queried.", imgName);
141 if (img.getMd5() != null && !img.getMd5().isEmpty()) {
144 if (img.getSha1() != null && !img.getSha1().isEmpty()) {
147 if (img.getSha256() != null && !img.getSha256().isEmpty()) {
150 }
catch (TskCoreException ex) {
151 String msg = Bundle.DataSourceIntegrityIngestModule_process_errorLoadingHashes(imgName);
153 logger.log(Level.SEVERE, msg, ex);
159 if (hashDataList.isEmpty()) {
167 logger.log(Level.INFO,
"Not computing hashes for {0} since the option was disabled", imgName);
169 Bundle.DataSourceIntegrityIngestModule_process_skipCompute(imgName)));
172 logger.log(Level.INFO,
"Not verifying hashes for {0} since the option was disabled", imgName);
174 Bundle.DataSourceIntegrityIngestModule_process_skipVerify(imgName)));
182 hashDataList.add(
new HashData(type,
""));
187 for (
HashData hashData : hashDataList) {
189 hashData.digest = MessageDigest.getInstance(hashData.type.getName());
190 }
catch (NoSuchAlgorithmException ex) {
191 String msg = Bundle.DataSourceIntegrityIngestModule_process_hashAlgorithmError(hashData.type.getName());
193 logger.log(Level.SEVERE, msg, ex);
201 long chunkSize = 64 * img.getSsize();
202 chunkSize = (chunkSize == 0) ? DEFAULT_CHUNK_SIZE : chunkSize;
205 int totalChunks = (int) Math.ceil((
double) size / (
double) chunkSize);
206 logger.log(Level.INFO,
"Total chunks = {0}", totalChunks);
209 logger.log(Level.INFO,
"Starting hash verification of {0}", img.getName());
211 logger.log(Level.INFO,
"Starting hash calculation for {0}", img.getName());
214 NbBundle.getMessage(this.getClass(),
215 "DataSourceIntegrityIngestModule.process.startingImg",
222 byte[] data =
new byte[(int) chunkSize];
224 for (
int i = 0; i < totalChunks; i++) {
229 read = img.read(data, i * chunkSize, chunkSize);
230 }
catch (TskCoreException ex) {
231 String msg = NbBundle.getMessage(this.getClass(),
232 "DataSourceIntegrityIngestModule.process.errReadImgAtChunk", imgName, i);
234 logger.log(Level.SEVERE, msg, ex);
239 if (read == chunkSize) {
240 for (
HashData struct : hashDataList) {
241 struct.digest.update(data);
244 byte[] subData = Arrays.copyOfRange(data, 0, read);
245 for (
HashData struct : hashDataList) {
246 struct.digest.update(subData);
253 for(
HashData hashData: hashDataList) {
254 hashData.calculatedHash = Hex.encodeHexString(hashData.digest.digest()).toLowerCase();
255 logger.log(Level.INFO,
"Hash calculated from {0}: {1}",
new Object[]{imgName, hashData.calculatedHash});
260 boolean verified =
true;
261 String detailedResults = NbBundle
262 .getMessage(this.getClass(),
"DataSourceIntegrityIngestModule.shutDown.verifyResultsHeader", imgName);
263 String hashResults =
"";
264 String artifactComment =
"";
266 for (
HashData hashData : hashDataList) {
267 if (hashData.storedHash.equals(hashData.calculatedHash)) {
268 hashResults += Bundle.DataSourceIntegrityIngestModule_process_hashMatch(hashData.type.name) +
" ";
271 hashResults += Bundle.DataSourceIntegrityIngestModule_process_hashNonMatch(hashData.type.name) +
" ";
272 artifactComment += Bundle.DataSourceIntegrityIngestModule_process_hashFailedForArtifact(hashData.type.name,
273 hashData.calculatedHash, hashData.storedHash) +
" ";
275 hashResults += Bundle.DataSourceIntegrityIngestModule_process_hashList(hashData.calculatedHash, hashData.storedHash);
278 String verificationResultStr;
279 String messageResultStr;
283 verificationResultStr = NbBundle.getMessage(this.getClass(),
"DataSourceIntegrityIngestModule.shutDown.verified");
284 messageResultStr = Bundle.DataSourceIntegrityIngestModule_process_verificationSuccess(imgName);
287 verificationResultStr = NbBundle.getMessage(this.getClass(),
"DataSourceIntegrityIngestModule.shutDown.notVerified");
288 messageResultStr = Bundle.DataSourceIntegrityIngestModule_process_verificationFailure(imgName);
291 detailedResults += NbBundle.getMessage(this.getClass(),
"DataSourceIntegrityIngestModule.shutDown.resultLi", verificationResultStr);
292 detailedResults += hashResults;
297 BlackboardArtifact.Type.TSK_VERIFICATION_FAILED,
298 img.getId(), img.getId(),
300 null, null, artifactComment,
301 Arrays.asList(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT,
303 .getAnalysisResult();
307 }
catch (TskCoreException ex) {
308 logger.log(Level.SEVERE,
"Error creating verification failed artifact", ex);
309 }
catch (Blackboard.BlackboardException ex) {
310 logger.log(Level.SEVERE,
"Error posting verification failed artifact", ex);
315 messageResultStr, detailedResults));
320 String results = Bundle.DataSourceIntegrityIngestModule_process_calculateHashDone(imgName);
322 for (
HashData hashData : hashDataList) {
323 switch (hashData.type) {
326 img.setMD5(hashData.calculatedHash);
327 }
catch (TskDataException ex) {
328 logger.log(Level.SEVERE,
"Error setting calculated hash", ex);
333 img.setSha1(hashData.calculatedHash);
334 }
catch (TskDataException ex) {
335 logger.log(Level.SEVERE,
"Error setting calculated hash", ex);
340 img.setSha256(hashData.calculatedHash);
341 }
catch (TskDataException ex) {
342 logger.log(Level.SEVERE,
"Error setting calculated hash", ex);
348 results += Bundle.DataSourceIntegrityIngestModule_process_calcHashWithType(hashData.type.name, hashData.calculatedHash);
353 imgName + Bundle.DataSourceIntegrityIngestModule_process_hashesCalculated(), results));
355 }
catch (TskCoreException ex) {
356 String msg = Bundle.DataSourceIntegrityIngestModule_process_errorSavingHashes(imgName);
358 logger.log(Level.SEVERE,
"Error saving hash for image " + imgName +
" to database", ex);
static final IngestServices services
org.sleuthkit.datamodel.Blackboard getArtifactsBlackboard()
static final Logger logger
static IngestMessage createMessage(MessageType messageType, String source, String subject, String detailsHtml)
final List< HashData > hashDataList
void postMessage(final IngestMessage message)
final boolean verifyHashes
SleuthkitCase getSleuthkitCase()
static final long DEFAULT_CHUNK_SIZE
boolean dataSourceIngestIsCancelled()
void switchToDeterminate(int workUnits)
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
final boolean computeHashes
ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper)
void progress(int workUnits)
void startUp(IngestJobContext context)
static synchronized IngestServices getInstance()