web-dev-qa-db-fra.com

C # équivalent à hash_hmac dans PHP

en utilisant .NET et C #, je dois fournir une chaîne d'intégrité en utilisant HMAC SHA512 à un serveur PHP. Utilisation en C #:

Encoding encoding = Encoding.UTF8;
byte[] keyByte = encoding.GetBytes(key);
HMACSHA512 hmacsha512 = new HMACSHA512(keyByte);
byte[] messageBytes = encoding.GetBytes(message);
byte[]  hashmessage = hmacsha512.ComputeHash(messageBytes);
return(ByteToString(hashmessage).toUpper());

Mais cela ne correspond pas avec PHP hash_hmac () PHP code:

$hmac = strtoupper(hash_hmac($pbx_hash, $msg, $binKey));

J'essaye de changer l'encodage en C # (utf8, ASCII, Unicode) Sans succès.

J'ai essayé de nombreuses solutions trouvées sur le net mais rien ne donne la même chaîne :(

Je ne peux pas changer le code PHP, et je ne vois pas ce qui ne va pas en C #

Edit Ceci est ByteToString (copié à partir du commentaire):

static string ByteToString(byte[] buff)
{
    string sbinary = "";
    for (int i = 0; i < buff.Length; i++)
    {
        sbinary += buff[i].ToString("X2"); /* hex format */
    }
    return (sbinary);
}    

Après de nombreux tets, j'ai trouvé que j'obtiens les mêmes résultats si PHP hash_hmac key est une chaîne, pas un tableau d'octets. Il semble que le problème vient du PHP = fonction de conversion $ binKey = pack ("H *", $ keyTest);

26
Philippe

Le problème doit être la représentation réelle des données de clé/message.

Voir les tests suivants:

PHP

#!/usr/bin/php
<?php
print strtoupper(hash_hmac("sha256", "message", "key"));
?>

Sortie (en direct via http://writecodeonline.com/php/ ):

6E9EF29B75FFFC5B7ABAE527D58FDADB2FE42E7219011976917343065F58ED4A

C#

using System;
using System.Text;
using System.Security.Cryptography;

public class Program
{
    private const string key = "key";
    private const string message = "message";
    private static readonly Encoding encoding = Encoding.UTF8; 

    static void Main(string[] args)
    {
        var keyByte = encoding.GetBytes(key);
        using (var hmacsha256 = new HMACSHA256(keyByte))
        {
            hmacsha256.ComputeHash(encoding.GetBytes(message));

            Console.WriteLine("Result: {0}", ByteToString(hmacsha256.Hash));
        }
    }
    static string ByteToString(byte[] buff)
    {
        string sbinary = "";
        for (int i = 0; i < buff.Length; i++)
            sbinary += buff[i].ToString("X2"); /* hex format */
        return sbinary;
    }    
}

Sortie (en direct via http://ideone.com/JdpeL ):

Result: 6E9EF29B75FFFC5B7ABAE527D58FDADB2FE42E7219011976917343065F58ED4A

Vérifiez donc le jeu de caractères/l'encodage des données d'entrée PHP. Vérifiez également l'algorithme réel (dans $pbx_hash).

33
sehe
    private static string HashHmac(string message, string secret)
    {
        Encoding encoding = Encoding.UTF8;
        using (HMACSHA512 hmac = new HMACSHA512(encoding.GetBytes(secret)))
        {
            var msg = encoding.GetBytes(message);
            var hash = hmac.ComputeHash(msg);
            return BitConverter.ToString(hash).ToLower().Replace("-", string.Empty);
        }
    }
13
Micah Osborne

Comme dit plus haut, le problème était avec PHP Pack (fonction H * utilisée pour convertir la clé en tableau d'octets. C # Getbytes ne donne pas le même résultat (utf8, asci, unicode ...) . La solution trouvée ici: http://www.nuronconsulting.com/c-pack-h.aspx était ok pour moi. Maintenant HMAC de C # correspond avec PHP =!

public static byte[] PackH(string hex)
{
       if ((hex.Length % 2) == 1) hex += '0';
       byte[] bytes = new byte[hex.Length / 2];
       for (int i = 0; i < hex.Length; i += 2)
       {
             bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
       }
 return bytes;
}

Manu merci à tous pour votre aide.

3
Philippe