diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED index ec1b7be47e..6df3399a0a 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle.properties-MERGED @@ -96,7 +96,7 @@ Metadata.tableRowTitle.mimeType=MIME Type Metadata.tableRowTitle.name=Name Metadata.tableRowTitle.sectorSize=Sector Size Metadata.tableRowTitle.sha1=SHA1 -Metadata.tableRowTitle.sha256=SHA256 +Metadata.tableRowTitle.sha256=SHA-256 Metadata.tableRowTitle.size=Size Metadata.tableRowTitle.fileNameAlloc=File Name Allocation Metadata.tableRowTitle.metadataAlloc=Metadata Allocation diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java index 796386a5b3..45dae8e2e0 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java @@ -137,7 +137,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { "Metadata.tableRowTitle.mimeType=MIME Type", "Metadata.nodeText.truncated=(results truncated)", "Metadata.tableRowTitle.sha1=SHA1", - "Metadata.tableRowTitle.sha256=SHA256", + "Metadata.tableRowTitle.sha256=SHA-256", "Metadata.tableRowTitle.imageType=Type", "Metadata.tableRowTitle.sectorSize=Sector Size", "Metadata.tableRowTitle.timezone=Time Zone", @@ -182,6 +182,11 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer { md5 = NbBundle.getMessage(this.getClass(), "Metadata.tableRowContent.md5notCalc"); } addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.md5"), md5); + String sha256 = file.getSha256Hash(); + if (sha256 == null) { + sha256 = NbBundle.getMessage(this.getClass(), "Metadata.tableRowContent.md5notCalc"); + } + addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.sha256"), sha256); addRow(sb, NbBundle.getMessage(this.getClass(), "Metadata.tableRowTitle.hashLookupResults"), file.getKnown().toString()); addAcquisitionDetails(sb, dataSource); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 74ac603e0b..ee862eee96 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -278,6 +278,7 @@ public abstract class AbstractAbstractFileNode extends A "AbstractAbstractFileNode.typeMetaColLbl=Type(Meta)", "AbstractAbstractFileNode.knownColLbl=Known", "AbstractAbstractFileNode.md5HashColLbl=MD5 Hash", + "AbstractAbstractFileNode.sha256HashColLbl=SHA-256 Hash", "AbstractAbstractFileNode.objectId=Object ID", "AbstractAbstractFileNode.mimeType=MIME Type", "AbstractAbstractFileNode.extensionColLbl=Extension"}) @@ -305,6 +306,7 @@ public abstract class AbstractAbstractFileNode extends A TYPE_META(AbstractAbstractFileNode_typeMetaColLbl()), KNOWN(AbstractAbstractFileNode_knownColLbl()), MD5HASH(AbstractAbstractFileNode_md5HashColLbl()), + SHA256HASH(AbstractAbstractFileNode_sha256HashColLbl()), ObjectID(AbstractAbstractFileNode_objectId()), MIMETYPE(AbstractAbstractFileNode_mimeType()), EXTENSION(AbstractAbstractFileNode_extensionColLbl()); @@ -358,6 +360,7 @@ public abstract class AbstractAbstractFileNode extends A properties.add(new NodeProperty<>(KNOWN.toString(), KNOWN.toString(), NO_DESCR, content.getKnown().getName())); properties.add(new NodeProperty<>(LOCATION.toString(), LOCATION.toString(), NO_DESCR, getContentPath(content))); properties.add(new NodeProperty<>(MD5HASH.toString(), MD5HASH.toString(), NO_DESCR, StringUtils.defaultString(content.getMd5Hash()))); + properties.add(new NodeProperty<>(SHA256HASH.toString(), SHA256HASH.toString(), NO_DESCR, StringUtils.defaultString(content.getSha256Hash()))); properties.add(new NodeProperty<>(MIMETYPE.toString(), MIMETYPE.toString(), NO_DESCR, StringUtils.defaultString(content.getMIMEType()))); properties.add(new NodeProperty<>(EXTENSION.toString(), EXTENSION.toString(), NO_DESCR, content.getNameExtension())); @@ -577,6 +580,7 @@ public abstract class AbstractAbstractFileNode extends A map.put(FLAGS_META.toString(), content.getMetaFlagsAsString()); map.put(KNOWN.toString(), content.getKnown().getName()); map.put(MD5HASH.toString(), StringUtils.defaultString(content.getMd5Hash())); + map.put(SHA256HASH.toString(), StringUtils.defaultString(content.getSha256Hash())); map.put(MIMETYPE.toString(), StringUtils.defaultString(content.getMIMEType())); map.put(EXTENSION.toString(), content.getNameExtension()); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties-MERGED index e7310882a3..4e87eab218 100755 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Bundle.properties-MERGED @@ -30,6 +30,7 @@ AbstractAbstractFileNode.modifiedTimeColLbl=Modified Time AbstractAbstractFileNode.nameColLbl=Name AbstractAbstractFileNode.objectId=Object ID AbstractAbstractFileNode.originalName=Original Name +AbstractAbstractFileNode.sha256HashColLbl=SHA-256 Hash AbstractAbstractFileNode.sizeColLbl=Size AbstractAbstractFileNode.tagsProperty.displayName=Tags AbstractAbstractFileNode.typeDirColLbl=Type(Dir) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java index 65bf047fa1..f55d4b0488 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbIngestModule.java @@ -20,9 +20,11 @@ package org.sleuthkit.autopsy.modules.hashdatabase; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; import java.util.logging.Level; @@ -208,10 +210,17 @@ public class HashDbIngestModule implements FileIngestModule { // Safely get a reference to the totalsForIngestJobs object IngestJobTotals totals = getTotalsForIngestJobs(jobId); - // calc hash value - String md5Hash = getHash(file, totals); - if (md5Hash == null) { - return ProcessResult.ERROR; + // calc hash values + try { + calculateHashes(file, totals); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Error calculating hash of file '%s' (id=%d).", file.getName(), file.getId()), ex); //NON-NLS + services.postMessage(IngestMessage.createErrorMessage( + HashLookupModuleFactory.getModuleName(), + NbBundle.getMessage(this.getClass(), "HashDbIngestModule.fileReadErrorMsg", file.getName()), + NbBundle.getMessage(this.getClass(), "HashDbIngestModule.calcHashValueErr", + file.getParentPath() + file.getName(), + file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC) ? "Allocated File" : "Deleted File"))); } // the processing result of handling this file @@ -451,50 +460,46 @@ public class HashDbIngestModule implements FileIngestModule { } /** - * Retrieves the md5 hash for a file or generates one if no one exists on - * the file. + * Generates hashes for the given file if they haven't already been set. + * Hashes are saved to the AbstractFile object. * * @param file The file in order to determine the hash. * @param totals The timing metrics for this process. - * - * @return The found or determined md5 hash or null if none could be - * determined. */ - private String getHash(AbstractFile file, IngestJobTotals totals) { + private void calculateHashes(AbstractFile file, IngestJobTotals totals) throws TskCoreException { + + // First check if we've already calculated the hashes. String md5Hash = file.getMd5Hash(); - if (md5Hash != null && md5Hash.isEmpty()) { - return md5Hash; + String sha256Hash = file.getSha256Hash(); + if ((md5Hash != null && md5Hash.isEmpty()) + && (sha256Hash != null && sha256Hash.isEmpty())) { + return; } - try { - TimingMetric metric = HealthMonitor.getTimingMetric("Disk Reads: Hash calculation"); - long calcstart = System.currentTimeMillis(); - md5Hash = HashUtility.calculateMd5Hash(file); - if (file.getSize() > 0) { - // Surprisingly, the hash calculation does not seem to be correlated that - // strongly with file size until the files get large. - // Only normalize if the file size is greater than ~1MB. - if (file.getSize() < 1000000) { - HealthMonitor.submitTimingMetric(metric); - } else { - // In testing, this normalization gave reasonable resuls - HealthMonitor.submitNormalizedTimingMetric(metric, file.getSize() / 500000); - } + TimingMetric metric = HealthMonitor.getTimingMetric("Disk Reads: Hash calculation"); + long calcstart = System.currentTimeMillis(); + List newHashResults = + HashUtility.calculateHashes(file, Arrays.asList(HashUtility.HashType.MD5,HashUtility.HashType.SHA256 )); + if (file.getSize() > 0) { + // Surprisingly, the hash calculation does not seem to be correlated that + // strongly with file size until the files get large. + // Only normalize if the file size is greater than ~1MB. + if (file.getSize() < 1000000) { + HealthMonitor.submitTimingMetric(metric); + } else { + // In testing, this normalization gave reasonable resuls + HealthMonitor.submitNormalizedTimingMetric(metric, file.getSize() / 500000); } - file.setMd5Hash(md5Hash); - long delta = (System.currentTimeMillis() - calcstart); - totals.totalCalctime.addAndGet(delta); - return md5Hash; - } catch (IOException ex) { - logger.log(Level.WARNING, String.format("Error calculating hash of file '%s' (id=%d).", file.getName(), file.getId()), ex); //NON-NLS - services.postMessage(IngestMessage.createErrorMessage( - HashLookupModuleFactory.getModuleName(), - NbBundle.getMessage(this.getClass(), "HashDbIngestModule.fileReadErrorMsg", file.getName()), - NbBundle.getMessage(this.getClass(), "HashDbIngestModule.calcHashValueErr", - file.getParentPath() + file.getName(), - file.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC) ? "Allocated File" : "Deleted File"))); - return null; } + for (HashUtility.HashValue hash : newHashResults) { + if (hash.getType().equals(HashUtility.HashType.MD5)) { + file.setMd5Hash(hash.getValue()); + } else if (hash.getType().equals(HashUtility.HashType.SHA256)) { + file.setSha256Hash(hash.getValue()); + } + } + long delta = (System.currentTimeMillis() - calcstart); + totals.totalCalctime.addAndGet(delta); } /** diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java index 83bfb2fdae..67b253a1fa 100644 --- a/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java +++ b/Core/src/org/sleuthkit/autopsy/report/modules/portablecase/PortableCaseReportModule.java @@ -1117,7 +1117,7 @@ public class PortableCaseReportModule implements ReportModule { newContent = portableSkCase.addLocalFile(abstractFile.getName(), relativePath, abstractFile.getSize(), abstractFile.getCtime(), abstractFile.getCrtime(), abstractFile.getAtime(), abstractFile.getMtime(), - abstractFile.getMd5Hash(), abstractFile.getKnown(), abstractFile.getMIMEType(), + abstractFile.getMd5Hash(), abstractFile.getSha256Hash(), abstractFile.getKnown(), abstractFile.getMIMEType(), true, TskData.EncodingType.NONE, newParent, trans); } catch (IOException ex) {