it-swarm.com.de

Wie erzeugt man HMAC-SHA1 in C #?

Ich versuche, eine REST API mit C # zu verwenden. Der API-Ersteller hat Beispielbibliotheken in PHP, Ruby und Java bereitgestellt. Ich werde aufgehängt auf einem Teil davon, wo ich ein HMAC erzeugen muss.

In den bereitgestellten Beispielbibliotheken wird folgendermaßen vorgegangen.

[~ # ~] 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. UPDATE: Das folgende C # -Beispiel funktioniert einwandfrei. Ich habe herausgefunden, dass das eigentliche Problem auf einige plattformübergreifende Unterschiede bei den Zeilenumbrüchen in meinem signatureString zurückzuführen ist.

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();
44
jessegavin

eine Erweiterung zu Vimvq1987s Antwort :

return hashValue.ToString(); erzeugt nicht die Ausgabe, die Sie wollen/brauchen. Sie müssen die Bytes im Array hashValue in ihre hexadezimale Darstellung konvertieren.
Kann so einfach sein wie return BitConverter.toString(hashValue); (druckt Großbuchstaben von A bis F) oder wenn Sie es etwas komplexer mögen:

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

welche 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";
}

edit: Dmitriy Nemykin hat folgende Änderung vorgeschlagen

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 betont hat, ist das sing statement ein guter Punkt.

30
VolkerK

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

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

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();
}
5
Vimvq1987