1 package org
.argeo
.util
;
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
;
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";
22 private static Boolean debug
= false;
23 // TODO: make it configurable
24 private final static Integer byteBufferCapacity
= 100 * 1024;// 100 KB
26 public static byte[] sha1(byte[] bytes
) {
28 MessageDigest digest
= MessageDigest
.getInstance(SHA1
);
30 byte[] checksum
= digest
.digest();
32 } catch (NoSuchAlgorithmException e
) {
33 throw new IllegalArgumentException(e
);
37 public static String
digest(String algorithm
, byte[] bytes
) {
39 MessageDigest digest
= MessageDigest
.getInstance(algorithm
);
41 byte[] checksum
= digest
.digest();
42 String res
= encodeHexString(checksum
);
44 } catch (NoSuchAlgorithmException e
) {
45 throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm
, e
);
49 public static String
digest(String algorithm
, InputStream in
) {
51 MessageDigest digest
= MessageDigest
.getInstance(algorithm
);
52 // ReadableByteChannel channel = Channels.newChannel(in);
53 // ByteBuffer bb = ByteBuffer.allocateDirect(byteBufferCapacity);
54 // while (channel.read(bb) > 0)
56 byte[] buffer
= new byte[byteBufferCapacity
];
58 while ((read
= in
.read(buffer
)) > 0) {
59 digest
.update(buffer
, 0, read
);
62 byte[] checksum
= digest
.digest();
63 String res
= encodeHexString(checksum
);
65 } catch (NoSuchAlgorithmException e
) {
66 throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm
, e
);
67 } catch (IOException e
) {
68 throw new RuntimeException(e
);
70 StreamUtils
.closeQuietly(in
);
74 public static String
digest(String algorithm
, File file
) {
75 FileInputStream fis
= null;
76 FileChannel fc
= null;
78 fis
= new FileInputStream(file
);
79 fc
= fis
.getChannel();
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
);
88 StreamUtils
.closeQuietly(fis
);
92 } catch (IOException e
) {
98 protected static String
digest(String algorithm
, ByteBuffer bb
) {
99 long begin
= System
.currentTimeMillis();
101 MessageDigest digest
= MessageDigest
.getInstance(algorithm
);
103 byte[] checksum
= digest
.digest();
104 String res
= encodeHexString(checksum
);
105 long end
= System
.currentTimeMillis();
107 System
.out
.println((end
- begin
) + " ms / " + ((end
- begin
) / 1000) + " s");
109 } catch (NoSuchAlgorithmException e
) {
110 throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm
, e
);
114 public static String
sha1hex(Path path
) {
115 return digest(SHA1
, path
, byteBufferCapacity
);
118 public static String
digest(String algorithm
, Path path
, long bufferSize
) {
119 byte[] digest
= digestRaw(algorithm
, path
, bufferSize
);
120 return encodeHexString(digest
);
123 public static byte[] digestRaw(String algorithm
, Path file
, long bufferSize
) {
124 long begin
= System
.currentTimeMillis();
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
);
133 long lastCycle
= (fileSize
/ bufferSize
) - 1;
135 for (int i
= 0; i
<= lastCycle
; i
++) {
137 if (i
!= lastCycle
) {
138 bb
= fc
.map(MapMode
.READ_ONLY
, position
, bufferSize
);
139 position
= position
+ bufferSize
;
141 bb
= fc
.map(MapMode
.READ_ONLY
, position
, fileSize
- position
);
147 long end
= System
.currentTimeMillis();
149 System
.out
.println((end
- begin
) + " ms / " + ((end
- begin
) / 1000) + " s");
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
);
158 public static void main(String
[] args
) {
161 file
= new File(args
[0]);
163 System
.err
.println("Usage: <file> [<algorithm>]" + " (see http://java.sun.com/j2se/1.5.0/"
164 + "docs/guide/security/CryptoSpec.html#AppA)");
168 if (args
.length
> 1) {
169 String algorithm
= args
[1];
170 System
.out
.println(digest(algorithm
, file
));
172 String algorithm
= "MD5";
173 System
.out
.println(algorithm
+ ": " + digest(algorithm
, file
));
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
));
184 final private static char[] hexArray
= "0123456789abcdef".toCharArray();
188 * http://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to
189 * -a-hex-string-in-java
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];
198 return new String(hexChars
);