View Javadoc
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 org.slf4j.Logger;
21  import org.slf4j.LoggerFactory;
22  
23  import java.io.File;
24  import java.io.FileInputStream;
25  import java.io.IOException;
26  import java.nio.ByteBuffer;
27  import java.nio.channels.FileChannel;
28  import java.security.MessageDigest;
29  import java.security.NoSuchAlgorithmException;
30  
31  /**
32   * Includes methods to generate the MD5 and SHA1 checksum.
33   *
34   * @author Jeremy Long
35   *
36   */
37  public final class Checksum {
38  
39      /**
40       * The logger.
41       */
42      private static final Logger LOGGER = LoggerFactory.getLogger(Checksum.class);
43  
44      /**
45       * Private constructor for a utility class.
46       */
47      private Checksum() {
48      }
49  
50      /**
51       * <p>
52       * Creates the cryptographic checksum of a given file using the specified
53       * algorithm.</p>
54       *
55       * @param algorithm the algorithm to use to calculate the checksum
56       * @param file the file to calculate the checksum for
57       * @return the checksum
58       * @throws IOException when the file does not exist
59       * @throws NoSuchAlgorithmException when an algorithm is specified that does
60       * not exist
61       */
62      public static byte[] getChecksum(String algorithm, File file) throws NoSuchAlgorithmException, IOException {
63          final MessageDigest md = MessageDigest.getInstance(algorithm);
64          FileInputStream fis = null;
65          FileChannel ch = null;
66          try {
67              fis = new FileInputStream(file);
68              ch = fis.getChannel();
69              final ByteBuffer buf = ByteBuffer.allocateDirect(8192);
70              int b = ch.read(buf);
71              while (b != -1 && b != 0) {
72                  buf.flip();
73                  final byte[] bytes = new byte[b];
74                  buf.get(bytes);
75                  md.update(bytes, 0, b);
76                  buf.clear();
77                  b = ch.read(buf);
78              }
79              return md.digest();
80          } finally {
81              if (ch != null) {
82                  try {
83                      ch.close();
84                  } catch (IOException ex) {
85                      LOGGER.trace("Error closing channel '{}'.", file.getName(), ex);
86                  }
87              }
88              if (fis != null) {
89                  try {
90                      fis.close();
91                  } catch (IOException ex) {
92                      LOGGER.trace("Error closing file '{}'.", file.getName(), ex);
93                  }
94              }
95          }
96      }
97  
98      /**
99       * Calculates the MD5 checksum of a specified file.
100      *
101      * @param file the file to generate the MD5 checksum
102      * @return the hex representation of the MD5 hash
103      * @throws IOException when the file passed in does not exist
104      * @throws NoSuchAlgorithmException when the MD5 algorithm is not available
105      */
106     public static String getMD5Checksum(File file) throws IOException, NoSuchAlgorithmException {
107         final byte[] b = getChecksum("MD5", file);
108         return getHex(b);
109     }
110 
111     /**
112      * Calculates the SHA1 checksum of a specified file.
113      *
114      * @param file the file to generate the MD5 checksum
115      * @return the hex representation of the SHA1 hash
116      * @throws IOException when the file passed in does not exist
117      * @throws NoSuchAlgorithmException when the SHA1 algorithm is not available
118      */
119     public static String getSHA1Checksum(File file) throws IOException, NoSuchAlgorithmException {
120         final byte[] b = getChecksum("SHA1", file);
121         return getHex(b);
122     }
123     /**
124      * Hex code characters used in getHex.
125      */
126     private static final String HEXES = "0123456789abcdef";
127 
128     /**
129      * <p>
130      * Converts a byte array into a hex string.</p>
131      *
132      * <p>
133      * This method was copied from <a
134      * href="http://www.rgagnon.com/javadetails/java-0596.html">http://www.rgagnon.com/javadetails/java-0596.html</a></p>
135      *
136      * @param raw a byte array
137      * @return the hex representation of the byte array
138      */
139     public static String getHex(byte[] raw) {
140         if (raw == null) {
141             return null;
142         }
143         final StringBuilder hex = new StringBuilder(2 * raw.length);
144         for (final byte b : raw) {
145             hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt(b & 0x0F));
146         }
147         return hex.toString();
148     }
149 }