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