HMAC-SHA1: Jak to zrobić poprawnie w Javie?

Hashuję niektóre wartości używając HMAC-SHA1, używając następującego kodu w Javie:

public static String hmacSha1(String value, String key) {
    try {
        // Get an hmac_sha1 key from the raw key bytes
        byte[] keyBytes = key.getBytes();           
        SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");

        // Get an hmac_sha1 Mac instance and initialize with the signing key
        Mac mac = Mac.getInstance("HmacSHA1");
        mac.init(signingKey);

        // Compute the hmac on input data bytes
        byte[] rawHmac = mac.doFinal(value.getBytes());

        // Convert raw bytes to Hex
        byte[] hexBytes = new Hex().encode(rawHmac);

        //  Covert array of Hex bytes to a String
        return new String(hexBytes, "UTF-8");
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

Hex() należy do org.apache.commons.codec

W PHP jest podobna funkcja hash_hmac(algorithm, data, key), której używam do porównywania wartości zwracanych przez moją implementację Javy.

Więc pierwsza próba to:

hash_hmac("sha1", "helloworld", "mykey") // PHP

Które zwraca: 74ae5a4a3d9996d5918defc2c3d475471bbf59ac

Moja funkcja Java zwraca również 74ae5a4a3d9996d5918defc2c3d475471bbf59ac.

Ok, wygląda na to, że działa. Następnie staram się użyć bardziej złożonego klucza:
hash_hmac("sha1", "helloworld", "PRIE7$oG2uS-Yf17kEnUEpi5hvW/#AFo") // PHP

To zwraca: e98bcc5c5be6f11dc582ae55f520d1ec4ae29f7a

Podczas gdy Tym razem mój Java impl zwraca: c19fccf57c613f1868dd22d586f9571cf6412cd0

Hash zwracany przez mój kod PHP nie jest równy wartości zwracanej przez moją funkcję Java i nie mogę się dowiedzieć dlaczego.

Jakieś wskazówki?
Author: Andrii Abramov, 2011-06-11

4 answers

Po stronie PHP użyj cudzysłowów wokół klucza, aby znak $ nie był traktowany jako odniesienie do zmiennej. tzn.,

hash_hmac("sha1", "helloworld", 'PRIE7$oG2uS-Yf17kEnUEpi5hvW/#AFo')

W przeciwnym razie klucz, który naprawdę otrzymujesz, to PRIE7-Yf17kEnUEpi5hvW/#AFo (zakładając, że zmienna $oG2uS nie jest zdefiniowana).

 50
Author: Chris Jester-Young,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-10 22:21:31

Polecam Apache Common Codec Library , dość prosty i łatwy w użyciu. HmacUtils.hmacSha1Hex(key, string_to_sign);

 12
Author: Armstrongya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-13 06:21:41

Dowolny symbol $ w cudzysłowach ( "" ) jest traktowany jako zmienna a w PHP. Możesz uniknąć błędu, używając pojedynczych cudzysłowów, jak wskazał poprzedni komentator, lub możesz uciec od znaku dolara, jak poniżej

hash_hmac("sha1", "helloworld", "PRIE7\$oG2uS-Yf17kEnUEpi5hvW/#AFo")

Notice $ is now \$

 7
Author: tlogbon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-27 16:17:32

W Java i używając maven :

Dodaj poniższą zależność do pom.xml:

 <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
    <dependency>
        <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.4</version>
    </dependency>

A następnie spróbuj go podpisać używając tego

HmacUtils.hmacSha1Hex(key, string_to_sign);
 0
Author: Salman Lashkarara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-30 15:38:08