diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java index e473c7497..3a568daf2 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java @@ -32,10 +32,7 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileFilter; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.owasp.dependencycheck.dependency.EvidenceType; @@ -135,12 +132,7 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer { */ @Override protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationException { - try { - getSha1MessageDigest(); - } catch (IllegalStateException ex) { - setEnabled(false); - throw new InitializationException("Unable to create SHA1 MessageDigest", ex); - } + //do nothing } /** @@ -191,9 +183,6 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer { * @param engine the dependency-check engine * @param contents the version information */ - @edu.umd.cs.findbugs.annotations.SuppressFBWarnings( - value = "DM_DEFAULT_ENCODING", - justification = "Default encoding is only used if UTF-8 is not available") private void analyzeSetVersionCommand(Dependency dependency, Engine engine, String contents) { Dependency currentDep = dependency; @@ -218,14 +207,8 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer { final String filePath = String.format("%s:%s", dependency.getFilePath(), product); currentDep.setFilePath(filePath); - byte[] path; - try { - path = filePath.getBytes("UTF-8"); - } catch (UnsupportedEncodingException ex) { - path = filePath.getBytes(); - } - final MessageDigest sha1 = getSha1MessageDigest(); - currentDep.setSha1sum(Checksum.getHex(sha1.digest(path))); + currentDep.setSha1sum(Checksum.getSHA1Checksum(filePath)); + currentDep.setMd5sum(Checksum.getMD5Checksum(filePath)); engine.addDependency(currentDep); } final String source = currentDep.getFileName(); @@ -242,18 +225,4 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer { protected String getAnalyzerEnabledSettingKey() { return Settings.KEYS.ANALYZER_CMAKE_ENABLED; } - - /** - * Returns the SHA1 message digest. - * - * @return the SHA1 message digest - */ - private MessageDigest getSha1MessageDigest() { - try { - return MessageDigest.getInstance("SHA1"); - } catch (NoSuchAlgorithmException e) { - LOGGER.error(e.getMessage()); - throw new IllegalStateException("Failed to obtain the SHA1 message digest.", e); - } - } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java index aba20c9d5..e2aeba101 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java @@ -34,9 +34,6 @@ import org.slf4j.LoggerFactory; import java.io.FileFilter; import java.io.FileInputStream; import java.io.IOException; -import java.nio.charset.Charset; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import org.owasp.dependencycheck.dependency.EvidenceType; /** @@ -92,12 +89,7 @@ public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer { */ @Override protected void prepareFileTypeAnalyzer(Engine engine) throws InitializationException { - try { - getSha1MessageDigest(); - } catch (IllegalStateException ex) { - setEnabled(false); - throw new InitializationException("Unable to create SHA1 MessageDigest", ex); - } + // do nothing } /** @@ -122,9 +114,9 @@ public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer { d.setName(dep.getProject()); d.setVersion(dep.getVersion()); d.setEcosystem(DEPENDENCY_ECOSYSTEM); - final MessageDigest sha1 = getSha1MessageDigest(); d.setFilePath(filePath); - d.setSha1sum(Checksum.getHex(sha1.digest(filePath.getBytes(Charset.defaultCharset())))); + d.setSha1sum(Checksum.getSHA1Checksum(filePath)); + d.setMd5sum(Checksum.getMD5Checksum(filePath)); d.addEvidence(EvidenceType.VENDOR, COMPOSER_LOCK, "vendor", dep.getGroup(), Confidence.HIGHEST); d.addEvidence(EvidenceType.PRODUCT, COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST); d.addEvidence(EvidenceType.VERSION, COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST); @@ -175,18 +167,4 @@ public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer { public AnalysisPhase getAnalysisPhase() { return AnalysisPhase.INFORMATION_COLLECTION; } - - /** - * Returns the sha1 message digest. - * - * @return the sha1 message digest - */ - private MessageDigest getSha1MessageDigest() { - try { - return MessageDigest.getInstance("SHA1"); - } catch (NoSuchAlgorithmException e) { - LOGGER.error(e.getMessage()); - throw new IllegalStateException("Failed to obtain the SHA1 message digest.", e); - } - } } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.java index b87b7c57c..df6f50708 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.java @@ -17,8 +17,6 @@ */ package org.owasp.dependencycheck.analyzer; -import mockit.Mock; -import mockit.MockUp; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -28,12 +26,8 @@ import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.data.nvdcve.DatabaseException; import org.owasp.dependencycheck.dependency.Dependency; -import org.owasp.dependencycheck.exception.InitializationException; import java.io.File; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.List; import java.util.regex.Pattern; import static org.hamcrest.CoreMatchers.equalTo; @@ -197,22 +191,4 @@ public class CMakeAnalyzerTest extends BaseDBTestCase { } assertTrue("Expected version evidence to contain \"" + version + "\".", found); } - - @Test(expected = InitializationException.class) - public void analyzerIsDisabledInCaseOfMissingMessageDigest() throws InitializationException { - new MockUp() { - @Mock - MessageDigest getInstance(String ignore) throws NoSuchAlgorithmException { - throw new NoSuchAlgorithmException(); - } - }; - - analyzer = new CMakeAnalyzer(); - analyzer.setFilesMatched(true); - assertTrue(analyzer.isEnabled()); - analyzer.initialize(getSettings()); - analyzer.prepare(null); - - assertFalse(analyzer.isEnabled()); - } } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzerTest.java index 53dd3e1a6..d5f1b8778 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzerTest.java @@ -17,8 +17,6 @@ */ package org.owasp.dependencycheck.analyzer; -import mockit.Mock; -import mockit.MockUp; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -27,11 +25,8 @@ import org.owasp.dependencycheck.BaseTest; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Dependency; -import org.owasp.dependencycheck.exception.InitializationException; import java.io.File; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import org.apache.commons.lang3.ArrayUtils; import static org.junit.Assert.assertEquals; @@ -137,22 +132,4 @@ public class ComposerLockAnalyzerTest extends BaseDBTestCase { assertEquals(ComposerLockAnalyzer.DEPENDENCY_ECOSYSTEM, d.getEcosystem()); } } - - @Test(expected = InitializationException.class) - public void analyzerIsDisabledInCaseOfMissingMessageDigest() throws InitializationException { - new MockUp() { - @Mock - MessageDigest getInstance(String ignore) throws NoSuchAlgorithmException { - throw new NoSuchAlgorithmException("SHA1 is missing"); - } - }; - - analyzer = new ComposerLockAnalyzer(); - analyzer.setFilesMatched(true); - analyzer.initialize(getSettings()); - assertTrue(analyzer.isEnabled()); - analyzer.prepare(null); - - assertFalse(analyzer.isEnabled()); - } } diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Checksum.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Checksum.java index fa4565946..25200c077 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Checksum.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Checksum.java @@ -22,8 +22,12 @@ import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Includes methods to generate the MD5 and SHA1 checksum. @@ -38,6 +42,11 @@ public final class Checksum { */ private static final String HEXES = "0123456789abcdef"; + /** + * The logger. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(Checksum.class); + /** * Private constructor for a utility class. */ @@ -100,6 +109,58 @@ public final class Checksum { return getHex(b); } + /** + * Calculates the MD5 checksum of a specified bytes. + * + * @param algorithm the algorithm to use (md5, sha1, etc.) to calculate the + * message digest + * @param bytes the bytes to generate the MD5 checksum + * @return the hex representation of the MD5 hash + */ + public static String getChecksum(String algorithm, byte[] bytes) { + MessageDigest digest = getMessageDigest(algorithm); + final byte[] b = digest.digest(bytes); + return getHex(b); + } + + /** + * Calculates the MD5 checksum of the specified text. + * + * @param text the text to generate the MD5 checksum + * @return the hex representation of the MD5 + */ + public static String getMD5Checksum(String text) { + final byte[] data = stringToBytes(text); + return getChecksum("MD5", data); + } + + /** + * Calculates the SHA1 checksum of the specified text. + * + * @param text the text to generate the SHA1 checksum + * @return the hex representation of the SHA1 + */ + public static String getSHA1Checksum(String text) { + final byte[] data = stringToBytes(text); + return getChecksum("SHA1", data); + } + + /** + * Converts the given text into bytes. + * + * @param text the text to convert + * @return the bytes + */ + private static byte[] stringToBytes(String text) { + byte[] data; + try { + data = text.getBytes(Charset.forName("UTF-8")); + } catch (UnsupportedCharsetException ex) { + data = text.getBytes(Charset.defaultCharset()); + } + return data; + } + /** *

* Converts a byte array into a hex string.

@@ -121,4 +182,20 @@ public final class Checksum { } return hex.toString(); } + + /** + * Returns the message digest. + * + * @param algorithm the algorithm for the message digest + * @return the message digest + */ + private static MessageDigest getMessageDigest(String algorithm) { + try { + return MessageDigest.getInstance(algorithm); + } catch (NoSuchAlgorithmException e) { + LOGGER.error(e.getMessage()); + final String msg = String.format("Failed to obtain the {} message digest.", algorithm); + throw new IllegalStateException(msg, e); + } + } } diff --git a/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/ChecksumTest.java b/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/ChecksumTest.java index 14b347c98..ce5e68481 100644 --- a/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/ChecksumTest.java +++ b/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/ChecksumTest.java @@ -20,10 +20,15 @@ package org.owasp.dependencycheck.utils; import java.io.File; import java.io.IOException; import java.security.NoSuchAlgorithmException; +import org.junit.After; +import org.junit.AfterClass; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -48,15 +53,7 @@ public class ChecksumTest { File file = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").toURI().getPath()); byte[] expResult = {-16, -111, 92, 95, 70, -72, -49, -94, -125, -27, -83, 103, -96, -101, 55, -109}; byte[] result = Checksum.getChecksum(algorithm, file); - boolean arraysAreEqual = true; - if (expResult.length == result.length) { - for (int i = 0; arraysAreEqual && i < result.length; i++) { - arraysAreEqual = result[i] == expResult[i]; - } - } else { - fail("Checksum results do not match expected results."); - } - assertTrue(arraysAreEqual); + assertArrayEquals(expResult, result); } /** @@ -128,4 +125,72 @@ public class ChecksumTest { String result = Checksum.getHex(raw); assertEquals(expResult, result); } + + /** + * Test of getChecksum method, of class Checksum. + */ + @Test + public void testGetChecksum_String_File() throws Exception { + String algorithm = "MD5"; + File file = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").toURI().getPath()); + byte[] expResult = {-16, -111, 92, 95, 70, -72, -49, -94, -125, -27, -83, 103, -96, -101, 55, -109}; + byte[] result = Checksum.getChecksum(algorithm, file); + assertArrayEquals(expResult, result); + } + + /** + * Test of getMD5Checksum method, of class Checksum. + */ + @Test + public void testGetMD5Checksum_File() throws Exception { + File file = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").toURI().getPath()); + String expResult = "f0915c5f46b8cfa283e5ad67a09b3793"; + String result = Checksum.getMD5Checksum(file); + assertEquals(expResult, result); + } + + /** + * Test of getSHA1Checksum method, of class Checksum. + */ + @Test + public void testGetSHA1Checksum_File() throws Exception { + File file = new File(this.getClass().getClassLoader().getResource("checkSumTest.file").toURI().getPath()); + String expResult = "b8a9ff28b21bcb1d0b50e24a5243d8b51766851a"; + String result = Checksum.getSHA1Checksum(file); + assertEquals(expResult, result); + } + + /** + * Test of getChecksum method, of class Checksum. + */ + @Test + public void testGetChecksum_String_byteArr() { + String algorithm = "SHA1"; + byte[] bytes = {-16, -111, 92, 95, 70, -72, -49, -94, -125, -27, -83, 103, -96, -101, 55, -109}; + String expResult = "89268a389a97f0bfba13d3ff2370d8ad436e36f6"; + String result = Checksum.getChecksum(algorithm, bytes); + assertEquals(expResult, result); + } + + /** + * Test of getMD5Checksum method, of class Checksum. + */ + @Test + public void testGetMD5Checksum_String() { + String text = "test string"; + String expResult = "6f8db599de986fab7a21625b7916589c"; + String result = Checksum.getMD5Checksum(text); + assertEquals(expResult, result); + } + + /** + * Test of getSHA1Checksum method, of class Checksum. + */ + @Test + public void testGetSHA1Checksum_String() { + String text = "test string"; + String expResult = "661295c9cbf9d6b2f6428414504a8deed3020641"; + String result = Checksum.getSHA1Checksum(text); + assertEquals(expResult, result); + } }