2014-06-26 30 views
7

w PHP Mam następującą funkcję:dlaczego hash_hmac PHP („sha256”) daje inny wynik niż Java sha256_HMAC

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

Próbuję utworzyć funkcję w Javie, które dadzą ten sam wynik dla same parametry "dane" i "tajne".

Próbowałem korzystać z tej funkcji:

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); 
} 

Ale mam różne wyniki dla tego samego wejścia


UPDATE: Ta funkcja działa. Cieszyć się.

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 = "abcdef"; 
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(); 
} 
+0

kodowanie danych może? ANSI vs UTF-8 na przykład? – gtgaxiola

+0

Próbowałem używać getBytes ("UTF-8") na obu parametrach i nadal nie jest to ten sam wynik co wersja PHP –

+0

Zobacz ten Q & A http://stackoverflow.com/q/4680661/ gdzie mówią o 'String.getBytes() 'i ten jeden http://stackoverflow.com/q/23066005/ te zostały znalezione w" Powiązane ". –

Odpowiedz

2

Wyjściem funkcji php są małe litery heksadecymalne, gdy czwarty parametr jest fałszywy. Twoja druga wersja java generuje jednak wielkie cyfry szesnastkowe. Popraw skrzynkę lub zmień czwarty parametr hash_hmac na true i prawdopodobnie będzie zgodny z twoją pierwszą wersją Java.

+0

Rozwiązany. Dzięki człowiekowi –

0

Dla kogoś, kto może być w obliczu niewielkiej zmiany (nie działa) w wyniku Java w porównaniu do PHP, mój problem polegał na zwróceniu skrótu z HmacSHA256 jako String, podczas gdy powinieneś go zwrócić i przekazać do Hex jako byte[]. Oto metody pracy do symulacji 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; 
} 
1

Jeśli starając się dopasować wyjście drupal_hmac_base64 z Java 8, można użyć następującego kodu:

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); 

Zauważ, że Drupal zwraca hash używając surowy dane binarne (trzeci parametr TRUE). Ponadto kodowanie base64 w PHP pasuje do kodera adresu URL i nazwy pliku Safe base64 w Javie https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html#url.

+0

jest to to samo co base64_encode (hash_hmac ("sha256 ', $ data, $ secret, false)) z Javą 8 (to właśnie próbuję osiągnąć)? –

Powiązane problemy