2016-08-12 93 views
5

我在C#下面的代碼計算簽名/哈希在Javascript和有相同的結果,C#

var apiKey = "SBB3aWxsIG1ha2UgbXbcQVBJIHN|Y3VyZQ=="; 
var apiSecret = "QaTW3xlf1U5ljdlAJSdltzT71fFF+eZ="; 

var key = Convert.FromBase64String(apiSecret); 
var provider = new System.Security.Cryptography.HMACSHA256(key); 

var hash = provider.ComputeHash(Encoding.UTF8.GetBytes(apiKey)); 
var signature = Convert.ToBase64String(hash); 

我試圖使用CryptJS庫但我可以告訴我得到同樣的結果在Javascript我沒有將密鑰和祕密轉換爲字節數組,編碼不正確。第一次嘗試是這樣的:

var apiKey = "SBB3aWxsIG1ha2UgbXbcQVBJIHN|Y3VyZQ=="; 
var apiSecret = "QaTW3xlf1U5ljdlAJSdltzT71fFF+eZ="; 
var hash = CryptoJS.HmacSHA256(apiKey, apiSecret); 
var sig = hash.toString(CryptoJS.enc.Base64); 
+2

閱讀,你在這裏再次發佈的代碼。你忘了在CryptoJS中解析Base64編碼的'apiSecret'。更糟的是,你完全忘記了將'apiKey'和'apiSecret'傳遞給'CryptoJS.HmacSHA256'。 –

+0

這是CryptoJS文檔原始代碼的快速剪切和粘貼。傳遞正確的值仍然不能解決它,但謝謝指出。你有任何真正的洞察力,使其工作? –

+1

是的,我有實際的見解,我已經與你分享。你已經應該有工具來使它工作。用CryptoJS解析Base64編碼的字符串有困難嗎?如果沒有,你是否將參數的順序交給了'CryptoJS.HmacSHA256'? –

回答

8

啓發由https://stackoverflow.com/a/13837543/1810391

的Javascript

var CryptoJS = require('crypto-js'); 

var apiKey = "SBB3aWxsIG1ha2UgbXbcQVBJIHN|Y3VyZQ=="; 
var apiSecret = "QaTW3xlf1U5ljdlAJSdltzT71fFF+eZ="; 

// var key = Convert.FromBase64String(apiSecret); 
var key = CryptoJS.enc.Base64.parse(apiSecret); 
console.log('key:' + key); 

// var prehash = Encoding.UTF8.GetBytes(apiKey); 
var prehash = CryptoJS.enc.Utf8.parse(apiKey); 
console.log('Pre-hash:' + prehash); 

// var provider = new System.Security.Cryptography.HMACSHA256(key); 
// var hash = provider.ComputeHash(prehash); 
var hash = CryptoJS.HmacSHA256(prehash, key); 
console.log('hash:' + hash); 

//var signature = Convert.ToBase64String(hash); 
var signature = hash.toString(CryptoJS.enc.Base64); 
console.log('signature:' + signature); 

的Javascript輸出

key:41a4d6df195fd54e658dd940252765b734fbd5f145f9e6 
Pre-hash:53424233615778734947316861325567625862635156424a49484e7c593356795a513d3d 
hash:ecb6cdf5dd39872bb2cbce4321e2725e11b99c01af9c2a620ebbaf3d8d8607e7 
signature:7LbN9d05hyuyy85DIeJyXhG5nAGvnCpiDruvPY2GB+c= 

C#

using System; 
using System.Text; 

namespace ConsoleApplication 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      var apiKey = "SBB3aWxsIG1ha2UgbXbcQVBJIHN|Y3VyZQ=="; 
      var apiSecret = "QaTW3xlf1U5ljdlAJSdltzT71fFF+eZ="; 
      var key = Convert.FromBase64String(apiSecret); 
      Console.Write("key:"); 
      prtByte(key); 

      Console.Write("Pre-hash:"); 
      prtByte(Encoding.UTF8.GetBytes(apiKey)); 
      var provider = new System.Security.Cryptography.HMACSHA256(key); 
      var hash = provider.ComputeHash(Encoding.UTF8.GetBytes(apiKey)); 
      Console.Write("hash:"); 
      prtByte(hash); 

      var signature = Convert.ToBase64String(hash); 
      Console.WriteLine("signature:" + signature); 
     } 
     public static void prtByte(byte[] b) 
     { 
      for (var i = 0; i < b.Length; i++) 
      { 
       Console.Write(b[i].ToString("x2")); 
      } 
      Console.WriteLine(); 
     } 
    } 
} 

C#輸出

key:41a4d6df195fd54e658dd940252765b734fbd5f145f9e6 
Pre-hash:53424233615778734947316861325567625862635156424a49484e7c593356795a513d3d 
hash:ecb6cdf5dd39872bb2cbce4321e2725e11b99c01af9c2a620ebbaf3d8d8607e7 
signature:7LbN9d05hyuyy85DIeJyXhG5nAGvnCpiDruvPY2GB+c= 
+0

嗨,約翰,非常感謝你抽出時間。對此,我真的非常感激。這裏的問題是我的原始C#是正確的,我需要JS來計算與我提供的C#相同的簽名。簽名看起來像UufyTxE87/MsjPkLVBBm39G5H1O4bnMj17qSXqyO2/0 =。也許你很近?再次感謝您抽出時間。不知道人們爲什麼低估這一點。 –

+1

@billyjean我的C#實際上是你的代碼,唯一的變化就是所有的'Console.Write'。我在Windows 10和OS X盒子上進行了測試,並且c#和js都給出了相同的結果。你是否使用了你在問題中發佈的相同的'apiKey'和'apiSecret'? –

+0

約翰,你是完全正確的。對困惑感到抱歉。我只是再次通過您的代碼,將其實施到我的解決方案中並重試,並且一切正常。非常感謝。希望我有更多的發送比代表。再次不確定爲什麼這是downvoted。這是解決此問題的唯一完整解決方案。對於所有嘗試使用JS連接到.NET API的用戶而言,這是一個問題,需要使用此安全機制。 –