簡體   English   中英

為什么PHP的hash_hmac('sha256')給出的結果與java sha256_HMAC不同

[英]why PHP's hash_hmac('sha256') gives different result than java sha256_HMAC

在PHP中我有以下功能:

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

我正在嘗試在Java中創建一個函數,它將為相同的“數據”和“秘密”參數提供相同的結果。

我試着使用這個功能:

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版本匹配。

如果嘗試將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編碼器相匹配。

對於那些與PHP相比可能面臨微小變化(不工作)的人,我的問題是將HmacSHA256的哈希值作為String返回,而你應該返回它並以byte[]傳遞給Hex。 以下是模擬PHP的hash_hmac()的工作方法

public String hashValue(String message) {
    byte[] hash = toHmacSHA256(message);
    String hashHexed = toHex(hash);
    return hashHexed;
}

private String toHex(byte[] value) {
    String hexed = String.format("%040x", new BigInteger(1, value));
    return hexed;
}

private byte[] toHmacSHA256(String value) {
    byte[] hash = null;
    try {
        SecretKey secretKey = new SecretKeySpec(PRIVATE_KEY.getBytes("UTF-8"), "HmacSHA256");
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(secretKey);
        hash = mac.doFinal(value.getBytes("UTF-8"));

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }

    return hash;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM