001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.codec.digest;
019
020 import java.io.IOException;
021 import java.io.InputStream;
022 import java.security.MessageDigest;
023 import java.security.NoSuchAlgorithmException;
024
025 import org.apache.commons.codec.binary.Hex;
026 import org.apache.commons.codec.binary.StringUtils;
027
028 /**
029 * Operations to simplifiy common {@link java.security.MessageDigest} tasks. This class is thread safe.
030 *
031 * @author Apache Software Foundation
032 * @version $Id: DigestUtils.java 801391 2009-08-05 19:55:54Z ggregory $
033 */
034 public class DigestUtils {
035
036 private static final int STREAM_BUFFER_LENGTH = 1024;
037
038 /**
039 * Read through an InputStream and returns the digest for the data
040 *
041 * @param digest
042 * The MessageDigest to use (e.g. MD5)
043 * @param data
044 * Data to digest
045 * @return MD5 digest
046 * @throws IOException
047 * On error reading from the stream
048 */
049 private static byte[] digest(MessageDigest digest, InputStream data) throws IOException {
050 byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
051 int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
052
053 while (read > -1) {
054 digest.update(buffer, 0, read);
055 read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
056 }
057
058 return digest.digest();
059 }
060
061 /**
062 * Calls {@link StringUtils#getBytesUtf8(String)}
063 *
064 * @param string
065 * the String to encode
066 * @return encoded bytes
067 */
068 private static byte[] getBytesUtf8(String data) {
069 return StringUtils.getBytesUtf8(data);
070 }
071
072 /**
073 * Returns a <code>MessageDigest</code> for the given <code>algorithm</code>.
074 *
075 * @param algorithm
076 * the name of the algorithm requested. See <a
077 * href="http://java.sun.com/j2se/1.3/docs/guide/security/CryptoSpec.html#AppA">Appendix A in the Java
078 * Cryptography Architecture API Specification & Reference</a> for information about standard algorithm
079 * names.
080 * @return An MD5 digest instance.
081 * @see MessageDigest#getInstance(String)
082 * @throws RuntimeException
083 * when a {@link java.security.NoSuchAlgorithmException} is caught.
084 */
085 static MessageDigest getDigest(String algorithm) {
086 try {
087 return MessageDigest.getInstance(algorithm);
088 } catch (NoSuchAlgorithmException e) {
089 throw new RuntimeException(e.getMessage());
090 }
091 }
092
093 /**
094 * Returns an MD5 MessageDigest.
095 *
096 * @return An MD5 digest instance.
097 * @throws RuntimeException
098 * when a {@link java.security.NoSuchAlgorithmException} is caught.
099 */
100 private static MessageDigest getMd5Digest() {
101 return getDigest("MD5");
102 }
103
104 /**
105 * Returns an SHA-256 digest.
106 * <p>
107 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
108 * </p>
109 *
110 * @return An SHA-256 digest instance.
111 * @throws RuntimeException
112 * when a {@link java.security.NoSuchAlgorithmException} is caught.
113 */
114 private static MessageDigest getSha256Digest() {
115 return getDigest("SHA-256");
116 }
117
118 /**
119 * Returns an SHA-384 digest.
120 * <p>
121 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
122 * </p>
123 *
124 * @return An SHA-384 digest instance.
125 * @throws RuntimeException
126 * when a {@link java.security.NoSuchAlgorithmException} is caught.
127 */
128 private static MessageDigest getSha384Digest() {
129 return getDigest("SHA-384");
130 }
131
132 /**
133 * Returns an SHA-512 digest.
134 * <p>
135 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
136 * </p>
137 *
138 * @return An SHA-512 digest instance.
139 * @throws RuntimeException
140 * when a {@link java.security.NoSuchAlgorithmException} is caught.
141 */
142 private static MessageDigest getSha512Digest() {
143 return getDigest("SHA-512");
144 }
145
146 /**
147 * Returns an SHA-1 digest.
148 *
149 * @return An SHA-1 digest instance.
150 * @throws RuntimeException
151 * when a {@link java.security.NoSuchAlgorithmException} is caught.
152 */
153 private static MessageDigest getShaDigest() {
154 return getDigest("SHA");
155 }
156
157 /**
158 * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
159 *
160 * @param data
161 * Data to digest
162 * @return MD5 digest
163 */
164 public static byte[] md5(byte[] data) {
165 return getMd5Digest().digest(data);
166 }
167
168 /**
169 * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
170 *
171 * @param data
172 * Data to digest
173 * @return MD5 digest
174 * @throws IOException
175 * On error reading from the stream
176 * @since 1.4
177 */
178 public static byte[] md5(InputStream data) throws IOException {
179 return digest(getMd5Digest(), data);
180 }
181
182 /**
183 * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
184 *
185 * @param data
186 * Data to digest
187 * @return MD5 digest
188 */
189 public static byte[] md5(String data) {
190 return md5(getBytesUtf8(data));
191 }
192
193 /**
194 * Calculates the MD5 digest and returns the value as a 32 character hex string.
195 *
196 * @param data
197 * Data to digest
198 * @return MD5 digest as a hex string
199 */
200 public static String md5Hex(byte[] data) {
201 return Hex.encodeHexString(md5(data));
202 }
203
204 /**
205 * Calculates the MD5 digest and returns the value as a 32 character hex string.
206 *
207 * @param data
208 * Data to digest
209 * @return MD5 digest as a hex string
210 * @throws IOException
211 * On error reading from the stream
212 * @since 1.4
213 */
214 public static String md5Hex(InputStream data) throws IOException {
215 return Hex.encodeHexString(md5(data));
216 }
217
218 /**
219 * Calculates the MD5 digest and returns the value as a 32 character hex string.
220 *
221 * @param data
222 * Data to digest
223 * @return MD5 digest as a hex string
224 */
225 public static String md5Hex(String data) {
226 return Hex.encodeHexString(md5(data));
227 }
228
229 /**
230 * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
231 *
232 * @param data
233 * Data to digest
234 * @return SHA-1 digest
235 */
236 public static byte[] sha(byte[] data) {
237 return getShaDigest().digest(data);
238 }
239
240 /**
241 * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
242 *
243 * @param data
244 * Data to digest
245 * @return SHA-1 digest
246 * @throws IOException
247 * On error reading from the stream
248 * @since 1.4
249 */
250 public static byte[] sha(InputStream data) throws IOException {
251 return digest(getShaDigest(), data);
252 }
253
254 /**
255 * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
256 *
257 * @param data
258 * Data to digest
259 * @return SHA-1 digest
260 */
261 public static byte[] sha(String data) {
262 return sha(getBytesUtf8(data));
263 }
264
265 /**
266 * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
267 * <p>
268 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
269 * </p>
270 *
271 * @param data
272 * Data to digest
273 * @return SHA-256 digest
274 * @since 1.4
275 */
276 public static byte[] sha256(byte[] data) {
277 return getSha256Digest().digest(data);
278 }
279
280 /**
281 * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
282 * <p>
283 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
284 * </p>
285 *
286 * @param data
287 * Data to digest
288 * @return SHA-256 digest
289 * @throws IOException
290 * On error reading from the stream
291 * @since 1.4
292 */
293 public static byte[] sha256(InputStream data) throws IOException {
294 return digest(getSha256Digest(), data);
295 }
296
297 /**
298 * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
299 * <p>
300 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
301 * </p>
302 *
303 * @param data
304 * Data to digest
305 * @return SHA-256 digest
306 * @since 1.4
307 */
308 public static byte[] sha256(String data) {
309 return sha256(getBytesUtf8(data));
310 }
311
312 /**
313 * Calculates the SHA-256 digest and returns the value as a hex string.
314 * <p>
315 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
316 * </p>
317 *
318 * @param data
319 * Data to digest
320 * @return SHA-256 digest as a hex string
321 * @since 1.4
322 */
323 public static String sha256Hex(byte[] data) {
324 return Hex.encodeHexString(sha256(data));
325 }
326
327 /**
328 * Calculates the SHA-256 digest and returns the value as a hex string.
329 * <p>
330 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
331 * </p>
332 *
333 * @param data
334 * Data to digest
335 * @return SHA-256 digest as a hex string
336 * @throws IOException
337 * On error reading from the stream
338 * @since 1.4
339 */
340 public static String sha256Hex(InputStream data) throws IOException {
341 return Hex.encodeHexString(sha256(data));
342 }
343
344 /**
345 * Calculates the SHA-256 digest and returns the value as a hex string.
346 * <p>
347 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
348 * </p>
349 *
350 * @param data
351 * Data to digest
352 * @return SHA-256 digest as a hex string
353 * @since 1.4
354 */
355 public static String sha256Hex(String data) {
356 return Hex.encodeHexString(sha256(data));
357 }
358
359 /**
360 * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
361 * <p>
362 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
363 * </p>
364 *
365 * @param data
366 * Data to digest
367 * @return SHA-384 digest
368 * @since 1.4
369 */
370 public static byte[] sha384(byte[] data) {
371 return getSha384Digest().digest(data);
372 }
373
374 /**
375 * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
376 * <p>
377 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
378 * </p>
379 *
380 * @param data
381 * Data to digest
382 * @return SHA-384 digest
383 * @throws IOException
384 * On error reading from the stream
385 * @since 1.4
386 */
387 public static byte[] sha384(InputStream data) throws IOException {
388 return digest(getSha384Digest(), data);
389 }
390
391 /**
392 * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
393 * <p>
394 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
395 * </p>
396 *
397 * @param data
398 * Data to digest
399 * @return SHA-384 digest
400 * @since 1.4
401 */
402 public static byte[] sha384(String data) {
403 return sha384(getBytesUtf8(data));
404 }
405
406 /**
407 * Calculates the SHA-384 digest and returns the value as a hex string.
408 * <p>
409 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
410 * </p>
411 *
412 * @param data
413 * Data to digest
414 * @return SHA-384 digest as a hex string
415 * @since 1.4
416 */
417 public static String sha384Hex(byte[] data) {
418 return Hex.encodeHexString(sha384(data));
419 }
420
421 /**
422 * Calculates the SHA-384 digest and returns the value as a hex string.
423 * <p>
424 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
425 * </p>
426 *
427 * @param data
428 * Data to digest
429 * @return SHA-384 digest as a hex string
430 * @throws IOException
431 * On error reading from the stream
432 * @since 1.4
433 */
434 public static String sha384Hex(InputStream data) throws IOException {
435 return Hex.encodeHexString(sha384(data));
436 }
437
438 /**
439 * Calculates the SHA-384 digest and returns the value as a hex string.
440 * <p>
441 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
442 * </p>
443 *
444 * @param data
445 * Data to digest
446 * @return SHA-384 digest as a hex string
447 * @since 1.4
448 */
449 public static String sha384Hex(String data) {
450 return Hex.encodeHexString(sha384(data));
451 }
452
453 /**
454 * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
455 * <p>
456 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
457 * </p>
458 *
459 * @param data
460 * Data to digest
461 * @return SHA-512 digest
462 * @since 1.4
463 */
464 public static byte[] sha512(byte[] data) {
465 return getSha512Digest().digest(data);
466 }
467
468 /**
469 * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
470 * <p>
471 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
472 * </p>
473 *
474 * @param data
475 * Data to digest
476 * @return SHA-512 digest
477 * @throws IOException
478 * On error reading from the stream
479 * @since 1.4
480 */
481 public static byte[] sha512(InputStream data) throws IOException {
482 return digest(getSha512Digest(), data);
483 }
484
485 /**
486 * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
487 * <p>
488 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
489 * </p>
490 *
491 * @param data
492 * Data to digest
493 * @return SHA-512 digest
494 * @since 1.4
495 */
496 public static byte[] sha512(String data) {
497 return sha512(getBytesUtf8(data));
498 }
499
500 /**
501 * Calculates the SHA-512 digest and returns the value as a hex string.
502 * <p>
503 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
504 * </p>
505 *
506 * @param data
507 * Data to digest
508 * @return SHA-512 digest as a hex string
509 * @since 1.4
510 */
511 public static String sha512Hex(byte[] data) {
512 return Hex.encodeHexString(sha512(data));
513 }
514
515 /**
516 * Calculates the SHA-512 digest and returns the value as a hex string.
517 * <p>
518 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
519 * </p>
520 *
521 * @param data
522 * Data to digest
523 * @return SHA-512 digest as a hex string
524 * @throws IOException
525 * On error reading from the stream
526 * @since 1.4
527 */
528 public static String sha512Hex(InputStream data) throws IOException {
529 return Hex.encodeHexString(sha512(data));
530 }
531
532 /**
533 * Calculates the SHA-512 digest and returns the value as a hex string.
534 * <p>
535 * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
536 * </p>
537 *
538 * @param data
539 * Data to digest
540 * @return SHA-512 digest as a hex string
541 * @since 1.4
542 */
543 public static String sha512Hex(String data) {
544 return Hex.encodeHexString(sha512(data));
545 }
546
547 /**
548 * Calculates the SHA-1 digest and returns the value as a hex string.
549 *
550 * @param data
551 * Data to digest
552 * @return SHA-1 digest as a hex string
553 */
554 public static String shaHex(byte[] data) {
555 return Hex.encodeHexString(sha(data));
556 }
557
558 /**
559 * Calculates the SHA-1 digest and returns the value as a hex string.
560 *
561 * @param data
562 * Data to digest
563 * @return SHA-1 digest as a hex string
564 * @throws IOException
565 * On error reading from the stream
566 * @since 1.4
567 */
568 public static String shaHex(InputStream data) throws IOException {
569 return Hex.encodeHexString(sha(data));
570 }
571
572 /**
573 * Calculates the SHA-1 digest and returns the value as a hex string.
574 *
575 * @param data
576 * Data to digest
577 * @return SHA-1 digest as a hex string
578 */
579 public static String shaHex(String data) {
580 return Hex.encodeHexString(sha(data));
581 }
582 }