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    *      https://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 java.nio.charset.StandardCharsets;
20  import java.security.SecureRandom;
21  
22  /**
23   * GNU libc crypt(3) compatible hash method.
24   * <p>
25   * See {@link #crypt(String, String)} for further details.
26   * </p>
27   * <p>
28   * This class is immutable and thread-safe.
29   * </p>
30   *
31   * @since 1.7
32   */
33  public class Crypt {
34  
35      /**
36       * Encrypts a password in a crypt(3) compatible way.
37       * <p>
38       * A random salt and the default algorithm (currently SHA-512) are used. See {@link #crypt(String, String)} for
39       * details.
40       * </p>
41       * <p>
42       * A salt is generated for you using {@link SecureRandom}.
43       * </p>
44       *
45       * @param keyBytes
46       *            plaintext password
47       * @return hash value
48       * @throws IllegalArgumentException
49       *             when a {@link java.security.NoSuchAlgorithmException} is caught.
50       */
51      public static String crypt(final byte[] keyBytes) {
52          return crypt(keyBytes, null);
53      }
54  
55      /**
56       * Encrypts a password in a crypt(3) compatible way.
57       * <p>
58       * If no salt is provided, a random salt and the default algorithm (currently SHA-512) will be used. See
59       * {@link #crypt(String, String)} for details.
60       * </p>
61       *
62       * @param keyBytes
63       *            plaintext password
64       * @param salt
65       *            the salt, which is used to select the algorithm, see {@link #crypt(String, String)}
66       *            The salt may be null,
67       *            in which case the method delegates to {@link Sha2Crypt#sha512Crypt(byte[])}
68       *
69       * @return hash value
70       * @throws IllegalArgumentException
71       *             if the salt does not match the allowed pattern
72       * @throws IllegalArgumentException
73       *             when a {@link java.security.NoSuchAlgorithmException} is caught.
74       */
75      public static String crypt(final byte[] keyBytes, final String salt) {
76          if (salt == null) {
77              return Sha2Crypt.sha512Crypt(keyBytes);
78          }
79          if (salt.startsWith(Sha2Crypt.SHA512_PREFIX)) {
80              return Sha2Crypt.sha512Crypt(keyBytes, salt);
81          }
82          if (salt.startsWith(Sha2Crypt.SHA256_PREFIX)) {
83              return Sha2Crypt.sha256Crypt(keyBytes, salt);
84          }
85          if (salt.startsWith(Md5Crypt.MD5_PREFIX)) {
86              return Md5Crypt.md5Crypt(keyBytes, salt);
87          }
88          return UnixCrypt.crypt(keyBytes, salt);
89      }
90  
91      /**
92       * Calculates the digest using the strongest crypt(3) algorithm.
93       * <p>
94       * A random salt and the default algorithm (currently SHA-512) are used.
95       * </p>
96       * <p>
97       * A salt is generated for you using {@link SecureRandom}.
98       * </p>
99       *
100      * @see #crypt(String, String)
101      * @param key
102      *            plaintext password
103      * @return hash value
104      * @throws IllegalArgumentException
105      *             when a {@link java.security.NoSuchAlgorithmException} is caught.
106      */
107     public static String crypt(final String key) {
108         return crypt(key, null);
109     }
110 
111     /**
112      * Encrypts a password in a crypt(3) compatible way.
113      * <p>
114      * The exact algorithm depends on the format of the salt string:
115      * </p>
116      * <ul>
117      * <li>SHA-512 salts start with {@code $6$} and are up to 16 chars long.
118      * <li>SHA-256 salts start with {@code $5$} and are up to 16 chars long
119      * <li>MD5 salts start with {@code $1$} and are up to 8 chars long
120      * <li>DES, the traditional UnixCrypt algorithm is used with only 2 chars
121      * <li>Only the first 8 chars of the passwords are used in the DES algorithm!
122      * </ul>
123      * <p>
124      * The magic strings {@code "$apr1$"} and {@code "$2a$"} are not recognized by this method as its output should be
125      * identical with that of the libc implementation.
126      * </p>
127      * <p>
128      * The rest of the salt string is drawn from the set {@code [a-zA-Z0-9./]} and is cut at the maximum length or if a
129      * {@code "$"} sign is encountered. It is therefore valid to enter a complete hash value as salt to e.g. verify a
130      * password with:
131      * </p>
132      * <pre>
133      * storedPwd.equals(crypt(enteredPwd, storedPwd))
134      * </pre>
135      * <p>
136      * The resulting string starts with the marker string ({@code $n$}), where n is the same as the input salt.
137      * The salt is then appended, followed by a {@code "$"} sign.
138      * This is followed by the actual hash value.
139      * For DES the string only contains the salt and actual hash.
140      * The total length is dependent on the algorithm used:
141      * </p>
142      * <ul>
143      * <li>SHA-512: 106 chars
144      * <li>SHA-256: 63 chars
145      * <li>MD5: 34 chars
146      * <li>DES: 13 chars
147      * </ul>
148      * <p>
149      * Example:
150      * </p>
151      * <pre>
152      *      crypt("secret", "$1$xxxx") =&gt; "$1$xxxx$aMkevjfEIpa35Bh3G4bAc."
153      *      crypt("secret", "xx") =&gt; "xxWAum7tHdIUw"
154      * </pre>
155      * <p>
156      * This method comes in a variation that accepts a byte[] array to support input strings that are not encoded in
157      * UTF-8 but e.g. in ISO-8859-1 where equal characters result in different byte values.
158      * </p>
159      *
160      * @see "The man page of the libc crypt (3) function."
161      * @param key
162      *            plaintext password as entered by the used
163      * @param salt
164      *            real salt value without prefix or "rounds=". The salt may be null, in which case a
165      *            salt is generated for you using {@link SecureRandom}
166      * @return hash value, i.e. encrypted password including the salt string
167      * @throws IllegalArgumentException
168      *             if the salt does not match the allowed pattern
169      * @throws IllegalArgumentException
170      *             when a {@link java.security.NoSuchAlgorithmException} is caught. *
171      */
172     public static String crypt(final String key, final String salt) {
173         return crypt(key.getBytes(StandardCharsets.UTF_8), salt);
174     }
175 
176     /**
177      * TODO Make private in 2.0.
178      *
179      * @deprecated TODO Make private in 2.0.
180      */
181     @Deprecated
182     public Crypt() {
183         // empty
184     }
185 }