代码之家  ›  专栏  ›  技术社区  ›  William Yeung

Ruby中的hmac-sha1与c hmac sha1不同

  •  8
  • William Yeung  · 技术社区  · 15 年前

    我正在尝试测试来自的API ankoder.com 并对 authentication token . 当我试图从C调用时,示例是Ruby。当我比较hmac-sha1中的摘要结果时,我发现passkey结果有问题。

    为了便于测试,以下是代码:

    require 'hmac-sha1'
    require 'digest/sha1'
    require 'base64'
    token="-Sat, 14 Nov 2009 09:47:53 GMT-GET-/video.xml-"
    private_key="whatever"
    salt=Digest::SHA1.hexdigest(token)[0..19]
    passkey=Base64.encode64(HMAC::SHA1.digest(private_key, salt)).strip
    

    结果是:“x/0engstyf7l8e7lvoihtmletlm=\n” 如果我在c中尝试以下方法:

    const string PrivateKey = "whatever";
    
    var date = "Sat, 14 Nov 2009 09:47:53 GMT";//DateTime.Now.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss") + " GMT";
    string token=string.Format("-{0}-GET-/video.xml-", date);
    
    var salt_binary=SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(token));
    var salt_hex=BitConverter.ToString(salt_binary).Replace("-", "").ToLower();
    var salt =salt_hex.Substring(0,20);
    
    var hmac_sha1 =
                new HMACSHA1(Encoding.ASCII.GetBytes(salt));
    hmac_sha1.Initialize();
    
    var private_key_binary = Encoding.ASCII.GetBytes(PrivateKey);
    var passkey_binary = hmac_sha1.ComputeHash(private_key_binary,0,private_key_binary.Length);
    
    var passkey = Convert.ToBase64String(passkey_binary).Trim();
    

    salt结果相同,但passkey结果不同-c给出:

    QLC68XJQLEBRUWBVWR7EUUFHW/K型=

    两者都产生盐:f5cab5092f9271d43d2e

    有什么好主意吗?

    2 回复  |  直到 11 年前
        1
  •  10
  •   Emerick Rogul    15 年前

    你已经把 PrivateKey salt 根据Ruby代码,在C代码中的错误位置, 私人钥匙 是HMAC的秘密钥匙。

    还要注意,您已经在Ruby程序生成的哈希的末尾包含了一个换行符(无论如何,根据您的示例输出)。你必须 包括换行符或哈希不匹配。

    这个C程序纠正了第一个问题:

    using System;
    using System.Security.Cryptography;
    using System.Text;
    
    namespace Hasher
    {
      class Program
      {
        static void Main(string[] args)
        {
          const string PrivateKey = "whatever";
    
          string date = "Sat, 14 Nov 2009 09:47:53 GMT";
          string token = string.Format("-{0}-GET-/video.xml-", date);
    
          byte[] salt_binary = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(token));
          string salt_hex = BitConverter.ToString(salt_binary).Replace("-", "").ToLower();
          string salt = salt_hex.Substring(0, 20);
    
          HMACSHA1 hmac_sha1 = new HMACSHA1(Encoding.ASCII.GetBytes(PrivateKey));
          hmac_sha1.Initialize();
    
          byte[] private_key_binary = Encoding.ASCII.GetBytes(salt);
          byte[] passkey_binary = hmac_sha1.ComputeHash(private_key_binary, 0, private_key_binary.Length);
    
          string passkey = Convert.ToBase64String(passkey_binary).Trim();
        }
      }
    }
    
        2
  •  3
  •   ZZ Coder    15 年前

    我看到2个问题,

    1. 钥匙/数据被颠倒了。在Ruby中,私钥是密钥,salt是数据。在C中,你做了相反的事情。
    2. 如果任何字符串中允许使用非ASCII码,则必须确保使用相同的编码。Ruby将所有内容都视为原始字节,因此C必须与其编码匹配。如果使用jcode,c中的编码应该与$kcode匹配。