Shopify C# HMAC SHA256 OAuth 验证

3
我正在尝试在OAUTH请求期间验证Shopify HMAC,但我生成的哈希值与请求中提供的不匹配。
我找到了一些其他的线程,但它们要么过时(either outdated),因为文档现在声明使用GET请求而不是POST,要么在Java中没有得到回答(unanswered)。
我的C#代码如下:
string key = "mysecretkey";

string message = string.Format("shop={0}&timestamp={1}", shop, timestamp);

System.Text.ASCIIEncoding encoding = new ASCIIEncoding();

byte[] keyBytes = encoding.GetBytes(key);

byte[] messageBytes = encoding.GetBytes(message);

System.Security.Cryptography.HMACSHA256 cryptographer = new System.Security.Cryptography.HMACSHA256(keyBytes);

byte[] bytes = cryptographer.ComputeHash(messageBytes);

string digest = BitConverter.ToString(bytes).Replace("-", "");

bool valid = digest == hmac.ToUpper();

我猜测信息构建有误,但是我已经按照官方文档的指导操作了,但没有成功。
请问有人可以帮忙吗?

您正在计算 HMAC,但未使用密钥。文档指出应使用共享密钥生成 HMAC 摘要。在计算哈希之前,请尝试设置 cryptographer.Key = keyBytes; - Oguz Ozgul
2
尝试使用以下字符串:code=code&shop=shop&state=state&timestamp=timestamp; 这对我有用。 - Parag Jadhav
谢谢Parag。我怀疑这可能是原因,但无论我使用什么参数组合,它仍然无法工作。我已经向Shopify的开发人员寻求帮助,我们将看看他们会说什么。 - Guy Lowe
2
@Parag 是正确的。根据文档,您只需删除 hmac 和 signature 字段,并使用剩余变量计算 hmac。将来,如果 Shopify 决定在响应中添加另一个变量,则 hmac 计算也应包括该变量。感谢 Parag。 - Sasi varna kumar
3个回答

6

好的,Shopify公司的开发人员已经回复了我的问题。看起来你需要按照字母顺序哈希查询字符串的全部内容,除了签名和hmac以外。我自己添加了一个参数(rlr),还有一个在文档中没有提到的参数(state)。

 string message = "";// "code=7af66fd73427a1634cee3103297230b8&rlr=9DFD5EA9-7747-4142-97D9-2D44BBA442F1&shop=appswiz.myshopify.com&state=fa992b8f-762e-4813-b707-6044e71ad3b5&timestamp=1448856806";
        message = "code=xxxxxxxx";
        message += "&rlr=xxxxx";
        message += "&shop=xxx.myshopify.com";
        message += "&state=xxxxxxxx";
        message += "&timestamp=1449111190";
        hmac = "xxxxxxx";
        System.Text.ASCIIEncoding encoding = new ASCIIEncoding();
        byte[] keyBytes = encoding.GetBytes(key);
        byte[] messageBytes = encoding.GetBytes(message);
        System.Security.Cryptography.HMACSHA256 cryptographer = new System.Security.Cryptography.HMACSHA256(keyBytes);

        byte[] bytes = cryptographer.ComputeHash(messageBytes);

        string digest = BitConverter.ToString(bytes).Replace("-", "");
        return digest == hmac.ToUpper();

现在这个可以工作了。


1

您正在计算HMAC,但没有使用密钥。

文档说明应使用共享密钥生成HMAC摘要。没有密钥的HMAC值有什么意义呢?如果Shopify没有在您和他们之间使用预共享密钥来计算HMAC,则任何人都可以模仿Shopify服务器。

以下代码块来自文档:

digest = OpenSSL::Digest.new('sha256')
secret = "hush"
message = "shop=some-shop.myshopify.com&timestamp=1337178173"

digest = OpenSSL::HMAC.hexdigest(digest, secret, message)
digest == "2cb1a277650a659f1b11e92a4a64275b128e037f2c3390e3c8fd2d8721dac9e2"

因此,在计算哈希之前,请尝试cryptographer.Key = keyBytes;
byte[] keyBytes = encoding.GetBytes(key);

byte[] messageBytes = encoding.GetBytes(message);

System.Security.Cryptography.HMACSHA256 cryptographer = new System.Security.Cryptography.HMACSHA256(keyBytes);

cryptographer.Key = keyBytes;

byte[] bytes = cryptographer.ComputeHash(messageBytes);

谢谢,但密钥是HMACSHA256类的构造函数的一部分。 - Guy Lowe
哦,我疏忽了,抱歉。 - Oguz Ozgul
你的密码中有没有非 ASCII 字符? - Oguz Ozgul
谢谢Oguz,这个秘密是一个十六进制字符串,所以不行。 - Guy Lowe

0

借鉴Guy Lowe的答案,我最近使这个工作起来了:

    public bool ValidateShopifyHmac(string hmacHeader, string localData, string apiSecret) {
        var ascii = new ASCIIEncoding();
        var secretBytes = ascii.GetBytes(apiSecret);
        var cryptographer = new System.Security.Cryptography.HMACSHA256(secretBytes);
        var messageBytes = ascii.GetBytes(localData);
        var hashedMessage = cryptographer.ComputeHash(messageBytes);
        var digest = BitConverter.ToString(hashedMessage).Replace("-", "");
        return digest == hmacHeader.ToUpper();
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接