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