如何在Java中执行MySQL UNHEX()函数

如何在Java中执行MySQL UNHEX()函数,java,mysql,hash,passwords,Java,Mysql,Hash,Passwords,我试图从字符串中获取Java中的MySQL密码哈希,所以我在Google上搜索了一下,发现了MySQL中的Password()是如何工作的: SELECT SHA1(UNHEX(SHA1('test'))); 给出与相同的结果 SELECT PASSWORD('test'); 我接着说 我编写了一个将字符串转换为SHA1散列的方法,该方法非常有效(测试了几个不同的字符串,得到的结果与MySQL中的SHA1(str)相同) 接下来要做的是UNHEX()方法。我现在被卡住了 我目前的方法是: p

我试图从字符串中获取Java中的MySQL密码哈希,所以我在Google上搜索了一下,发现了MySQL中的Password()是如何工作的:

SELECT SHA1(UNHEX(SHA1('test')));
给出与相同的结果

SELECT PASSWORD('test');
我接着说

我编写了一个将字符串转换为SHA1散列的方法,该方法非常有效(测试了几个不同的字符串,得到的结果与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;
}
我的“toSHA1Hash”方法:


我不喜欢使用任何外部软件包,所以请帮助我仅使用JDK 1.8.0_40来实现这一点。

因此,5年后,我正在编辑我自己对这个问题的答案,因为当时我并不知道我真正在做什么。答案是有效的,但不是最优的

1.实际问题:“如何在Java中执行MySQL UNHEX()函数?” 1.1 MySQL中的UNHEX()函数实际上做什么 这个问题的答案很简单。它接受并将其转换为二进制对象

请记住:十六进制字符串只是将字节表示为文本的许多方法之一。这句话很简单,这就是这个问题的答案——我们只需将这个字符串转换成
字节[]

有了这些知识,我们就有了答案,多年前就在这里:

简言之:

//这是MySQL中UNHEX()函数的Java等价物
公共静态字节[]hexStringToByteArray(字符串s){
int len=s.length();
字节[]数据=新字节[len/2];
对于(int i=0;i

jakarta.xml.bind
,前缀为文字
*

2.2分解它 2.2.1 SHA1散列 要构建任何输入的SHA1哈希,我们可以使用Java中的
MessageDigest

import java.security.MessageDigest;
导入java.security.NoSuchAlgorithmException;
公共静态字节[]摘要(字符串算法,字节[]数据)抛出NoSuchAlgorithmException{
返回MessageDigest.getInstance(算法).digest(数据);
}
公共静态字节[]sha1(字节[]数据)引发NoSuchAlgorithmException{
返回摘要(“SHA-1”,数据);
}
2.2.2 SHA1哈希的SHA1哈希
publicstaticbyte[]mysqlPasswordHash(byte[]data)抛出NoSuchAlgorithmException{
//使用2.2.1中说明的方法两次
返回sha1(sha1(数据));
}
2.2.3构建一个
字节[]
这与我之前描述的UNHEX()函数相反,当我问这个问题时已经有了很多答案。请参阅:

private static final byte[]HEX_ARRAY=“0123456789ABCDEF”.getBytes(StandardCharsets.UTF_8);
公共静态字符串bytesToHex(字节[]字节){
最终字节[]hexChars=新字节[bytes.length*2];
对于(int j=0;j>>4];
hexChars[j*2+1]=十六进制数组[v&0x0F];
}
返回新字符串(hexChars、StandardCharsets.UTF_8);
}
或者,如果您有可用的
DataTypeConverter

公共静态字符串bytesToHex(字节[]字节){
返回DatatypeConverter.printHexBinary(字节);
}
2.2.4相当于MySQL密码功能 如果您添加了前面步骤中描述的方法,那么Java中的MySQL密码实现的工作原理如下:

public静态字符串mysqlPasswordHashString(字符串密码,Charset Charset)抛出NoSuchAlgorithmException{
返回“*”+bytesToHex(mysqlPasswordHash(password.getBytes(charset));
}
2.3调用该方法 要调用该方法,必须提供一个
java.nio.charset.charset
。要获得与在MySQL数据库上运行该方法相同的结果,必须确定MySQL的默认字符集是什么

假设您的MySQL使用UTF-8:

publicstaticvoidmain(字符串[]args)引发异常{
最后一个字符串mysqlPasswordHash=mysqlPasswordHashString(“helloworld”,StandardCharsets.UTF_8);
System.out.println(mysqlPasswordHash);
}

这没有帮助吗?我正在使用MessageDigist创建我的SHA1哈希,它工作得非常好。我一直无法退出SHA1哈希。也许你想编辑你的帖子并询问如何实现UNHEX()函数……你不应该将二进制数据存储在字符串中(
unhexedHash1
)!改用字节数组。首先不要对其进行十六进制运算。运行
sha1
,获取二进制数组,再次运行
sha1
,然后对最终结果进行十六进制运算。
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();
}