com.siashan.toolkit.crypt.digest.Crypt Maven / Gradle / Ivy
package com.siashan.toolkit.crypt.digest;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
/**
* GNU libc crypt(3)兼容哈希方法.
*
* 这个类是不可变的,并且是线程安全的.
* @author siashan
* @since 1.0.7
*/
public class Crypt {
/**
* 以与密码(3)兼容的方式加密密码.
*
* 使用随机salt和默认算法(当前为SHA-512).
*
*
*
* @param keyBytes
* 明文密码
* @return 哈希值
*/
public static String crypt(final byte[] keyBytes) {
return crypt(keyBytes, null);
}
/**
* 以与密码(3)兼容的方式加密密码.
*
* 如果未提供salt,则将使用随机salt和默认算法(当前为SHA-512).
*
* @param keyBytes
* 明文密码
* @param salt
* 不带前缀或“rounds=”的实际盐值。
* 盐可能是空的,在这种情况下,将使用{@link-ThreadLocalRandom}为您生成一个salt;
* 对于更安全的盐,请考虑使用{Link SaleRealDANDOM }生成你自己的盐。
* @return 哈希值
*/
public static String crypt(final byte[] keyBytes, final String salt) {
if (salt == null) {
return Sha2Crypt.sha512Crypt(keyBytes);
} else if (salt.startsWith(Sha2Crypt.SHA512_PREFIX)) {
return Sha2Crypt.sha512Crypt(keyBytes, salt);
} else if (salt.startsWith(Sha2Crypt.SHA256_PREFIX)) {
return Sha2Crypt.sha256Crypt(keyBytes, salt);
} else if (salt.startsWith(Md5Crypt.MD5_PREFIX)) {
return Md5Crypt.md5Crypt(keyBytes, salt);
} else {
return UnixCrypt.crypt(keyBytes, salt);
}
}
/**
* 使用最强加密(3)算法计算摘要.
*
* 使用随机salt和默认算法(当前为SHA-512)。
*
*
* 使用{@link-ThreadLocalRandom}为您生成一个salt;
* 为了更安全的盐考虑使用{@link SecureRandom}生成您自己的salt并调用{@link#crypt(String,String)}.
*
*
* @param key
* 明文密码
* @return 哈希值
*/
public static String crypt(final String key) {
return crypt(key, null);
}
/**
* 以与密码(3)兼容的方式加密密码.
*
* 精确的算法取决于salt字符串的格式:
*
* - SHA-512盐以{@code$6$}开头,最长可达16个字符.
*
- SHA-256盐以{@code$5$}开头,最长可达16个字符
*
- MD5盐以{@code$1$}开头,最长可达8个字符
*
- DES,传统的UnixCrypt算法仅使用2个字符
*
- DES算法中只使用密码的前8个字符!
*
* 此方法无法识别神奇字符串{@code“$apr1$”}和{@code“$2a$”},因为其输出应该是与libc实现相同。
*
* 盐串的其余部分从集合{@code[a-zA-Z0-9./]}中提取,
* 并在a的最大长度处切割遇到{@code“$”}符号。
* 因此,输入完整的哈希值作为salt是有效的,例如验证密码为:
*
*
* storedPwd.equals(crypt(enteredPwd, storedPwd))
*
*
* 结果字符串以标记字符串({@code$n$})开头,其中n与输入字符串相同.
* 然后附加salt,后跟{@code“$”}符号.
* 后面是实际的散列值.
* 对于DES,字符串只包含salt和实际哈希.
* 总长度取决于使用的算法:
*
* - SHA-512:106个字符
*
- SHA-256: 63 个字符
*
- MD5: 34 个字符
*
- DES: 13 个字符
*
*
* Example:
*
*
* crypt("secret", "$1$xxxx") => "$1$xxxx$aMkevjfEIpa35Bh3G4bAc."
* crypt("secret", "xx") => "xxWAum7tHdIUw"
*
*
* 此方法的变体接受byte[]数组以支持未编码的输入字符串UTF-8,
* 但例如在ISO-8859-1中,相同的字符导致不同的字节值.
*
* @param key
* 由所用用户输入的明文密码
* @param salt
* 不带前缀或“rounds=”的实际盐值。
* 盐可能为空,在这种情况下salt是使用{@link-ThreadLocalRandom}为您生成的;
* 为了更安全的盐考虑使用{@Link SoalEnrand On}来生成自己的盐。
* @return 散列值,即包括salt字符串的加密密码
*/
public static String crypt(final String key, final String salt) {
return crypt(key.getBytes(StandardCharsets.UTF_8), salt);
}
}