]> git.argeo.org Git - lgpl/argeo-commons.git/blob - DigestUtils.java
ce018007c6c637dce08d0c563e80d27a16c575cc
[lgpl/argeo-commons.git] / DigestUtils.java
1 package org.argeo.util;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.nio.ByteBuffer;
8 import java.nio.channels.FileChannel;
9 import java.nio.channels.FileChannel.MapMode;
10 import java.nio.file.Files;
11 import java.nio.file.Path;
12 import java.security.MessageDigest;
13 import java.security.NoSuchAlgorithmException;
14
15 /** Utilities around cryptographic digests */
16 public class DigestUtils {
17 public final static String MD5 = "MD5";
18 public final static String SHA1 = "SHA1";
19 public final static String SHA256 = "SHA-256";
20 public final static String SHA512 = "SHA-512";
21
22 private static Boolean debug = false;
23 // TODO: make it configurable
24 private final static Integer byteBufferCapacity = 100 * 1024;// 100 KB
25
26 public static byte[] sha1(byte[] bytes) {
27 try {
28 MessageDigest digest = MessageDigest.getInstance(SHA1);
29 digest.update(bytes);
30 byte[] checksum = digest.digest();
31 return checksum;
32 } catch (NoSuchAlgorithmException e) {
33 throw new IllegalArgumentException(e);
34 }
35 }
36
37 public static String digest(String algorithm, byte[] bytes) {
38 try {
39 MessageDigest digest = MessageDigest.getInstance(algorithm);
40 digest.update(bytes);
41 byte[] checksum = digest.digest();
42 String res = encodeHexString(checksum);
43 return res;
44 } catch (NoSuchAlgorithmException e) {
45 throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm, e);
46 }
47 }
48
49 public static String digest(String algorithm, InputStream in) {
50 try {
51 MessageDigest digest = MessageDigest.getInstance(algorithm);
52 // ReadableByteChannel channel = Channels.newChannel(in);
53 // ByteBuffer bb = ByteBuffer.allocateDirect(byteBufferCapacity);
54 // while (channel.read(bb) > 0)
55 // digest.update(bb);
56 byte[] buffer = new byte[byteBufferCapacity];
57 int read = 0;
58 while ((read = in.read(buffer)) > 0) {
59 digest.update(buffer, 0, read);
60 }
61
62 byte[] checksum = digest.digest();
63 String res = encodeHexString(checksum);
64 return res;
65 } catch (NoSuchAlgorithmException e) {
66 throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm, e);
67 } catch (IOException e) {
68 throw new RuntimeException(e);
69 } finally {
70 StreamUtils.closeQuietly(in);
71 }
72 }
73
74 public static String digest(String algorithm, File file) {
75 FileInputStream fis = null;
76 FileChannel fc = null;
77 try {
78 fis = new FileInputStream(file);
79 fc = fis.getChannel();
80
81 // Get the file's size and then map it into memory
82 int sz = (int) fc.size();
83 ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz);
84 return digest(algorithm, bb);
85 } catch (IOException e) {
86 throw new IllegalArgumentException("Cannot digest " + file + " with algorithm " + algorithm, e);
87 } finally {
88 StreamUtils.closeQuietly(fis);
89 if (fc.isOpen())
90 try {
91 fc.close();
92 } catch (IOException e) {
93 // silent
94 }
95 }
96 }
97
98 protected static String digest(String algorithm, ByteBuffer bb) {
99 long begin = System.currentTimeMillis();
100 try {
101 MessageDigest digest = MessageDigest.getInstance(algorithm);
102 digest.update(bb);
103 byte[] checksum = digest.digest();
104 String res = encodeHexString(checksum);
105 long end = System.currentTimeMillis();
106 if (debug)
107 System.out.println((end - begin) + " ms / " + ((end - begin) / 1000) + " s");
108 return res;
109 } catch (NoSuchAlgorithmException e) {
110 throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm, e);
111 }
112 }
113
114 public static String sha1hex(Path path) {
115 return digest(SHA1, path, byteBufferCapacity);
116 }
117
118 public static String digest(String algorithm, Path path, long bufferSize) {
119 byte[] digest = digestRaw(algorithm, path, bufferSize);
120 return encodeHexString(digest);
121 }
122
123 public static byte[] digestRaw(String algorithm, Path file, long bufferSize) {
124 long begin = System.currentTimeMillis();
125 try {
126 MessageDigest md = MessageDigest.getInstance(algorithm);
127 FileChannel fc = FileChannel.open(file);
128 long fileSize = Files.size(file);
129 if (fileSize <= bufferSize) {
130 ByteBuffer bb = fc.map(MapMode.READ_ONLY, 0, fileSize);
131 md.update(bb);
132 } else {
133 long lastCycle = (fileSize / bufferSize) - 1;
134 long position = 0;
135 for (int i = 0; i <= lastCycle; i++) {
136 ByteBuffer bb;
137 if (i != lastCycle) {
138 bb = fc.map(MapMode.READ_ONLY, position, bufferSize);
139 position = position + bufferSize;
140 } else {
141 bb = fc.map(MapMode.READ_ONLY, position, fileSize - position);
142 position = fileSize;
143 }
144 md.update(bb);
145 }
146 }
147 long end = System.currentTimeMillis();
148 if (debug)
149 System.out.println((end - begin) + " ms / " + ((end - begin) / 1000) + " s");
150 return md.digest();
151 } catch (NoSuchAlgorithmException e) {
152 throw new IllegalArgumentException("Cannot digest " + file + " with algorithm " + algorithm, e);
153 } catch (IOException e) {
154 throw new RuntimeException("Cannot digest " + file + " with algorithm " + algorithm, e);
155 }
156 }
157
158 public static void main(String[] args) {
159 File file;
160 if (args.length > 0)
161 file = new File(args[0]);
162 else {
163 System.err.println("Usage: <file> [<algorithm>]" + " (see http://java.sun.com/j2se/1.5.0/"
164 + "docs/guide/security/CryptoSpec.html#AppA)");
165 return;
166 }
167
168 if (args.length > 1) {
169 String algorithm = args[1];
170 System.out.println(digest(algorithm, file));
171 } else {
172 String algorithm = "MD5";
173 System.out.println(algorithm + ": " + digest(algorithm, file));
174 algorithm = "SHA";
175 System.out.println(algorithm + ": " + digest(algorithm, file));
176 System.out.println(algorithm + ": " + sha1hex(file.toPath()));
177 algorithm = "SHA-256";
178 System.out.println(algorithm + ": " + digest(algorithm, file));
179 algorithm = "SHA-512";
180 System.out.println(algorithm + ": " + digest(algorithm, file));
181 }
182 }
183
184 final private static char[] hexArray = "0123456789abcdef".toCharArray();
185
186 /**
187 * From
188 * http://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to
189 * -a-hex-string-in-java
190 */
191 public static String encodeHexString(byte[] bytes) {
192 char[] hexChars = new char[bytes.length * 2];
193 for (int j = 0; j < bytes.length; j++) {
194 int v = bytes[j] & 0xFF;
195 hexChars[j * 2] = hexArray[v >>> 4];
196 hexChars[j * 2 + 1] = hexArray[v & 0x0F];
197 }
198 return new String(hexChars);
199 }
200
201 }