cod*_*dev 5 java mysql passwords hash
我正在尝试从字符串中获取 Java 中的 MySQL 密码哈希,所以我用谷歌搜索了一下,发现了 MySQL 中的 PASSWORD() 是如何工作的:
SELECT SHA1(UNHEX(SHA1('test')));
Run Code Online (Sandbox Code Playgroud)
给出相同的结果
SELECT PASSWORD('test');
Run Code Online (Sandbox Code Playgroud)
有了这个我继续。
我写了一个将字符串转换为 SHA1 Hash 的方法,它完美地工作(测试了几个不同的字符串,得到与 MySQL 中的 SHA1(str) 相同的结果)
接下来要做的是 UNHEX() 方法。我现在卡住了。
我目前的方法:
public static String toMySQLPasswordHash(String str)
{
String hash1 = toSHA1Hash(str);
String unhexedHash1 = new String(DatatypeConverter.parseHexBinary(hash1));
String hash2 = toSHA1Hash(unhexedHash1);
String passwordHash = "*" + hash2.toUpperCase();
return passwordHash;
}
Run Code Online (Sandbox Code Playgroud)
我的“toSHA1Hash”方法:
public static String toSHA1Hash(String str)
{
MessageDigest md = null;
try
{
md = MessageDigest.getInstance("SHA-1");
}
catch (NoSuchAlgorithmException e)
{
Logger.WriteLog(e.toString());
}
if (md == null)
return null;
md.reset();
md.update(str.getBytes());
byte[] byteData = md.digest();
StringBuilder sb = new StringBuilder();
for (byte currByte : byteData)
sb.append(Integer.toString((currByte & 0xff) + 0x100, 16).substring(1));
return sb.toString();
}
Run Code Online (Sandbox Code Playgroud)
我不喜欢使用任何外部包,所以请帮助我仅使用 JDK 1.8.0_40 来完成此操作。
所以,五年后我正在编辑自己对这个问题的答案,因为那时我并不真正知道自己到底在做什么。答案有效,但不是最佳的。
这个问题的答案很简单。它接受一串十六进制字符并将其转换为二进制对象。
请记住:十六进制字符串只是将字节表示为文本的多种方法之一。这句话很简单,这就是这个问题的答案 - 我们只需将此字符串转换为byte[].
有了这些知识,我们就有了答案,多年前就在这里:使用 Java 将十六进制转储的字符串表示形式转换为字节数组?
简而言之:
// this is the Java equivalent to the UNHEX() function in MySQL
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
Run Code Online (Sandbox Code Playgroud)
或者简单地:
import javax.xml.bind.DatatypeConverter;
Run Code Online (Sandbox Code Playgroud)
// this is the Java equivalent to the UNHEX() function in MySQL
public static byte[] hexStringToByteArray(String s) {
return DatatypeConverter.parseHexBinary(s);
}
Run Code Online (Sandbox Code Playgroud)
(Java > 8 删除了 Java EE 类,您可以通过添加以下依赖项来添加 DataTypeConverter):
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.3</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
MySQL Password() 函数是输入的 sha1-Hash 的 sha1-Hash,采用十六进制表示形式,前缀为文字*。
要构建任何输入的 SHA1-Hash,我们可以使用MessageDigestJava 中的类。
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
Run Code Online (Sandbox Code Playgroud)
public static byte[] digest(String algorithm, byte[] data) throws NoSuchAlgorithmException {
return MessageDigest.getInstance(algorithm).digest(data);
}
public static byte[] sha1(byte[] data) throws NoSuchAlgorithmException {
return digest("SHA-1", data);
}
Run Code Online (Sandbox Code Playgroud)
public static byte[] mysqlPasswordHash(byte[] data) throws NoSuchAlgorithmException {
// using the method explained in 2.2.1 twice
return sha1(sha1(data));
}
Run Code Online (Sandbox Code Playgroud)
byte[]这与我之前描述的 UNHEX() 函数相反,当我问这个问题时已经有很多答案。请参阅:如何在 Java 中将字节数组转换为十六进制字符串?
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.UTF_8);
public static String bytesToHex(byte[] bytes) {
final byte[] hexChars = new byte[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars, StandardCharsets.UTF_8);
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您有DataTypeConverter可用的:
public static String bytesToHex(byte[] bytes) {
return DatatypeConverter.printHexBinary(bytes);
}
Run Code Online (Sandbox Code Playgroud)
如果您添加了前面步骤中描述的方法,Java 中的 MySQL-Password 实现将如下所示:
public static String mysqlPasswordHashString(String password, Charset charset) throws NoSuchAlgorithmException {
return "*" + bytesToHex(mysqlPasswordHash(password.getBytes(charset)));
}
Run Code Online (Sandbox Code Playgroud)
要调用该方法,您必须提供java.nio.charset.Charset. 为了获得与在 MySQL 数据库上运行相同的结果,您必须弄清楚 MySQL 的默认字符集是什么。
假设您的 MySQL 使用 UTF-8:
public static void main(String[] args) throws Exception {
final String mysqlPasswordHash = mysqlPasswordHashString("Hello world", StandardCharsets.UTF_8);
System.out.println(mysqlPasswordHash);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1903 次 |
| 最近记录: |