HMAC-SHA256 Algorithmus zur Signaturberechnung

74

Ich versuche, eine Signatur mit dem HMAC-SHA256-Algorithmus zu erstellen, und dies ist mein Code. Ich verwende die US-ASCII-Codierung.

final Charset asciiCs = Charset.forName("US-ASCII");
final Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
final SecretKeySpec secret_key = new javax.crypto.spec.SecretKeySpec(asciiCs.encode("key").array(), "HmacSHA256");
final byte[] mac_data = sha256_HMAC.doFinal(asciiCs.encode("The quick brown fox jumps over the lazy dog").array());
String result = "";
for (final byte element : mac_data)
{
    result += Integer.toString((element & 0xff) + 0x100, 16).substring(1);
}
System.out.println("Result:[" + result + "]");

Das Ergebnis, das ich aus dem obigen Code erhalte, ist:

f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8

Dies ist dasselbe wie im Wiki

HMAC_SHA256("key", "The quick brown fox jumps over the lazy dog") = 0x f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8

mit Ausnahme der 0x.

Ich suche nach Ideen / Kommentaren, wenn ich alles richtig mache oder meinen Code verbessern kann.

Rishi
quelle
4
Haben Sie ein bestimmtes Problem oder eine bestimmte Frage?
Oliver Charlesworth
Vielen Dank, ich habe über einen Tag lang nach
genau diesem

Antworten:

39

Das 0x bedeutet nur, dass die Zeichen danach eine Hex-Zeichenfolge darstellen.

0x1A == 1Ah == 26 == 1A

Das 0x dient also nur zur Verdeutlichung des Formats der Ausgabe, ohne dass Sie sich darum kümmern müssen.

Louis Ricci
quelle
79

Hier ist meine Lösung:

public static String encode(String key, String data) throws Exception {
  Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
  SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
  sha256_HMAC.init(secret_key);

  return Hex.encodeHexString(sha256_HMAC.doFinal(data.getBytes("UTF-8")));
}

public static void main(String [] args) throws Exception {
  System.out.println(encode("key", "The quick brown fox jumps over the lazy dog"));
}

Oder Sie können den in Base64 codierten Hash zurückgeben:

Base64.encodeBase64String(sha256_HMAC.doFinal(data.getBytes("UTF-8")));

Die Ausgabe in hex ist wie erwartet:

f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
vtlinh
quelle
11
Sie möchten wahrscheinlich nicht verwenden, key.getBytes()stattdessen wäre es ratsam, die Codierung anzugeben, dh key.getBytes("UTF-8")Sie könnten sich mit laufzeitspezifischen Fehlern bestrafen :)
Dori
2
Hexist nicht in der nativen Android API jetzt eine Alternative dafür verfügbar?
MilapTank
Kann unter Nicht-Android javax.xml.bind.DatatypeConverter verwenden . Alternativ sehen Sie benutzerdefinierte Implementierung in dieser anderen Frage: stackoverflow.com/questions/9655181/…
ruhong
2
Woher kommt die Hex-Klasse? Was ist der Import?
Portfoliobuilder
2
zu @Doris Punkt musste ich verwenden key.getBytes(StandardCharsets.UTF_8)und data.getBytes(StandardCharsets.UTF_8)vermeiden, einen zu werfen UnsupportedEncodingException. docs.oracle.com/javase/8/docs/api/java/nio/charset/…
LaurelB
14

