]> git.argeo.org Git - lgpl/argeo-commons.git/blob - util/DigestUtils.java
Prepare next development cycle
[lgpl/argeo-commons.git] / util / DigestUtils.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.util;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.nio.ByteBuffer;
23 import java.nio.channels.FileChannel;
24 import java.nio.channels.FileChannel.MapMode;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.security.MessageDigest;
28 import java.security.NoSuchAlgorithmException;
29
30 /** Utilities around cryptographic digests */
31 public class DigestUtils {
32 private static Boolean debug = false;
33 // TODO: make it writable
34 private final static Integer byteBufferCapacity = 100 * 1024;// 100 KB
35
36 public static String digest(String algorithm, byte[] bytes) {
37 try {
38 MessageDigest digest = MessageDigest.getInstance(algorithm);
39 digest.update(bytes);
40 byte[] checksum = digest.digest();
41 String res = encodeHexString(checksum);
42 return res;
43 } catch (Exception e) {
44 throw new UtilsException("Cannot digest with algorithm " + algorithm, e);
45 }
46 }
47
48 public static String digest(String algorithm, InputStream in) {
49 try {
50 MessageDigest digest = MessageDigest.getInstance(algorithm);
51 // ReadableByteChannel channel = Channels.newChannel(in);
52 // ByteBuffer bb = ByteBuffer.allocateDirect(byteBufferCapacity);
53 // while (channel.read(bb) > 0)
54 // digest.update(bb);
55 byte[] buffer = new byte[byteBufferCapacity];
56 int read = 0;
57 while ((read = in.read(buffer)) > 0) {
58 digest.update(buffer, 0, read);
59 }
60
61 byte[] checksum = digest.digest();
62 String res = encodeHexString(checksum);
63 return res;
64 } catch (Exception e) {
65 throw new UtilsException("Cannot digest with algorithm " + algorithm, e);
66 } finally {
67 StreamUtils.closeQuietly(in);
68 }
69 }
70
71 public static String digest(String algorithm, File file) {
72 FileInputStream fis = null;
73 FileChannel fc = null;
74 try {
75 fis = new FileInputStream(file);
76 fc = fis.getChannel();
77
78 // Get the file's size and then map it into memory
79 int sz = (int) fc.size();
80 ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz);
81 return digest(algorithm, bb);
82 } catch (IOException e) {
83 throw new UtilsException("Cannot digest " + file + " with algorithm " + algorithm, e);
84 } finally {
85 StreamUtils.closeQuietly(fis);
86 if (fc.isOpen())
87 try {
88 fc.close();
89 } catch (IOException e) {
90 // silent
91 }
92 }
93 }
94
95 protected static String digest(String algorithm, ByteBuffer bb) {
96 long begin = System.currentTimeMillis();
97 try {
98 MessageDigest digest = MessageDigest.getInstance(algorithm);
99 digest.update(bb);
100 byte[] checksum = digest.digest();
101 String res = encodeHexString(checksum);
102 long end = System.currentTimeMillis();
103 if (debug)
104 System.out.println((end - begin) + " ms / " + ((end - begin) / 1000) + " s");
105 return res;
106 } catch (NoSuchAlgorithmException e) {
107 throw new UtilsException("Cannot digest with algorithm " + algorithm, e);
108 }
109 }
110
111 public static byte[] digestRaw(String algorithm, Path file, long bufferSize) {
112 long begin = System.currentTimeMillis();
113 try {
114 MessageDigest md = MessageDigest.getInstance(algorithm);
115 FileChannel fc = FileChannel.open(file);
116 long fileSize = Files.size(file);
117 if (fileSize <= bufferSize) {
118 ByteBuffer bb = fc.map(MapMode.READ_ONLY, 0, fileSize);
119 md.update(bb);
120 } else {
121 long lastCycle = (fileSize / bufferSize) - 1;
122 long position = 0;
123 for (int i = 0; i <= lastCycle; i++) {
124 ByteBuffer bb;
125 if (i != lastCycle) {
126 bb = fc.map(MapMode.READ_ONLY, position, bufferSize);
127 position = position + bufferSize;
128 } else {
129 bb = fc.map(MapMode.READ_ONLY, position, fileSize - bufferSize);
130 position = fileSize;
131 }
132 md.update(bb);
133 }
134 }
135 long end = System.currentTimeMillis();
136 if (debug)
137 System.out.println((end - begin) + " ms / " + ((end - begin) / 1000) + " s");
138 return md.digest();
139 } catch (Exception e) {
140 throw new UtilsException("Cannot digest " + file + " with algorithm " + algorithm, e);
141 }
142 }
143
144 public static void main(String[] args) {
145 File file;
146 if (args.length > 0)
147 file = new File(args[0]);
148 else {
149 System.err.println("Usage: <file> [<algorithm>]" + " (see http://java.sun.com/j2se/1.5.0/"
150 + "docs/guide/security/CryptoSpec.html#AppA)");
151 return;
152 }
153
154 if (args.length > 1) {
155 String algorithm = args[1];
156 System.out.println(digest(algorithm, file));
157 } else {
158 String algorithm = "MD5";
159 System.out.println(algorithm + ": " + digest(algorithm, file));
160 algorithm = "SHA";
161 System.out.println(algorithm + ": " + digest(algorithm, file));
162 algorithm = "SHA-256";
163 System.out.println(algorithm + ": " + digest(algorithm, file));
164 algorithm = "SHA-512";
165 System.out.println(algorithm + ": " + digest(algorithm, file));
166 }
167 }
168
169 final private static char[] hexArray = "0123456789abcdef".toCharArray();
170
171 /**
172 * From
173 * http://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to
174 * -a-hex-string-in-java
175 */
176 public static String encodeHexString(byte[] bytes) {
177 char[] hexChars = new char[bytes.length * 2];
178 for (int j = 0; j < bytes.length; j++) {
179 int v = bytes[j] & 0xFF;
180 hexChars[j * 2] = hexArray[v >>> 4];
181 hexChars[j * 2 + 1] = hexArray[v & 0x0F];
182 }
183 return new String(hexChars);
184 }
185
186 }