为什么PHP的hash_hmac('sha256')给出的结果与java sha256_HMAC不同

时间:2014-06-26 11:49:22

标签: java php sha256

PHP中的

我有以下功能:

base64_encode(hash_hmac('sha256', $data, $secret, false));

我试图在Java中创建一个函数,它可以为相同的数据提供相同的结果"数据"和#34;秘密"参数。

我尝试使用此功能:

public static String base64sha256(String data, String secret) {
    Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
    SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
    sha256_HMAC.init(secret_key);
    byte[] res = sha256_HMAC.doFinal(data.getBytes());
    return Base64.encodeToString(res, Base64.NO_WRAP);
}

但是我得到相同输入的不同结果


更新:此功能有效。享受。

public static String base64sha256(String data, String secret) {
    String hash = null;
    try {
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        byte[] res = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
        hash = getHex(res);
        hash = Base64.encodeToString(hash.getBytes("UTF-8"), Base64.NO_WRAP);
    } catch (Exception e){}
    return hash;
}

static final String HEXES = "0123456789abcdef";
public static String getHex( byte [] raw ) {
    if ( raw == null ) {
        return null;
    }
    final StringBuilder hex = new StringBuilder( 2 * raw.length );
    for ( final byte b : raw ) {
        hex.append(HEXES.charAt((b & 0xF0) >> 4))
                .append(HEXES.charAt((b & 0x0F)));
    }
    return hex.toString();
}

3 个答案:

答案 0 :(得分:4)

当第四个参数为false时,php函数的输出为小写十六进制数字。但是,您的第二个Java版本会生成大写十六进制数字要么纠正大小写差异,要么可以将hash_hmac的第四个参数更改为true,它可能与您的第一个Java版本匹配。

答案 1 :(得分:1)

如果尝试将drupal_hmac_base64的输出与Java 8匹配,则可以使用以下代码:

final String ALGORITHM = "HmacSHA256";
        Mac mac = Mac.getInstance(ALGORITHM);
        SecretKeySpec secret = new SecretKeySpec(authorizationKey.getBytes(), ALGORITHM);

        mac.init(secret);
        byte[] digest = mac.doFinal(body.getBytes());

        hash = Base64.getUrlEncoder().withoutPadding().encodeToString(digest);

        return signature.equals(hash);

请注意,drupal使用原始二进制数据返回哈希值(第三个参数为TRUE)。此外,PHP中的base64编码与Java https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html#url中的URL和Filename安全base64编码器匹配。

答案 2 :(得分:0)

对于那些与PHP相比可能面临微小变化(不工作)的人,我的问题是将HmacSHA256的散列作为String返回,而你应该返回它并传递给Hex作为{ {1}}。 以下是模拟PHP byte[]

的工作方法
hash_hmac()