Wie generiert man HMAC-SHA1 in C#?

Lesezeit: 4 Minuten

Benutzer-Avatar
Jessegavin

Ich versuche, eine REST-API mit C # zu verwenden. Der API-Ersteller hat Beispielbibliotheken in PHP, Ruby und Java bereitgestellt. Ich hänge an einem Teil davon fest, wo ich eine generieren muss HMAC.

So wird es in den von ihnen bereitgestellten Beispielbibliotheken gemacht.

PHP

hash_hmac('sha1', $signatureString, $secretKey, false);

Rubin

digest = OpenSSL::Digest::Digest.new('sha1')
return OpenSSL::HMAC.hexdigest(digest, secretKey, signatureString)

Java

SecretKeySpec signingKey = new SecretKeySpec(secretKey.getBytes(), HMAC_SHA1_ALGORITHM);

Mac mac = null;
mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);

byte[] bytes = mac.doFinal(signatureString.getBytes());

String form = "";
for (int i = 0; i < bytes.length; i++)
{
    String str = Integer.toHexString(((int)bytes[i]) & 0xff);
    if (str.length() == 1)
    {
        str = "0" + str;
    }

    form = form + str;
}
return form;

Hier ist mein Versuch in C#. Es funktioniert nicht. AKTUALISIEREN: Das folgende C#-Beispiel funktioniert einwandfrei. Ich fand heraus, dass das eigentliche Problem auf einigen plattformübergreifenden Unterschieden bei den Zeilenumbruchzeichen in meinem lag signatureString.

var enc = Encoding.ASCII;
HMACSHA1 hmac = new HMACSHA1(enc.GetBytes(secretKey));
hmac.Initialize();

byte[] buffer = enc.GetBytes(signatureString);
return BitConverter.ToString(hmac.ComputeHash(buffer)).Replace("-", "").ToLower();

  • Es stellt sich heraus, dass mein C#-Code einwandfrei funktioniert. Das eigentliche Problem lag an einigen plattformübergreifenden Unterschieden bei Zeilenumbrüchen in meinem the signatureString. Ich werde diese Frage zum Löschen markieren.

    – Jessegavin

    20. Mai 2011 um 17:07 Uhr


  • Anstatt die Frage zu löschen, posten Sie Ihren Code als Antwort und akzeptieren Sie ihn. Diese Frage ist sehr nützlich, wenn Sie dasselbe tun möchten.

    – Serhat Özgel

    4. Dezember 2015 um 11:08 Uhr

  • Ich habe ein weiteres Update zum Text “Die API antwortet…” hinzugefügt, um mögliche Missverständnisse zu vermeiden

    – Ciro Corvino

    27. Oktober 2016 um 9:39 Uhr

Benutzer-Avatar
VolkerK

eine Erweiterung der Antwort von Vimvq1987:

return hashValue.ToString(); erzeugt nicht die Ausgabe, die Sie wollen/brauchen. Sie müssen die Bytes im Array konvertieren hashValue zu ihrer Hex-String-Darstellung.
Kann so einfach sein wie return BitConverter.toString(hashValue); (druckt Großbuchstaben AF) oder wer es etwas komplexer mag:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        public static string Encode(string input, byte[] key)
        {
            HMACSHA1 myhmacsha1 = new HMACSHA1(key);
            byte[] byteArray = Encoding.ASCII.GetBytes(input);
            MemoryStream stream = new MemoryStream(byteArray);
            return myhmacsha1.ComputeHash(stream).Aggregate("", (s, e) => s + String.Format("{0:x2}",e), s => s );
        }


        static void Main(string[] args)
        {
            byte[] key = Encoding.ASCII.GetBytes("abcdefghijklmnopqrstuvwxyz");
            string input = "";
            foreach (string s in new string[] { "Marry", " had", " a", " little", " lamb" })
            {
                input += s;
                System.Console.WriteLine( Encode(input, key) );
            }
            return;
        }
    }
}

was druckt

3545e064fb59bc4bfc02b6e1c3d4925c898aa504
3249f4c8468d4d67f465937da05b809eaff22fdb
87baaadf5d096677f944015e53d283834eb1e943
6325376820c29a09e3ab30db000033aa71d6927d
54579b0146e2476595381d837ee38863be358213

