如何生成HMAC-SHA1在C#中? [英] How to generate HMAC-SHA1 in 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屋!