    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 *      https://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 */
    017package org.apache.commons.codec.digest;
    018
    019import java.nio.charset.StandardCharsets;
    020import java.security.SecureRandom;
    021
    022/**
    023 * GNU libc crypt(3) compatible hash method.
    024 * <p>
    025 * See {@link #crypt(String, String)} for further details.
    026 * </p>
    027 * <p>
    028 * This class is immutable and thread-safe.
    029 * </p>
    030 *
    031 * @since 1.7
    032 */
    033public class Crypt {
    034
    035    /**
    036     * Encrypts a password in a crypt(3) compatible way.
    037     * <p>
    038     * A random salt and the default algorithm (currently SHA-512) are used. See {@link #crypt(String, String)} for
    039     * details.
    040     * </p>
    041     * <p>
    042     * A salt is generated for you using {@link SecureRandom}.
    043     * </p>
    044     *
    045     * @param keyBytes
    046     *            plaintext password
    047     * @return hash value
    048     * @throws IllegalArgumentException
    049     *             when a {@link java.security.NoSuchAlgorithmException} is caught.
    050     */
    051    public static String crypt(final byte[] keyBytes) {
    052        return crypt(keyBytes, null);
    053    }
    054
    055    /**
    056     * Encrypts a password in a crypt(3) compatible way.
    057     * <p>
    058     * If no salt is provided, a random salt and the default algorithm (currently SHA-512) will be used. See
    059     * {@link #crypt(String, String)} for details.
    060     * </p>
    061     *
    062     * @param keyBytes
    063     *            plaintext password
    064     * @param salt
    065     *            the salt, which is used to select the algorithm, see {@link #crypt(String, String)}
    066     *            The salt may be null,
    067     *            in which case the method delegates to {@link Sha2Crypt#sha512Crypt(byte[])}
    068     *
    069     * @return hash value
    070     * @throws IllegalArgumentException
    071     *             if the salt does not match the allowed pattern
    072     * @throws IllegalArgumentException
    073     *             when a {@link java.security.NoSuchAlgorithmException} is caught.
    074     */
    075    public static String crypt(final byte[] keyBytes, final String salt) {
    076        if (salt == null) {
    077            return Sha2Crypt.sha512Crypt(keyBytes);
    078        }
    079        if (salt.startsWith(Sha2Crypt.SHA512_PREFIX)) {
    080            return Sha2Crypt.sha512Crypt(keyBytes, salt);
    081        }
    082        if (salt.startsWith(Sha2Crypt.SHA256_PREFIX)) {
    083            return Sha2Crypt.sha256Crypt(keyBytes, salt);
    084        }
    085        if (salt.startsWith(Md5Crypt.MD5_PREFIX)) {
    086            return Md5Crypt.md5Crypt(keyBytes, salt);
    087        }
    088        return UnixCrypt.crypt(keyBytes, salt);
    089    }
    090
    091    /**
    092     * Calculates the digest using the strongest crypt(3) algorithm.
    093     * <p>
    094     * A random salt and the default algorithm (currently SHA-512) are used.
    095     * </p>
    096     * <p>
    097     * A salt is generated for you using {@link SecureRandom}.
    098     * </p>
    099     *
    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}