Discussion:
Wie berechnet man einen HMAC-SHA1 aus einem String?
(zu alt für eine Antwort)
Michael Wilde
2006-07-25 15:38:28 UTC
Permalink
Hallo,

gegeben ist der String "secret" aus dem ich den HMAC-SHA1 Hashcode
berechnen möchte. Kann mir bitte jemand den zugehörigen Hashcode posten
und mir sagen, wie man diesen berechnet?

Vielen Dank,
Michael.
Sven Köhler
2006-07-25 15:59:34 UTC
Permalink
Post by Michael Wilde
gegeben ist der String "secret" aus dem ich den HMAC-SHA1 Hashcode
berechnen möchte. Kann mir bitte jemand den zugehörigen Hashcode posten
und mir sagen, wie man diesen berechnet?
versuch mal http://de.wikipedia.org/wiki/HMAC

hab ich mir nicht wirklich durchgelesen.
Michael Wilde
2006-07-25 19:55:01 UTC
Permalink
Post by Sven Köhler
Post by Michael Wilde
gegeben ist der String "secret" aus dem ich den HMAC-SHA1 Hashcode
berechnen möchte. Kann mir bitte jemand den zugehörigen Hashcode posten
und mir sagen, wie man diesen berechnet?
versuch mal http://de.wikipedia.org/wiki/HMAC
hab ich mir nicht wirklich durchgelesen.
Hmm. Danke, ja. Hab vergessen anzumerken, dass meine Google-Suchen
bislang erfolglos geblieben sind...

Laut: http://www.w3.org/TR/xkms2/#XKMS_2_0_Section_8_1 soll der
SharedKey für die TripleDES-Verschlüsselung eines XML-Elements dem
HMAC-SHA1 Hashcode eines SharedSecrets - sprich eines Strings -
entsprechen. Diesen SharedKey brauche ich, sonst kann ich die Nachricht
nicht entschlüsseln.

Soweit ich das bis jetzt verstanden habe braucht man zusätzlich noch
eine Art Message, auf die man HMAC-SHA1 in Kombination mit dem
SharedSecret anwenden kann. Welche das ist steht in der Spezifikation
nicht drin. Oder ich hab es überlesen.

Meine Frage war eigentlich, ob es denn möglich ist _nur_ aus einem
String einen HMAC-SHA1 Hashcode zu erzeugen. Dabei nehme ich an
HMAC-SHA1 != SHA1
Stefan Matthias Aust
2006-07-25 17:56:58 UTC
Permalink
Post by Michael Wilde
gegeben ist der String "secret" aus dem ich den HMAC-SHA1 Hashcode
berechnen möchte. Kann mir bitte jemand den zugehörigen Hashcode posten
und mir sagen, wie man diesen berechnet?
So oder so ähnlich:

Mac m = Mac.getInstance("HmacSHA1");
m.init(...);
m.update(...);
m.doFinal();
--
Stefan Matthias Aust
Michael Wilde
2006-07-26 06:38:45 UTC
Permalink
Post by Stefan Matthias Aust
Post by Michael Wilde
gegeben ist der String "secret" aus dem ich den HMAC-SHA1 Hashcode
berechnen möchte. Kann mir bitte jemand den zugehörigen Hashcode posten
und mir sagen, wie man diesen berechnet?
Mac m = Mac.getInstance("HmacSHA1");
m.init(...);
m.update(...);
m.doFinal();
So weit war ich schon. Eine Funktion:

public String encrypt(String secret, String message)
{
byte[] mac = new byte[40];

try {
Mac sha = Mac.getInstance("HmacSHA1");
sha.init(new SecretKeySpec(secret.getBytes(), "HmacSHA1"));
mac = sha.doFinal(message.getBytes());
} catch (Exception e) {
e.printStackTrace();
}

return new String(mac);
}

liefert mir nur eine NoSuchAlgorithmException. HmacSHA1 ist kein
zulässiger Algorithmus für den Sun JCE und auch nicht für BouncyCastle.

