1717package org .apache .commons .codec .digest ;
1818
1919import java .security .MessageDigest ;
20+ import java .security .NoSuchAlgorithmException ;
2021import java .util .Arrays ;
2122import java .util .regex .Matcher ;
2223import java .util .regex .Pattern ;
2728 * The libc crypt() "$1$" and Apache "$apr1$" MD5-based hash algorithm.
2829 * <p>
2930 * Based on the public domain ("beer-ware") C implementation from Poul-Henning Kamp which was found at:
30- * </p>
31+ * <a href="http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libcrypt/crypt-md5.c?rev=1.1;content-type=text%2Fplain">
32+ * crypt-md5.c @ freebsd.org</a><br/>
3133 * <p>
32- * http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libcrypt/crypt-md5.c?rev=1.1;content-type=text%2Fplain<br/>
33- * Source: $FreeBSD: src/lib/libcrypt/crypt-md5.c,v 1.1 1999/01/21 13:50:09 brandon Exp $
34- * </ p>
35- * <p> Conversion to Kotlin and from there to Java in 2012.</p>
36- *
37- * <p> The C style comments are from the original C code, the ones with "//" from the port.</p>
38- *
39- * <p> This class is immutable and thread-safe.</p>
34+ * Source:
35+ * <pre> $FreeBSD: src/lib/libcrypt/crypt-md5.c,v 1.1 1999/01/21 13:50:09 brandon Exp $</pre>
36+ * <p>
37+ * Conversion to Kotlin and from there to Java in 2012.
38+ * <p>
39+ * The C style comments are from the original C code, the ones with "//" from the port.
40+ * <p>
41+ * This class is immutable and thread-safe.
4042 *
4143 * @version $Id$
4244 * @since 1.7
4345 */
4446public class Md5Crypt {
4547
46- /**
47- * The Identifier of the Apache variant.
48- */
48+ /** The Identifier of the Apache variant. */
4949 static final String APR1_PREFIX = "$apr1$" ;
5050
51- /**
52- * The number of bytes of the final hash.
53- */
51+ /** The number of bytes of the final hash. */
5452 private static final int BLOCKSIZE = 16 ;
5553
56- /**
57- * The MessageDigest MD5_ALGORITHM.
58- */
54+ /** The MessageDigest MD5_ALGORITHM. */
5955 private static final String MD5_ALGORITHM = "MD5" ;
6056
61- /**
62- * The Identifier of this crypt() variant.
63- */
57+ /** The Identifier of this crypt() variant. */
6458 static final String MD5_PREFIX = "$1$" ;
6559
66- /**
67- * The number of rounds of the big loop.
68- */
60+ /** The number of rounds of the big loop. */
6961 private static final int ROUNDS = 1000 ;
7062
71- /** See {@link #apr1Crypt(String, String)} for details. */
72- public static String apr1Crypt (byte [] keyBytes ) throws Exception {
63+ /**
64+ * See {@link #apr1Crypt(String, String)} for details.
65+ *
66+ * @throws NoSuchAlgorithmException if no "MD5" algorithm implementation is available
67+ */
68+ public static String apr1Crypt (byte [] keyBytes ) throws NoSuchAlgorithmException {
7369 return apr1Crypt (keyBytes , APR1_PREFIX + B64 .getRandomSalt (8 ));
7470 }
7571
76- /** See {@link #apr1Crypt(String, String)} for details. */
77- public static String apr1Crypt (byte [] keyBytes , String salt ) throws Exception {
72+ /**
73+ * See {@link #apr1Crypt(String, String)} for details.
74+ *
75+ * @throws IllegalArgumentException if the salt does not match the allowed pattern
76+ * @throws NoSuchAlgorithmException if no "MD5" algorithm implementation is available
77+ */
78+ public static String apr1Crypt (byte [] keyBytes , String salt ) throws NoSuchAlgorithmException {
7879 // to make the md5Crypt regex happy
7980 if (salt != null && !salt .startsWith (APR1_PREFIX )) {
8081 salt = APR1_PREFIX + salt ;
8182 }
8283 return Md5Crypt .md5Crypt (keyBytes , salt , APR1_PREFIX );
8384 }
8485
85- /** See {@link #apr1Crypt(String, String)} for details. */
86- public static String apr1Crypt (String keyBytes ) throws Exception {
86+ /**
87+ * See {@link #apr1Crypt(String, String)} for details.
88+ *
89+ * @throws NoSuchAlgorithmException if no "MD5" algorithm implementation is available
90+ */
91+ public static String apr1Crypt (String keyBytes ) throws NoSuchAlgorithmException {
8792 return apr1Crypt (keyBytes .getBytes (Charsets .UTF_8 ));
8893 }
8994
@@ -99,17 +104,21 @@ public static String apr1Crypt(String keyBytes) throws Exception {
99104 * salt string including the prefix and optionally garbage at the end.
100105 * Will be generated randomly if null.
101106 * @return computed hash value
107+ * @throws IllegalArgumentException if the salt does not match the allowed pattern
108+ * @throws NoSuchAlgorithmException if no "MD5" algorithm implementation is available
102109 */
103- public static String apr1Crypt (String keyBytes , String salt ) throws Exception {
110+ public static String apr1Crypt (String keyBytes , String salt ) throws NoSuchAlgorithmException {
104111 return apr1Crypt (keyBytes .getBytes (Charsets .UTF_8 ), salt );
105112 }
106113
107114 /**
108115 * Generates a libc6 crypt() compatible "$1$" hash value.
109116 * <p>
110117 * See {@link Crypt#crypt(String, String)} for details.
118+ *
119+ * @throws NoSuchAlgorithmException if no "MD5" algorithm implementation is available
111120 */
112- public static String md5Crypt (final byte [] keyBytes ) throws Exception {
121+ public static String md5Crypt (final byte [] keyBytes ) throws NoSuchAlgorithmException {
113122 return md5Crypt (keyBytes , MD5_PREFIX + B64 .getRandomSalt (8 ));
114123 }
115124
@@ -124,26 +133,32 @@ public static String md5Crypt(final byte[] keyBytes) throws Exception {
124133 * salt string including the prefix and optionally garbage at the end.
125134 * Will be generated randomly if null.
126135 * @return computed hash value
136+ * @throws IllegalArgumentException if the salt does not match the allowed pattern
137+ * @throws NoSuchAlgorithmException if no "MD5" algorithm implementation is available
127138 */
128- public static String md5Crypt (byte [] keyBytes , String salt ) throws Exception {
139+ public static String md5Crypt (byte [] keyBytes , String salt ) throws NoSuchAlgorithmException {
129140 return md5Crypt (keyBytes , salt , MD5_PREFIX );
130141 }
131142
132143 /**
133144 * Generates a libc6 crypt() "$1$" or Apache htpasswd "$apr1$" hash value.
134145 * <p>
135146 * See {@link Crypt#crypt(String, String)} or {@link #apr1Crypt(String, String)} for details.
147+ *
148+ * @throws IllegalArgumentException if the salt does not match the allowed pattern
149+ * @throws NoSuchAlgorithmException if no "MD5" algorithm implementation is available
136150 */
137- public static String md5Crypt (final byte [] keyBytes , final String salt , final String prefix ) throws Exception {
151+ public static String md5Crypt (final byte [] keyBytes , final String salt , final String prefix )
152+ throws NoSuchAlgorithmException {
138153 int keyLen = keyBytes .length ;
139154
140155 // Extract the real salt from the given string which can be a complete hash string.
141156 String saltString ;
142157 if (salt == null ) {
143158 saltString = B64 .getRandomSalt (8 );
144159 } else {
145- Pattern p = Pattern .compile ("^" + prefix .replace ("$" , "\\ $" ) + "([\\ .\\ /a-zA-Z0-9]{1,8}).*" );
146- Matcher m = p .matcher (salt );
160+ final Pattern p = Pattern .compile ("^" + prefix .replace ("$" , "\\ $" ) + "([\\ .\\ /a-zA-Z0-9]{1,8}).*" );
161+ final Matcher m = p .matcher (salt );
147162 if (m == null || !m .find ()) {
148163 throw new IllegalArgumentException ("Invalid salt value: " + salt );
149164 }
0 commit comments