有没有更简单的方法来计算 MD5 哈希值?

发布于 2024-12-06 02:52:35 字数 2516 浏览 1 评论 0原文

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

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

trnApproved=0&trnId=10000000&messageId=71&messageText=拒绝&authCode=000000&responseType=T&trnAmount=20.00&trnDate=9%2f23%2f2011+9%3a30%3a56+A M&trnOrderNumber=1000000&trnLanguage=eng&trnCustomerName=名字+姓氏&trnEmailAddress=something_something%40gmail.com&trnPhoneNumber=1235550123&av sProcessed=0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=地址+验证+未执行+for+this+交易。&cvdId=3&cardTyp e=VI&trnType=P& paymentMethod=CC&ref1=9dae6af7-7c22-4697-b23a-413d8a129a75&am p;ref2=&ref3=&ref4=&ref5=&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;
}

这一切都有效(直到有人输入我没有考虑到的角色),只是这看起来比应有的更复杂。我知道我不是唯一一个必须在 ASP.NET 应用程序中实现此 HCO 的人,因此我认为简单的验证不应该如此复杂。

我是否缺少一种更简单的方法来做到这一点?必须循环遍历这些字段,对其中一些字段进行编码,同时跳过其他字段,将其编码转换为大写,然后有选择地替换字符似乎有点……奇怪。

I'm working on implementing a hosted checkout, and the hosted checkout is supposed to redirect the user back to my website so that I can show a custom receipt page.

This is a sample querystring that I'd get back:

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

To validate the request, I'm supposed to remove &hashValue=f3cf58ef0fd363e0c2241938b04f1068 from the end of the querystring, and then append a key. I then perform an MD5 hash of the entire string, and the result should be 33dacf84682470f267b2cc6d528b1594, same as the original.

This is easy, except that a few of the fields are causing a problem for me. This is the code I use (taken from a dummy application, so you can ignore some of the bad coding):

// 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();

This is the UrlEncode method I use.

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;
}

This all works (until someone enters a character I haven't accounted for), except this seems more complicated than it should be. I know I'm not the only one who has to implement this HCO into an ASP.NET application, so I don't think the simple validation should be so complicated.

Am I missing an easier way to do this? Having to loop through the fields, encoding some of them while skipping others, converting their encoding to uppercase and then selectively replacing characters seems a little... odd.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

枯寂 2024-12-13 02:52:35

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

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 吗?您可以这样做,然后附加到查询字符串。

Here's a better way to work with query strings:

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

Then I didn't quite understand what you wanted to do. You want to calculate an MD5 on the result? You could do that and then append to the query string.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文