Mittlerweile konnte ich den HmacSHA1("secret", "secret")-Wert berechnen.
Er lautet: 09e0069ecfc66970aaedac31d85f26d89281e529
Allerdings nur mit einem externen Tool [1] Ich hätt' das aber gern
direkt in Java gelöst :-(

--
[1] HashCalc 2.01: http://hashcalc.slavasoft-inc.qarchive.org/
Stefan Matthias Aust
2006-07-26 09:25:36 UTC
Permalink
Post by Michael Wilde
sha.init(new SecretKeySpec(secret.getBytes(), "HmacSHA1"));
mac = sha.doFinal(message.getBytes());
return new String(mac);
Benutze niemals getBytes oder diesen String-Construktor ohne Encoding,
wenn du reproduzierbare Ergebnisse auf verschiedenen Plattformen haben
willst!
Post by Michael Wilde
liefert mir nur eine NoSuchAlgorithmException. HmacSHA1 ist kein
zulässiger Algorithmus für den Sun JCE und auch nicht für BouncyCastle.
Doch, definitiv.

Ich meine, HmacSHA1 und HmacMD5 gibt es bereits ab JDK 1.4.
--
Stefan Matthias Aust
Ralf Ullrich
2006-07-26 11:18:01 UTC
Permalink
Post by Michael Wilde
public String encrypt(String secret, String message)
{
byte[] mac = new byte[40];
try {
Mac sha = Mac.getInstance("HmacSHA1");
sha.init(new SecretKeySpec(secret.getBytes(), "HmacSHA1"));
mac = sha.doFinal(message.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
return new String(mac);
}
liefert mir nur eine NoSuchAlgorithmException. HmacSHA1 ist kein
zulässiger Algorithmus für den Sun JCE und auch nicht für BouncyCastle.
Dein Code ist korrekt*, deine JCE-Konfiguration scheint aber korrupt zu
sein.
Post by Michael Wilde
Mittlerweile konnte ich den HmacSHA1("secret", "secret")-Wert berechnen.
Er lautet: 09e0069ecfc66970aaedac31d85f26d89281e529
Allerdings nur mit einem externen Tool [1] Ich hätt' das aber gern
direkt in Java gelöst :-(
Hier mein SSCCE bzw. SEx, das bei mir (JDK 1.5) sauber läuft:

package de.jnana.dclj;

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

public class HMACDemo {
static String hex(byte[] data) {
StringBuilder sb = new StringBuilder();
for (byte b : data) {
sb.append(Character.forDigit((b & 240) >> 4, 16));
sb.append(Character.forDigit((b & 15), 16));
}
return sb.toString();
}

public static void main(String[] args) {
String secret = "secret";
String message = "secret";
byte[] mac = new byte[40];

try {
Mac sha = Mac.getInstance("HmacSHA1");
sha.init(new SecretKeySpec(secret.getBytes(), "HmacSHA1"));
mac = sha.doFinal(message.getBytes());
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(hex(mac));

}
}

cu

* korrekt: nur wenn man von den Encoding-Fehlern, auf die Stefan schon
hingewiesen hat, absieht.
Michael Wilde
2006-07-26 13:59:41 UTC
Permalink
Hallo Ralf,
Post by Michael Wilde
Mittlerweile konnte ich den HmacSHA1("secret", "secret")-Wert berechnen.
Er lautet: 09e0069ecfc66970aaedac31d85f26d89281e529
Allerdings nur mit einem externen Tool [1] Ich hätt' das aber gern
direkt in Java gelöst :-(
[...]

Danke, das funktioniert wunderbar. Danke auch an Stefan für seinen
Hinweis mit dem Encoding. Ich hab trotzdem noch ein Problem, aber
vielleicht könnt ihr mir dabei behilflich sein.

Ich würde gerne einen TripleDES-Block entschlüsseln. Der symmetrische
Schlüssel sollte mit HMAC-SHA1 vom String "secret" abgeleitet werden
können. Hab das Ganze nun in ein lauffähiges Programm gepackt (siehe
unten). Ich erhalte allerdings folgende Exception:

javax.crypto.BadPaddingException: Given final block not properly padded

Könnt ihr mir bitte dabei helfen den cipher zu entschlüsseln? Ich bin
mir nicht sicher, wie ich den SecretKey übergeben muss.

Punkt [331] von http://www.w3.org/TR/xkms2/#XKMS_2_0_Section_8_1
beschreibt, wie man an den Key kommt. Der shared String ist "secret"
(laut http://www.soapclient.com/xkmstest.html - scheint momentan offline
zu sein, die Adresse und der angegebene shared String stimmen aber).

Ich wäre euch zu dank verpflichtet!


Mein Programm:

package test;

import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;

public class HashCalculator {

private static String secret = "secret";
private static String message =
"6VSIdlBUlS19IL4mI7Re75umJWtUBRHaqI3coi+G2l+peKphQw0fuOml6hDmTL9P" +
"ppozPO3pJdNdYb3soigl1cbeUoGMVAQYjxSDhb/7A/59ECQmfUSLCijGUB47RdMP" +
"gMHan4fTBKf/+PxJw4hBv5iK7gitoWAdYs3QJ4D3aY+gW+p253D4dDuHZXYjCoxH" +
"CPUtslGn/qAYgzExxBtp3Iw0v7Ow9lzaWt1275rIawIjYOdtVHMfDkLWSvilkzZu" +
"io5p+ci7h/z2Ngqjz1PeOxuI6SSjwDImdKQzGl1zBtAOC/BWQKiNC0sv4Gr3EAdO" +
"0+81c0Ayn8r/ZSiQ9SN0RSkE2Vo+8rtYaI6phPkmV7qR35nRoNjPBH6/YXrufQjx" +
"L9J5IZFvCWZJeZSLk8Y02OSqD+M30g14awHR30MuCkr3JF/Re3bxVBsU7sJZHetw" +
"NwilXbZiSiKCElLAFbag038LuhOxGg7zRQrKgwYTo2piEU3tGiDZDS/sqC9GYa4F" +
"yEu1K+vpqTv0iwX2RA8sD+2KF0UqCSrJkJImtfkFDgkXUf33CsPzl3G9ehpqzROe" +
"vQV+T2Pc8+fRK/7XtNrP7GBz6n4oAOvcLnz0EYdHkUJ0cPoesz+OEbJCB196kx5j" +
"gAlFsfBJtNheB0q55WypyE/vKnyr4lIacIXtrCRKzrecZHdVgf/k4VyvArz5RNIk" +
"LwQOvl0TQYSDf5cSx/8CRuYzt2vKzjfjzavoxlTgngHw203m5DE1Wji3U6CENdyp" +
"hvIS0TGM/i+Wa+EvvDEKEs9HtspJJ47XIXlcOHtoQCgLJdg94O+njC675NI8OQt0" +
"EDICvtPJk02hFTOAW8OWJIi72ams/ofxBFOKi6/u5XUFccjnVsdKNJCcCxmYw9a+" +
"WwyZ9ZjJPlOzpRDWxFm39joydySrsPqvdQI26gstxUgfyHE2QqsMczMK+soPyqRo" +
"gHS+ujIfcX9cW3tv8W6e4ZPNzuP04ccNUWVtYqWjAWf5VF6p9tqPzwpUWOdh0Z1y" +
"gevuy6XGA7M/6By+17Eenw6T53/XuFnzlfeNBF68Z/rBscquJQEbvCeZCKIZ/RKL" +
"zwIVcaSdvcEDJ5DudmjutcVyVOS/envgJr423oyv7VjrdYxF+O4TsxQKNPdEez4j" +
"jupRReM+X/ofI/+WIhr/YYpiXrlBn5qeIjwAmTnaOp9gSMkQ7rgoPgXCEyBU51+t" +
"Oa9qAFe9KYf9aFzNqDne8dk1A9JMO6FxBnSoyF1PaDtTzf424DLk9Ym4ZEsvUGT9" +
"fU1IC0gxb3UpV/jiGibW5Q==";

public static void main(String[] args) {

try {
Security.addProvider(new BouncyCastleProvider());

String hmacSha1 = hmacSha1(secret, secret);
SecretKey key = getSecretKey(hmacSha1);
String decryptedString = decrypt(key, message);

System.out.println(decryptedString);
} catch (Exception e) {
e.printStackTrace();
}
}

public static SecretKey getSecretKey(String hmacSha1)
throws Exception {

DESedeKeySpec keyspec = new DESedeKeySpec(hmacSha1.getBytes("UTF-8"));
SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede");
SecretKey key = keyfactory.generateSecret(keyspec);

return key;
}

public static String decrypt(SecretKey key, String base64)
throws Exception {

byte[] encryptedString = Base64.decode(base64);

Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.DECRYPT_MODE, key);

byte[] decryptedString = cipher.doFinal(encryptedString);

return new String(decryptedString);
}

private static String hmacSha1(String secret, String message) {

byte[] mac = new byte[20];

try {
Mac sha = Mac.getInstance("HmacSHA1");
sha.init(new SecretKeySpec(secret.getBytes("UTF-8"),
"HmacSHA1"));
mac = sha.doFinal(message.getBytes("UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}

return hex(mac);
}

private static String hex(byte[] data) {

StringBuilder sb = new StringBuilder();

for (byte b : data) {
sb.append(Character.forDigit((b & 240) >> 4, 16));
sb.append(Character.forDigit((b & 15), 16));
}

return sb.toString();
}
}

TIA,
Michael.
Stefan Matthias Aust
2006-07-26 18:26:57 UTC
Permalink
Post by Michael Wilde
Danke auch an Stefan für seinen
Hinweis mit dem Encoding.
Dann befolge ihn. Richtig :) Ich denke hier liegt dein Problem. Etwas wie
Post by Michael Wilde
sha.init(new SecretKeySpec(secret.getBytes("UTF-8"),
"HmacSHA1"));
kann nicht funktionieren, denn keys in encodeter Form sind byte[] und
keine Strings. Du hast Glück, dass du kein ungültiges Encoding triffst.
Post by Michael Wilde
mac = sha.doFinal(message.getBytes("UTF-8"));
Auch das kann nicht funktionieren, denn wenn du auch nur ein Zeichen mit
einem Codepoint > 127 hast, wird das in mehr als einem Byte als
UTF-8-Sequenz dargestellt. Dadurch wird sich die Größe deiner Message
ändern und das wird zu deinem Fehler, dass das Padding nicht passt, führen.
--
Stefan Matthias Aust
Michael Wilde
2006-07-27 06:52:08 UTC
Permalink
Post by Stefan Matthias Aust
Post by Michael Wilde
Danke auch an Stefan für seinen
Hinweis mit dem Encoding.
Dann befolge ihn. Richtig :) Ich denke hier liegt dein Problem. Etwas wie
Post by Michael Wilde
sha.init(new SecretKeySpec(secret.getBytes("UTF-8"),
"HmacSHA1"));
kann nicht funktionieren, denn keys in encodeter Form sind byte[] und
keine Strings. Du hast Glück, dass du kein ungültiges Encoding triffst.
Nunja, obiges Beispiel liefert mir zumindest den HmacSHA1-Wert zurück,
so wie ich ihn erwarten würde. Mein Problem ist, dass ich nur einen
String zur Verfügung habe, aus dem ich den SecretKey ableiten muss.

In der Spezifikation [1] steht:

"[331]Keying material is derived from the shared string using a MAC
function.

[332]The default MAC algorithm used is HMAC-SHA1."

und weiter:

"[334]If the output of the MAC function provides more keying material
than is required for a cryptographic operation (i.e. encryption, MAC),
the lowest significant bits are used.

[335]If the output of the MAC function provides less keying material
than is required additional keying material is obtained as follows:

[...]"

Und der Interoperability-Provider [2] gibt an:

"Shared Secret: secret"

Aus diesem String soll das "Keying material" abgeleitet werden. Nur wie
macht man das korrekt? Ich komm mit dieser Beschreibung nicht zurecht.
Post by Stefan Matthias Aust
Post by Michael Wilde
mac = sha.doFinal(message.getBytes("UTF-8"));
Auch das kann nicht funktionieren, denn wenn du auch nur ein Zeichen mit
einem Codepoint > 127 hast, wird das in mehr als einem Byte als
UTF-8-Sequenz dargestellt. Dadurch wird sich die Größe deiner Message
ändern und das wird zu deinem Fehler, dass das Padding nicht passt, führen.
Das wäre eine Erklärung, ist aber im Prinzip der selbe Fehler wie
vorher. Die Strings secret und message sind ja identisch, d.h. sie haben
den Wert "secret". Nur wie soll man es sonst machen? Die Codepoints
liegen zwischen 99 (c) und 116 (t), das sollte zumindest passen.

Danke,
Michael.

--
[1] http://www.w3.org/TR/xkms2/#XKMS_2_0_Section_8_1
[2] http://www.soapclient.com/xkmstest.html
Michael Wilde
2006-07-27 08:58:22 UTC
Permalink
Sorry, für das TOFU, aber ich bin dem Problem jetzt auf die Schliche
gekommen. Hier einige Testdaten:

Authentication Data
024837
Converted Authentication Data
[30][32][34][38][33][37]
Key = HMAC-SHA1 (Converted Authentication Data, 0x1)
[d6][cc][34][cb][83][fa][e2][99] [3a][39][3a][a8][e7][de][9a][06]
[c7][fa][2c][92]

Um an den Key zu kommen muss "Authentication Data" erst einmal in hex
umgewandelt werden. Das klappt schon mal recht gut.

Wenn ich hmacSha1 mit den Parametern 024837 und 303234383337 aufrufe
erhalte ich b5d9f1e8e7be256e60f93012e05e2ff51ce645b7 retour bzw. wenn
ich die Parameter vertausche 8b9e2c559c109e084f9ff35903663cfc46d5cca1,
und nicht, wie zu erwarten, d6cc34cb83fae2993a393aa8e7de9a06c7fa2c92.

Wenn dieses Problem gelöst ist, dürfte auch mein anderes gelöst sein.

Bitte nochmals um Hilfe!
Post by Michael Wilde
Post by Stefan Matthias Aust
Post by Michael Wilde
Danke auch an Stefan für seinen
Hinweis mit dem Encoding.
Dann befolge ihn. Richtig :) Ich denke hier liegt dein Problem. Etwas wie
Post by Michael Wilde
sha.init(new SecretKeySpec(secret.getBytes("UTF-8"),
"HmacSHA1"));
kann nicht funktionieren, denn keys in encodeter Form sind byte[] und
keine Strings. Du hast Glück, dass du kein ungültiges Encoding triffst.
Nunja, obiges Beispiel liefert mir zumindest den HmacSHA1-Wert zurück,
so wie ich ihn erwarten würde. Mein Problem ist, dass ich nur einen
String zur Verfügung habe, aus dem ich den SecretKey ableiten muss.
"[331]Keying material is derived from the shared string using a MAC
function.
[332]The default MAC algorithm used is HMAC-SHA1."
"[334]If the output of the MAC function provides more keying material
than is required for a cryptographic operation (i.e. encryption, MAC),
the lowest significant bits are used.
[335]If the output of the MAC function provides less keying material
[...]"
"Shared Secret: secret"
Aus diesem String soll das "Keying material" abgeleitet werden. Nur wie
macht man das korrekt? Ich komm mit dieser Beschreibung nicht zurecht.
Post by Stefan Matthias Aust
Post by Michael Wilde
mac = sha.doFinal(message.getBytes("UTF-8"));
Auch das kann nicht funktionieren, denn wenn du auch nur ein Zeichen mit
einem Codepoint > 127 hast, wird das in mehr als einem Byte als
UTF-8-Sequenz dargestellt. Dadurch wird sich die Größe deiner Message
ändern und das wird zu deinem Fehler, dass das Padding nicht passt, führen.
Das wäre eine Erklärung, ist aber im Prinzip der selbe Fehler wie
vorher. Die Strings secret und message sind ja identisch, d.h. sie haben
den Wert "secret". Nur wie soll man es sonst machen? Die Codepoints
liegen zwischen 99 (c) und 116 (t), das sollte zumindest passen.
Danke,
Michael.
--
[1] http://www.w3.org/TR/xkms2/#XKMS_2_0_Section_8_1
[2] http://www.soapclient.com/xkmstest.html
Tobias Mayer
2006-07-26 09:29:58 UTC
Permalink
Post by Michael Wilde
gegeben ist der String "secret" aus dem ich den HMAC-SHA1 Hashcode
berechnen möchte. Kann mir bitte jemand den zugehörigen Hashcode posten
und mir sagen, wie man diesen berechnet?
http://jcetaglib.sourceforge.net/lightcrypto/

# Create MACs (Message Authentication Code) from text and files with
HMAC (HMAC-SHA1) or CBC-BlockCipherMAC with IV.

Damit solltest du das hin bekommen denke ich.

Tobi
Lesen Sie weiter auf narkive:
Loading...