und ich bekomme genau das gleiche Ergebnis für

<?php
$secretKey = 'abcdefghijklmnopqrstuvwxyz';

$signatureString = '';
foreach( array('Marry',' had',' a',' little',' lamb') as $s ) {
    $signatureString .= $s;
    echo hash_hmac('sha1', $signatureString, $secretKey, false), "\n";
}

Bearbeiten: Dmitriy Nemykin schlug die folgende Bearbeitung vor

public static string Encode(string input, byte[] key)
{
    byte[] byteArray = Encoding.ASCII.GetBytes(input);
    using(var myhmacsha1 = new HMACSHA1(key))
    {
        var hashArray = myhmacsha1.ComputeHash(byteArray);
        return hashArray.Aggregate("", (s, e) => s + String.Format("{0:x2}",e), s => s );
    }
}

was abgelehnt wurde. Aber wie James bereits in einem Kommentar zu dieser Antwort anmerkte, zumindest das using-Anweisung ist ein guter Punkt.

  • myhmacsha1.ComputeHash(stream).Aggregate Geben Sie einen Fehler: Das Aggregat ist nicht für System.array definiert. Vermisse ich etwas?

    – Roee Gavirel

    26. Dezember 2011 um 13:20 Uhr

  • Hängt von der .net-Version ab, die Sie verwenden, siehe msdn.microsoft.com/en-us/library/bb548651%28v=VS.90%29.aspx

    – VolkerK

    26. Dezember 2011 um 20:23 Uhr

  • ho. das ist es. Vielen Dank.

    – Roee Gavirel

    27. Dezember 2011 um 6:44 Uhr

  • Ist der MemoryStream hier notwendig? Kann Ihr Code nicht gekürzt werden? myhmacsha1.ComputeHash(byteArray)? Außerdem sollten Sie erwägen, Ihre zu verpacken HMACSHA1 mit einer using blockieren (und die MemoryStream falls erforderlich).

    – James

    3. September 2012 um 20:26 Uhr


  • VolkerK = Heldenstatus

    – Joe Schmucker

    17. März 2021 um 17:51 Uhr

Diese Seite hat einige ziemlich gute Beispiele für Sprachen: http://jokecamp.wordpress.com/2012/10/21/examples-of-creating-base64-hashes-using-hmac-sha256-in-different-languages/

Die c#-Implementierung zum Zeitpunkt des Schreibens ist:

private string CreateToken(string message, string secret)
{
 secret = secret ?? "";
 var encoding = new System.Text.ASCIIEncoding();
 byte[] keyByte = encoding.GetBytes(secret);
 byte[] messageBytes = encoding.GetBytes(message);
 using (var hmacsha256 = new HMACSHA256(keyByte))
 {
 byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
 return Convert.ToBase64String(hashmessage);
 }
}

Versuche dies:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha1.aspx

schneller und schmutziger Code:

public string Encode(string input, byte [] key)
{
        HMACSHA1 myhmacsha1 = new HMACSHA1(key);
        byte[] byteArray = Encoding.ASCII.GetBytes( input );
        MemoryStream stream = new MemoryStream( byteArray ); 
        byte[] hashValue = myhmacsha1.ComputeHash(stream);
        return hashValue.ToString();
}

  • Danke für die Antwort. Ihr Code gibt jedoch die Zeichenfolge zurück System.Byte[]. Also habe ich die letzte Zeile geändert return BitConverter.ToString(hashValue).Replace("-","").ToLower() aber ich bin immer noch nicht in der Lage, diesen C#-Code dazu zu bringen, denselben Hash wie die anderen Sprachen zu generieren.

    – Jessegavin

    20. Mai 2011 um 15:54 Uhr

  • Super spät aber string.Join("", Array.ConvertAll(hashValue, b => b.ToString("x2"))) sollte arbeiten.

    – Jason Larke

    31. Januar 2013 um 4:43 Uhr


1317860cookie-checkWie generiert man HMAC-SHA1 in C#?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy