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