为什么使用PHP';s hash#uhmac(';sha256';)给出的结果与javasha256#hmac不同

为什么使用PHP';s hash#uhmac(';sha256';)给出的结果与javasha256#hmac不同,java,php,sha256,Java,Php,Sha256,在PHP中,我有以下函数: base64_encode(hash_hmac('sha256', $data, $secret, false)); public static String base64sha256(String data, String secret) { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(secret.get

在PHP中,我有以下函数:

base64_encode(hash_hmac('sha256', $data, $secret, false));
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);
}
我正在尝试用Java创建一个函数,它将为相同的“数据”和“秘密”参数提供相同的结果

我尝试使用此功能:

base64_encode(hash_hmac('sha256', $data, $secret, false));
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();
}

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

与PHP相比,Java结果可能面临轻微变化(不起作用),我的问题是将hash作为字符串从
HmacSHA256
返回,而您应该返回它并将其作为
字节[]
传递到十六进制。 下面是模拟PHP的
hash\u hmac()


如果尝试将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中的URL和文件名安全base64编码器匹配。

数据编码是否可能?例如ANSI vs UTF-8?我尝试在这两个参数上使用getBytes(“UTF-8”),但结果仍然与PHP版本不一样。请参见本问答,其中他们讨论了
String.getBytes()
,而这一个是在“Related”下找到的。我查看了这些链接,似乎没有一个示例使用密钥。。。尽管如此,我还是根据我在那里读到的内容(你可以在上面看到)创建了一个新的代码更新版本,但仍然没有得到从php代码中得到的结果。这很有效!。需要这个来为Facebook Graph API生成
appsecret\u-proof
。这与使用Java 8的base64_编码(hash_hmac('sha256',$data,$secret,false))相同(这就是我试图实现的)?