View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.codec.digest;
18  
19  import org.apache.commons.codec.Charsets;
20  
21  /**
22   * GNU libc crypt(3) compatible hash method.
23   * <p>
24   * See {@link #crypt(String, String)} for further details.
25   * <p>
26   * This class is immutable and thread-safe.
27   *
28   * @version $Id: Crypt.html 889935 2013-12-11 05:05:13Z ggregory $
29   * @since 1.7
30   */
31  public class Crypt {
32  
33      /**
34       * Encrypts a password in a crypt(3) compatible way.
35       * <p>
36       * A random salt and the default algorithm (currently SHA-512) are used. See {@link #crypt(String, String)} for
37       * details.
38       *
39       * @param keyBytes
40       *            plaintext password
41       * @return hash value
42       * @throws RuntimeException
43       *             when a {@link java.security.NoSuchAlgorithmException} is caught.
44       */
45      public static String crypt(byte[] keyBytes) {
46          return crypt(keyBytes, null);
47      }
48  
49      /**
50       * Encrypts a password in a crypt(3) compatible way.
51       * <p>
52       * If no salt is provided, a random salt and the default algorithm (currently SHA-512) will be used. See
53       * {@link #crypt(String, String)} for details.
54       *
55       * @param keyBytes
56       *            plaintext password
57       * @param salt
58       *            salt value
59       * @return hash value
60       * @throws IllegalArgumentException
61       *             if the salt does not match the allowed pattern
62       * @throws RuntimeException
63       *             when a {@link java.security.NoSuchAlgorithmException} is caught.
64       */
65      public static String crypt(byte[] keyBytes, String salt) {
66          if (salt == null) {
67              return Sha2Crypt.sha512Crypt(keyBytes);
68          } else if (salt.startsWith(Sha2Crypt.SHA512_PREFIX)) {
69              return Sha2Crypt.sha512Crypt(keyBytes, salt);
70          } else if (salt.startsWith(Sha2Crypt.SHA256_PREFIX)) {
71              return Sha2Crypt.sha256Crypt(keyBytes, salt);
72          } else if (salt.startsWith(Md5Crypt.MD5_PREFIX)) {
73              return Md5Crypt.md5Crypt(keyBytes, salt);
74          } else {
75              return UnixCrypt.crypt(keyBytes, salt);
76          }
77      }
78  
79      /**
80       * Calculates the digest using the strongest crypt(3) algorithm.
81       * <p>
82       * A random salt and the default algorithm (currently SHA-512) are used.
83       *
84       * @see #crypt(String, String)
85       * @param key
86       *            plaintext password
87       * @return hash value
88       * @throws RuntimeException
89       *             when a {@link java.security.NoSuchAlgorithmException} is caught.
90       */
91      public static String crypt(String key) {
92          return crypt(key, null);
93      }
94  
95      /**
96       * Encrypts a password in a crypt(3) compatible way.
97       * <p>
98       * The exact algorithm depends on the format of the salt string:
99       * <ul>
100      * <li>SHA-512 salts start with $6$ and are up to 16 chars long.
101      * <li>SHA-256 salts start with $5$ and are up to 16 chars long
102      * <li>MD5 salts start with "$1$" and are up to 8 chars long
103      * <li>DES, the traditional UnixCrypt algorithm is used else with only 2 chars
104      * <li>Only the first 8 chars of the passwords are used in the DES algorithm!
105      * </ul>
106      * The magic strings "$apr1$" and "$2a$" are not recognised by this method as its output should be identical with
107      * that of the libc implementation.
108      * <p>
109      * The rest of the salt string is drawn from the set [a-zA-Z0-9./] and is cut at the maximum length of if a "$"
110      * sign is encountered. It is therefore valid to enter a complete hash value as salt to e.g. verify a password
111      * with:
112      *
113      * <pre>
114      * storedPwd.equals(crypt(enteredPwd, storedPwd))
115      * </pre>
116      * <p>
117      * The resulting string starts with the marker string ($6$), continues with the salt value and ends with a "$" sign
118      * followed by the actual hash value. For DES the string only contains the salt and actual hash. It's total length
119      * is dependent on the algorithm used:
120      * <ul>
121      * <li>SHA-512: 106 chars
122      * <li>SHA-256: 63 chars
123      * <li>MD5: 34 chars
124      * <li>DES: 13 chars
125      * </ul>
126      * <p>
127      * Example:
128      *
129      * <pre>
130      *      crypt("secret", "$1$xxxx") => "$1$xxxx$aMkevjfEIpa35Bh3G4bAc."
131      *      crypt("secret", "xx") => "xxWAum7tHdIUw"
132      * </pre>
133      * <p>
134      * This method comes in a variation that accepts a byte[] array to support input strings that are not encoded in
135      * UTF-8 but e.g. in ISO-8859-1 where equal characters result in different byte values.
136      *
137      * @see "The man page of the libc crypt (3) function."
138      * @param key
139      *            plaintext password as entered by the used
140      * @param salt
141      *            salt value
142      * @return hash value, i.e. encrypted password including the salt string
143      * @throws IllegalArgumentException
144      *             if the salt does not match the allowed pattern
145      * @throws RuntimeException
146      *             when a {@link java.security.NoSuchAlgorithmException} is caught. *
147      */
148     public static String crypt(String key, String salt) {
149         return crypt(key.getBytes(Charsets.UTF_8), salt);
150     }
151 }