1 package org
.argeo
.util
;
3 import static org
.argeo
.util
.BytesUtils
.toHexString
;
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
;
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";
24 private static Boolean debug
= false;
25 // TODO: make it configurable
26 private final static Integer byteBufferCapacity
= 100 * 1024;// 100 KB
28 public static byte[] sha1(byte[]... bytes
) {
30 MessageDigest digest
= MessageDigest
.getInstance(SHA1
);
31 for (byte[] arr
: bytes
)
33 byte[] checksum
= digest
.digest();
35 } catch (NoSuchAlgorithmException e
) {
36 throw new UnsupportedOperationException("SHA1 is not avalaible", e
);
40 public static byte[] digestAsBytes(String algorithm
, byte[]... bytes
) {
42 MessageDigest digest
= MessageDigest
.getInstance(algorithm
);
43 for (byte[] arr
: bytes
)
45 byte[] checksum
= digest
.digest();
47 } catch (NoSuchAlgorithmException e
) {
48 throw new UnsupportedOperationException("Cannot digest with algorithm " + algorithm
, e
);
52 public static String
digest(String algorithm
, byte[]... bytes
) {
53 return toHexString(digestAsBytes(algorithm
, bytes
));
56 public static String
digest(String algorithm
, InputStream in
) {
58 MessageDigest digest
= MessageDigest
.getInstance(algorithm
);
59 // ReadableByteChannel channel = Channels.newChannel(in);
60 // ByteBuffer bb = ByteBuffer.allocateDirect(byteBufferCapacity);
61 // while (channel.read(bb) > 0)
63 byte[] buffer
= new byte[byteBufferCapacity
];
65 while ((read
= in
.read(buffer
)) > 0) {
66 digest
.update(buffer
, 0, read
);
69 byte[] checksum
= digest
.digest();
70 String res
= toHexString(checksum
);
72 } catch (NoSuchAlgorithmException e
) {
73 throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm
, e
);
74 } catch (IOException e
) {
75 throw new RuntimeException(e
);
77 StreamUtils
.closeQuietly(in
);
81 public static String
digest(String algorithm
, File file
) {
82 FileInputStream fis
= null;
83 FileChannel fc
= null;
85 fis
= new FileInputStream(file
);
86 fc
= fis
.getChannel();
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
);
95 StreamUtils
.closeQuietly(fis
);
99 } catch (IOException e
) {
105 protected static String
digest(String algorithm
, ByteBuffer bb
) {
106 long begin
= System
.currentTimeMillis();
108 MessageDigest digest
= MessageDigest
.getInstance(algorithm
);
110 byte[] checksum
= digest
.digest();
111 String res
= toHexString(checksum
);
112 long end
= System
.currentTimeMillis();
114 System
.out
.println((end
- begin
) + " ms / " + ((end
- begin
) / 1000) + " s");
116 } catch (NoSuchAlgorithmException e
) {
117 throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm
, e
);
121 public static String
sha1hex(Path path
) {
122 return digest(SHA1
, path
, byteBufferCapacity
);
125 public static String
digest(String algorithm
, Path path
, long bufferSize
) {
126 byte[] digest
= digestAsBytes(algorithm
, path
, bufferSize
);
127 return toHexString(digest
);
130 public static byte[] digestAsBytes(String algorithm
, Path file
, long bufferSize
) {
131 long begin
= System
.currentTimeMillis();
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
);
140 long lastCycle
= (fileSize
/ bufferSize
) - 1;
142 for (int i
= 0; i
<= lastCycle
; i
++) {
144 if (i
!= lastCycle
) {
145 bb
= fc
.map(MapMode
.READ_ONLY
, position
, bufferSize
);
146 position
= position
+ bufferSize
;
148 bb
= fc
.map(MapMode
.READ_ONLY
, position
, fileSize
- position
);
154 long end
= System
.currentTimeMillis();
156 System
.out
.println((end
- begin
) + " ms / " + ((end
- begin
) / 1000) + " s");
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
);
165 public static void main(String
[] args
) {
168 file
= new File(args
[0]);
170 System
.err
.println("Usage: <file> [<algorithm>]" + " (see http://java.sun.com/j2se/1.5.0/"
171 + "docs/guide/security/CryptoSpec.html#AppA)");
175 if (args
.length
> 1) {
176 String algorithm
= args
[1];
177 System
.out
.println(digest(algorithm
, file
));
179 String algorithm
= "MD5";
180 System
.out
.println(algorithm
+ ": " + digest(algorithm
, file
));
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
));
191 /** @deprecated Use {@link BytesUtils#toHexString(byte[])} instead */
193 public static String
encodeHexString(byte[] bytes
) {
194 return BytesUtils
.toHexString(bytes
);