1 /*
2 * This file is part of dependency-check-core.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * Copyright (c) 2014 Jeremy Long. All Rights Reserved.
17 */
18 package org.owasp.dependencycheck.utils;
19
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.IOException;
23 import java.nio.MappedByteBuffer;
24 import java.nio.channels.FileChannel;
25 import java.security.MessageDigest;
26 import java.security.NoSuchAlgorithmException;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29
30 /**
31 * Includes methods to generate the MD5 and SHA1 checksum.
32 *
33 * @author Jeremy Long <jeremy.long@owasp.org>
34 *
35 */
36 public final class Checksum {
37
38 /**
39 * The logger.
40 */
41 private static final Logger LOGGER = Logger.getLogger(Checksum.class.getName());
42
43 /**
44 * Private constructor for a utility class.
45 */
46 private Checksum() {
47 }
48
49 /**
50 * <p>
51 * Creates the cryptographic checksum of a given file using the specified algorithm.</p>
52 *
53 * @param algorithm the algorithm to use to calculate the checksum
54 * @param file the file to calculate the checksum for
55 * @return the checksum
56 * @throws IOException when the file does not exist
57 * @throws NoSuchAlgorithmException when an algorithm is specified that does not exist
58 */
59 @SuppressWarnings("empty-statement")
60 public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException {
61 MessageDigest digest = MessageDigest.getInstance(algorithm);
62 FileInputStream fis = null;
63 try {
64 fis = new FileInputStream(file);
65 FileChannel ch = fis.getChannel();
66 MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
67 digest.update(byteBuffer);
68 // BufferedInputStream bis = new BufferedInputStream(fis);
69 // DigestInputStream dis = new DigestInputStream(bis, digest);
70 // //yes, we are reading in a buffer for performance reasons - 1 byte at a time is SLOW
71 // byte[] buffer = new byte[8192];
72 // while (dis.read(buffer) != -1);
73 } finally {
74 if (fis != null) {
75 try {
76 fis.close();
77 } catch (IOException ex) {
78 LOGGER.log(Level.FINEST, "Error closing file '" + file.getName() + "'.", ex);
79 }
80 }
81 }
82 return digest.digest();
83 }
84
85 /**
86 * Calculates the MD5 checksum of a specified file.
87 *
88 * @param file the file to generate the MD5 checksum
89 * @return the hex representation of the MD5 hash
90 * @throws IOException when the file passed in does not exist
91 * @throws NoSuchAlgorithmException when the MD5 algorithm is not available
92 */
93 public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException {
94 byte[] b = getChecksum("MD5", file);
95 return getHex(b);
96 }
97
98 /**
99 * Calculates the SHA1 checksum of a specified file.
100 *
101 * @param file the file to generate the MD5 checksum
102 * @return the hex representation of the SHA1 hash
103 * @throws IOException when the file passed in does not exist
104 * @throws NoSuchAlgorithmException when the SHA1 algorithm is not available
105 */
106 public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException {
107 byte[] b = getChecksum("SHA1", file);
108 return getHex(b);
109 }
110 /**
111 * Hex code characters used in getHex.
112 */
113 private static final String HEXES = "0123456789ABCDEF";
114
115 /**
116 * <p>
117 * Converts a byte array into a hex string.</p>
118 *
119 * <p>
120 * This method was copied from <a
121 * href="http://www.rgagnon.com/javadetails/java-0596.html">http://www.rgagnon.com/javadetails/java-0596.html</a></p>
122 *
123 * @param raw a byte array
124 * @return the hex representation of the byte array
125 */
126 public static String getHex(byte[] raw) {
127 if (raw == null) {
128 return null;
129 }
130 final StringBuilder hex = new StringBuilder(2 * raw.length);
131 for (final byte b : raw) {
132 hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt(b & 0x0F));
133 }
134 return hex.toString();
135 }
136 }