如何生成HMAC-SHA1在C#中? [英] How to generate HMAC-SHA1 in C#?

查看:161
本文介绍了如何生成HMAC-SHA1在C#中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图利用使用C#中的REST API的。该API创建者在PHP,Ruby和Java的提供的样本库。我收到挂在它的一个组成部分,我需要生成一个 HMAC



下面是它是如何在他们所提供的样本库进行。



PHP

  hash_hmac('SHA1',$ signatureString,$ SecretKey的,虚假的); 



红宝石



 消化=的OpenSSL ::摘要:: Digest.new(SHA1)
返回的OpenSSL :: HMAC.hexdigest(消化,SecretKey的,signatureString)

的Java

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

的MAC MAC = NULL;
的MAC = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);

字节[]字节= mac.doFinal(signatureString.getBytes());

字符串格式=;
的for(int i = 0; I< bytes.length;我++)
{
字符串str = Integer.toHexString(((int)的字节[I])及0xFF的);
如果(str.length()== 1)
{
海峡=0+ STR;
}

=表格形式+ STR;
}
申报表;



这是我在C#中的尝试。 <击>它不工作更新:的C#示例下面工作得很好。我发现,真正的问题是由于我的 signatureString



<$ p在换行符一些跨平台的差异$ p> VAR ENC = Encoding.ASCII;
HMACSHA1 HMAC =新HMACSHA1(enc.GetBytes(SecretKey的));
hmac.Initialize();

字节[]缓冲= enc.GetBytes(signatureString);
返回BitConverter.ToString(hmac.ComputeHash(缓冲液))替换( - ,).ToLower();



该API一个错误说法回应说,我的 HMAC 是无效的。任何想法?


解决方案

延期的 Vimvq1987的回答



收益hashValue.ToString( ); 不产生你想要的输出/需要。你必须转换为字节数组散列值其十六进制字符串表示。照片
可以像简单返回BitConverter的ToString(散列值); (打印大写字母AF),或者如果你喜欢它更复杂一点:

 使用系统; 
使用System.Collections.Generic;
使用System.Linq的;
使用System.Text;
使用System.Security.Cryptography;
:使用System.IO;

命名ConsoleApplication1
{
类节目
{
公共静态字符串编码(字符串输入,字节[]键)
{
HMACSHA1 myhmacsha1 =新HMACSHA1(密钥);
字节[]的字节数组= Encoding.ASCII.GetBytes(输入);
MemoryStream的流=新的MemoryStream(字节阵列);
返回myhmacsha1.ComputeHash(流).Aggregate(,(S,E)=> S +的String.Format({0:X2},e)中,S =>氏);
}


静态无效的主要(字串[] args)
{
的byte []键= Encoding.ASCII.GetBytes(ABCDEFGHIJKLMNOPQRSTUVWXYZ) ;
列输入=;
的foreach(字符串s在新的String [] {结婚,有,A,小,羊肉})
{
输入+ = S;
的System.Console.WriteLine(编码(输入,键));
}
的回报;
}
}
}



这版画



  3545e064fb59bc4bfc02b6e1c3d4925c898aa504 
3249f4c8468d4d67f465937da05b809eaff22fdb
87baaadf5d096677f944015e53d283834eb1e943
6325376820c29a09e3ab30db000033aa71d6927d
54579b0146e2476595381d837ee38863be358213

和我获得



完全相同的结果

 < PHP 
$ SecretKey的='ABCDEFGHIJKLMNOPQRSTUVWXYZ';

$ signatureString ='';
的foreach(阵列('结婚','有','A','小','羊肉')为$ S){
$ signatureString = $ S。
回声hash_hmac(SHA1',$ signatureString,$ SecretKey的,假的),\\\

}






编辑:德米特里Nemykin 提出以下修改

 公共静态字符串编码(字符串输入,字节[]键)
{
字节[]的字节数组= Encoding.ASCII.GetBytes(输入);使用(VAR myhmacsha1 =新HMACSHA1(密钥))
{
VAR hashArray = myhmacsha1.ComputeHash(字节阵列)
;
返回hashArray.Aggregate(,(S,E)=> S +的String.Format({0:X2},E),S => S);
}
}



这遭到了拒绝。但正如詹姆斯已经评论指出,这个答案最起码的 using语句的好点。


I am trying to make use of a REST API using C#. The API creator has provided sample libraries in PHP, Ruby and Java. I am getting hung up on one part of it where I need to generate an HMAC.

Here's how it is done in the sample libraries they have provided.

PHP

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

Ruby

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;

Here's my attempt in C#. It is not working. UPDATE: The C# example below works just fine. I found out that the real problem was due to some cross-platform differences in newline characters in my 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();

The API responds with an error saying that my HMAC is invalid. Any ideas?

解决方案

an extension to Vimvq1987's answer:

return hashValue.ToString(); doesn't produce the output you want/need. You have to convert the bytes in the array hashValue to their hex-string representation.
Can be as simple as return BitConverter.toString(hashValue); (prints upper-case letters A-F) or if you like it a bit more complex:

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

which prints

3545e064fb59bc4bfc02b6e1c3d4925c898aa504
3249f4c8468d4d67f465937da05b809eaff22fdb
87baaadf5d096677f944015e53d283834eb1e943
6325376820c29a09e3ab30db000033aa71d6927d
54579b0146e2476595381d837ee38863be358213

and I get the exact same result for

<?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 suggested the following edit

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

which was rejected. But as James already pointed out in a comment to this answer at the very least the using statement is a good point.

这篇关于如何生成HMAC-SHA1在C#中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