【问题标题】:Is there a simpler way to calculate this MD5 hash?有没有更简单的方法来计算这个 MD5 哈希?
【发布时间】:2011-09-23 16:29:21
【问题描述】:

我正在实施托管结帐,托管结帐应该将用户重定向回我的网站,以便我可以显示自定义收据页面。

这是我要返回的示例查询字符串:

trnApproved=0&trnId=10000000&messageId=71&messageText=Declined&authCode=000000&responseType=T&trnAmount=20.00&trnDate=9%2f23%2f2011+9%3a30%3a56+AM&trnOrderNumber=1000000&trnLanguage=eng&trnCustomerName=FirstName+LastName&trnEmailAddress=something_something%40gmail.com&trnPhoneNumber=1235550123&avsProcessed= 0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=Address+Verification+not+performed+for+this+transaction.&cvdId=3&cardType=VI&trnType=P&paymentMethod=CC&ref1=9dae6af7-7c22-4697-b23a-413d8a129a75&ref2=&ref3=&ref2=&ref3=& &hashValue=33dacf84682470f267b2cc6d528b1594

为了验证请求,我应该从查询字符串的末尾删除&hashValue=f3cf58ef0fd363e0c2241938b04f1068,然后附加一个键。然后我对整个字符串进行 MD5 哈希,结果应该是33dacf84682470f267b2cc6d528b1594,和原来的一样。

这很容易,只是一些字段对我造成了问题。这是我使用的代码(取自一个虚拟应用程序,因此您可以忽略一些错误的编码):

// Split up the query string parameters
string[] parameters = GetQueryString().Split(new[] { "&" }, StringSplitOptions.None);
var querySet = new List<string>();

// Rebuild the query string, encoding the values.
foreach (string s in parameters)
{
    // Every field that contains a "." will need to be encoded except for trnAmount
    querySet.Add(param.Contains("trnAmount") ? param : UrlEncodeToUpper(param));
}

// Create the querystring without the hashValue, we need to calculate our hash without it.
string qs = string.Join("&", querySet.ToArray());
qs = qs.Substring(0, qs.IndexOf("&hashValue"));
qs = qs + "fb76124fea73488fa11995dfa4cbe89b";

var encoding = new UTF8Encoding();
var md5 = new MD5CryptoServiceProvider();
var hash = md5.ComputeHash(encoding.GetBytes(qs));

var calculatedHash = BitConverter.ToString(hash).Replace("-", String.Empty).ToLower();

这是我使用的 UrlEncode 方法。

private static string UrlEncodeToUpper(string value)
{
    // Convert their encoding into uppercase so we can do our hash
    value = Regex.Replace(value, "(%[0-9af][0-9a-f])", c => c.Value.ToUpper());
    // Encode the characters that they missed
    value = value.Replace("-", "%2D").Replace(".", "%2E").Replace("_", "%5F");
    return value;
}

这一切都有效(直到有人输入了我没有考虑过的角色),除了这似乎比它应该的更复杂。我知道我不是唯一一个必须将这个 HCO 实现到 ASP.NET 应用程序中的人,所以我认为简单的验证不应该这么复杂。

我错过了一种更简单的方法吗?必须遍历字段,对其中一些进行编码,同时跳过其他字段,将它们的编码转换为大写,然后选择性地替换字符似乎有点……奇怪。

【问题讨论】:

  • 是的,一个 GET 请求会改变状态...最好希望 Google 有足够的钱来支付它将从您的网站上购买的所有东西!
  • @Blindy,改变状态?此请求不会更改任何内容。我们只是向将要通过身份验证的用户显示收据。
  • 你可以发帖而不是使用查询字符串吗?
  • GetQueryString() 是做什么的?
  • @Jacob,在生产站点中它只是调用 HttpContext.Current.Request.QueryString,在我的小虚拟应用程序中它只是调用那个确切的字符串。

标签: c# asp.net md5


【解决方案1】:

这是处理查询字符串的更好方法:

var queryString = "trnApproved=0&trnId=10000000&messageId=71&messageText=Declined&authCode=000000&responseType=T&trnAmount=20.00&trnDate=9%2f23%2f2011+9%3a30%3a56+AM&trnOrderNumber=1000000&trnLanguage=eng&trnCustomerName=FirstName+LastName&trnEmailAddress=something_something%40gmail.com&trnPhoneNumber=1235550123&avsProcessed=0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=Address+Verification+not+performed+for+this+transaction.&cvdId=3&cardType=VI&trnType=P&paymentMethod=CC&ref1=9dae6af7-7c22-4697-b23a-413d8a129a75&ref2=&ref3=&ref4=&ref5=&hashValue=33dacf84682470f267b2cc6d528b1594";
var values = HttpUtility.ParseQueryString(queryString);
// remove the hashValue parameter
values.Remove("hashValue");
var result = values.ToString();
// At this stage result = trnApproved=0&trnId=10000000&messageId=71&messageText=Declined&authCode=000000&responseType=T&trnAmount=20.00&trnDate=9%2f23%2f2011+9%3a30%3a56+AM&trnOrderNumber=1000000&trnLanguage=eng&trnCustomerName=FirstName+LastName&trnEmailAddress=something_something%40gmail.com&trnPhoneNumber=1235550123&avsProcessed=0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=Address+Verification+not+performed+for+this+transaction.&cvdId=3&cardType=VI&trnType=P&paymentMethod=CC&ref1=9dae6af7-7c22-4697-b23a-413d8a129a75&ref2=&ref3=&ref4=&ref5=

// now add some other query string value
values["foo"] = "bar"; // you can stuff whatever you want it will be properly url encoded

那我不太明白你想做什么。您想对结果计算 MD5 吗?您可以这样做,然后附加到查询字符串。

【讨论】:

  • 问题是我不能只删除 hashValue 并进行哈希处理,因为在进行哈希处理之前,我需要遍历字段并“修复”某些字符的编码根据他们给我的回复。
  • @Brandon,你说的修复某些字符的编码是什么意思?你没有真正的查询字符串吗?
  • 是的。当我调用 HttpContext.Current.QueryString 时,我得到了我在问题中发布的结果。我无法对该查询字符串进行 MD5 哈希,因为它给出了不正确的结果。我需要执行我在问题中提到的修改以获得正确的结果。基本上,我不能按原样使用查询字符串,因为它与 HCO 提供程序用来计算其哈希的字符串不同。
  • @DarinDimitrov,您确定ParseQueryString 会保证在您调用ToString() 时变量将保持相同的顺序吗?
猜你喜欢
  • 1970-01-01
  • 2012-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-08
  • 2012-12-02
相关资源
最近更新 更多