将PHP中的SHA1哈希转换为JAVA代码


Convert SHA1 Hash in PHP to JAVA Code

嘿,伙计们,我有一个问题,我必须将PHP转换为Java…

Php函数以原始格式创建sha1散列并对其进行编码。

strtolower(urlencode(sha1("asfasfasdf", true)));

OUT: %bep%c3%9cc%dc%e4%89%f6n%0cw%fb%a3%95%ba%d8%c9r%82

在java中i try:

public static String buildIdentity(String identity) {
        try {
            return URLEncoder.encode(toSHA1(identity.getBytes())).toLowerCase();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static String toSHA1(byte[] convertme) throws UnsupportedEncodingException{
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("SHA-1");
            md.update(convertme);
            byte[] res = md.digest();
            return new String(res);
        }
        catch(NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

System.out.println(Utils.buildIdentity("asfasfasdf"));

,但它的输出是:%ef%bf%bdp%c3%9cc%ef%bf%bd%ef%bf%bd%ef%bf%bdn%0cw%ef%bf%bd%ef%bf%bd%ef%bf%bdr%ef%bf%bd

请帮助我:

解决方案发现!

public static String buildIdentity(String identity) {
    try {
        return URLEncoder.encode( new String(toSHA1(identity.getBytes("ISO-8859-1")), "ISO-8859-1"), "ISO-8859-1").toLowerCase();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return null;
}
public static byte[] toSHA1(byte[] convertme){
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        md.update(convertme);
        return md.digest();
    }
    catch(NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return null;
}

new String(byte[])使用平台默认编码将字节转换为字符。对我来说,它工作,如果你从你的toSHA1方法返回new String(res, "iso-8859-1");。这应该很好,因为"前256个代码点与ISO-8859-1的内容相同,这样就可以轻松转换现有的西方文本。"(从维基百科)。

但是这涉及到与字符串之间不必要的转换。相反,如果您不想添加依赖项,我将使用apache commons中的URLCodec类或复制粘贴此类。

默认编码问题也适用于identity.getBytes()调用:您应该在这里指定编码。它现在可能可以工作,但是如果您部署到生产服务器,它可能无法工作。

修复使用URLCodec: 的代码
public static String buildIdentity(String identity) {
    try {
        return new String(new URLCodec().encode(toSHA1(identity.getBytes("utf-8"))), "iso-8859-1");
    } catch (UnsupportedEncodingException e) {
        // should never happen, utf-8 and iso-8859-1 support is required by jvm specification. In any case, we rethrow.
        throw new RuntimeException(e);
    }
}
public static byte[] toSHA1(byte[] convertme) throws UnsupportedEncodingException {
    try {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        md.update(convertme);
        return md.digest();
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }
}
public static void main(String[] args) {
    System.out.println(buildIdentity("asfasfasdf"));
}

您的代码忽略了Java字符编码问题。在buildIdentity方法中,您在不带参数的String上调用getBytes,因此使用您的平台的默认字符编码。这可能会导致问题,也可能不会,这取决于您的平台;要获得跨平台可重复的结果,您需要指定编码,如identity.getBytes("UTF-8")

toSHA1方法中,调用构造函数new String(res)而不指定编码。这里最有可能出问题。如果您的操作系统的字符编码与ISO-8859-1不同,则一些字节将被替换为具有与原始字节不同的数值的字符,并且当您使用URLEncoder.encode对其进行编码时,您将无法获得预期的结果。因此,请使用new String(res, "ISO-8859-1")

似乎Java生成的哈希值也比PHP生成的哈希值长。但是,如果编码是正确的,它们应该都以相同的字符串开始,并且您应该能够调用substring来获得要编码的适当数量的字符。