Die Antwort, die Sie dort erhalten haben, ist richtig. Eine Kleinigkeit im obigen Code: Sie müssen init (key) eingeben, bevor Sie doFinal () aufrufen können.

    final Charset charSet = Charset.forName("US-ASCII");
    final Mac sha256_HMAC = Mac.getInstance("HmacSHA256");

    final SecretKeySpec secret_key = new javax.crypto.spec.SecretKeySpec(charSet.encode("key").array(), "HmacSHA256");
    try {
        sha256_HMAC.init(secret_key);
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    ...
Michael
quelle
9

Das funktioniert gut für mich

Ich habe Abhängigkeit hinzugefügt

compile 'commons-codec:commons-codec:1.9'

Ref: http://mvnrepository.com/artifact/commons-codec/commons-codec/1.9

meine Funktion

public String encode(String key, String data) {
    try {

        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
        sha256_HMAC.init(secret_key);

        return new String(Hex.encodeHex(sha256_HMAC.doFinal(data.getBytes("UTF-8"))));

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

    return null;
}
Bikesh M.
quelle
1
Tatsächlich ist dies die einfachste Arbeitslösung, die auch alle möglichen Ausnahmen gut behandelt.
Tom
1
@tom wie geht es mit Ausnahmen um? Im Falle einer Ausnahme wird eine Stapelverfolgung gedruckt und diese werden stillschweigend ausgeblendet.
Bash0r
Entschuldigung, falsche Formulierung, ich meinte, es zeigt, welche Ausnahmen während des Verfahrens auftreten können, das Sie behandeln müssen.
Tom
6

Versuche dies

Es tut mir leid, dass ich zu spät gekommen bin. Ich habe alle oben genannten Antworten ausprobiert, aber keine von ihnen gibt mir den richtigen Wert. Nachdem ich viel Forschung und Entwicklung betrieben habe, habe ich einen einfachen Weg gefunden, der mir den genauen Wert gibt.

  1. Deklarieren Sie diese Methode in Ihrer Klasse

    private String hmacSha(String KEY, String VALUE, String SHA_TYPE) {
    try {
        SecretKeySpec signingKey = new SecretKeySpec(KEY.getBytes("UTF-8"), SHA_TYPE);
        Mac mac = Mac.getInstance(SHA_TYPE);
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(VALUE.getBytes("UTF-8"));
        byte[] hexArray = {(byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'};
        byte[] hexChars = new byte[rawHmac.length * 2];
        for ( int j = 0; j < rawHmac.length; j++ ) {
            int v = rawHmac[j] & 0xFF;
            hexChars[j * 2] = hexArray[v >>> 4];
            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
        }
        return new String(hexChars);
    }
    catch (Exception ex) {
        throw new RuntimeException(ex);
    }
    

    }}

  2. Verwenden Sie dies wie

    Log.e("TAG", "onCreate: "+hmacSha("key","text","HmacSHA256"));
    

Überprüfung

1.Android Studio Ausgabe Android Studio Ausgabe 2. Online HMAC Generator Ausgabe (Besuchen Sie hier für Online Genrator) Geben Sie hier die Bildbeschreibung ein

Sunil
quelle
4

Einfacher Java-Code zum Generieren von codierten (HMAC-x) Signaturen. (Versucht mit Java-8 und Eclipse)

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import com.sun.org.apache.xml.internal.security.utils.Base64;

/**
 * Encryption class to show how to generate encoded(HMAC-x) signatures.
 * 
 */
public class Encryption {

    public static void main(String args[]) {

        String message = "This is my message.";
        String key = "your_key";
        String algorithm = "HmacMD5";  // OPTIONS= HmacSHA512, HmacSHA256, HmacSHA1, HmacMD5

        try {

            // 1. Get an algorithm instance.
            Mac sha256_hmac = Mac.getInstance(algorithm);

            // 2. Create secret key.
            SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), algorithm);

            // 3. Assign secret key algorithm.
            sha256_hmac.init(secret_key);

            // 4. Generate Base64 encoded cipher string.
            String hash = Base64.encode(sha256_hmac.doFinal(message.getBytes("UTF-8")));

            // You can use any other encoding format to get hash text in that encoding.
            System.out.println(hash);

            /**
             * Here are the outputs for given algorithms:-
             * 
             * HmacMD5 = hpytHW6XebJ/hNyJeX/A2w==
             * HmacSHA1 = CZbtauhnzKs+UkBmdC1ssoEqdOw=
             * HmacSHA256 =gCZJBUrp45o+Z5REzMwyJrdbRj8Rvfoy33ULZ1bySXM=
             * HmacSHA512 = OAqi5yEbt2lkwDuFlO6/4UU6XmU2JEDuZn6+1pY4xLAq/JJGSNfSy1if499coG1K2Nqz/yyAMKPIx9C91uLj+w==
             */

        } catch (NoSuchAlgorithmException e) {

            e.printStackTrace();

        } catch (UnsupportedEncodingException e) {

            e.printStackTrace();

        } catch (InvalidKeyException e) {

            e.printStackTrace();

        }

    }

}

Hinweis: Sie können andere Algorithmen verwenden und kann Erzeugungs versuchen HmacMD5, HmacSHA1, HmacSHA256, HmacSHA512Unterschriften.

Rahul Raina
quelle
2

Wenn Sie nur eine Chance haben, hier eine Lösung zur Berechnung von HMAC-SHA256 zu finden, erhalten Sie eine Ausnahme wie diese:

java.lang.NoSuchMethodError: Keine statische Methode encodeHexString ([B) Ljava / lang / String; in der Klasse Lorg / apache / commons / codec / binary / Hex; oder seine Superklassen (Deklaration von 'org.apache.commons.codec.binary.Hex' erscheint in /system/framework/org.apache.http.legacy.boot.jar)

Dann benutze:

public static String encode(String key, String data) {
    try {
        Mac hmac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
        hmac.init(secret_key);
        return new String(Hex.encodeHex(hmac.doFinal(data.getBytes("UTF-8"))));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Tomrozb
quelle
0

Hier ist meine Lösung:

public String HMAC_SHA256(String secret, String message)
{
    String hash="";
    try{
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
        sha256_HMAC.init(secret_key);

        hash = Base64.encodeToString(sha256_HMAC.doFinal(message.getBytes()), Base64.DEFAULT);
    }catch (Exception e)
    {

    }
    return hash.trim();
}
Rahim Rahimov
quelle