Message-Digest:字节串的Hash变换,将一个任意长度的字节串变幻成一定长(128位)的大整数。
- 这种变换只与字节的值有关,与字符集或编码方式无关。
- 是不可逆的,无法将一个MD5的值变换回原始的字符串。
- 高度离散型,原信息的一点小变化MD5就会有很大变化
1. API接口签名验证方法
1> 将所有请求参数按字母顺序排列得到Map,然后将key和value拼接得到参数字符串
2> 将参数字符串进行MD5加密(大写),得到签名Sign
- 请求的唯一性
在请求参数中,加入时间戳timestamp
/// <param name="parameters">所有字符型的请求参数</param>
/// <param name="secret">签名密钥</param>
/// <param name="qhs">是否前后都加密进行签名</param>
public string SignRequest(IDictionary<string, string> parameters, string secret, bool qhs)
{
// 第一步:把字典按Key的字母顺序排序
IDictionary<string, string> sortedParams = new SortedDictionary<string, string>(parameters);
IEnumerator<KeyValuePair<string, string>> dem = sortedParams.GetEnumerator();
// 第二步:把所有参数名和参数值串在一起
StringBuilder query = new StringBuilder(secret);
while (dem.MoveNext())
{
string key = dem.Current.Key;
string value = dem.Current.Value;
if (!string.IsNullOrWhiteSpace(key))//!string.IsNullOrWhiteSpace(value) 空值也加入计算??
{
query.Append(key).Append(value);
}
}
if (qhs)
{
query.Append(secret);
}
// 第三部:使用md5运算
MD5 md5 = MD5.Create();
byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(query.ToString()));
// 第四部:把二进制转为大写的十六进制
StringBuilder result = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
result.Append(bytes[i].ToString("X2"));
}
return result.ToString();
}
/// <summary>
/// 验证签名
/// </summary>
/// <returns></returns>
public bool ValidateSign(string secret)
{
string method = HttpContext.Current.Request.HttpMethod;
System.Collections.Specialized.NameValueCollection form = HttpContext.Current.Request.QueryString;
switch (method)
{
case "POST":
form = HttpContext.Current.Request.Form;
break;
case "GET":
form = HttpContext.Current.Request.QueryString;
break;
default:
return false;
}
IDictionary<string, string> parameters = new Dictionary<string, string>();
string sign = string.Empty;
for (int i = 0; i < form.Count; i++)
{
string key = form.Keys[i];
if (string.Equals(key,"sign",StringComparison.OrdinalIgnoreCase))
{
sign = form["sign"];
continue;
}
parameters.Add(key,form[key]);
}
return string.Equals(SignRequest(parameters, secret, false), sign,StringComparison.OrdinalIgnoreCase);
}
2. MessageDigest类
- 1> 初始化实例
Java.security.MessageDigest类是一种提供密码安全消息摘要如SHA-1和MD5功能的引擎类。
对于特定类型的消息摘要算法而言,可通过调MessageDigest类中的getInstance静态方法得到MessageDigest对象(算法名大小写不敏感):
Public static MessageDigest getInstance(String algorithm)
例如:
MessageDigest.getInstance(“SHA-1”);
调用者可以可选的制定提供者名,也可以指定provider实例,但必须保证请求算法的实现来自于指定的提供者:
public static MessageDigest getInstance(String algorithm,String provider)
public static MessageDigest getInstance(String algorithm,Provider provider)
对getInstance方法的调用,会返回一个已初始化的MessageDigest对象,因此不需要进一步初始化对象。
- 2> 提供数据
public void update(byte input)
public void update(byte[] input)
public void update(byte[] input,int offset,int len)
- 3>计算摘要
public byte[] digest()
public byte[] digest(byte[] input)
// 返回摘要存储在buf中,offset位置,len字节数
public int digest(byte[] buf,int offset,int len)
package michael.utils;
import java.security.MessageDigest;
public class EncoderHandler {
private static final String ALGORITHM = "MD5";
private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/**
* encode By MD5
*
* @param str
* @return String
*/
public static String encodeByMD5(String str) {
if (str == null) {
return null;
}
try {
MessageDigest messageDigest = MessageDigest.getInstance(ALGORITHM);
messageDigest.update(str.getBytes());
return getFormattedText(messageDigest.digest());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Takes the raw bytes from the digest and formats them correct.
*
* @param bytes
* the raw bytes from the digest.
* @return the formatted bytes.
*/
private static String getFormattedText(byte[] bytes) {
int len = bytes.length;
StringBuilder buf = new StringBuilder(len * 2);
// 把密文转换成十六进制的字符串形式
for (int j = 0; j < len; j++) {
buf.append(HEX_DIGITS[(bytes[j] > 4) & 0x0f]);
buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
}
return buf.toString();
}
public static void main(String[] args) {
System.out.println("111111 MD5 :"
+ EncoderHandler.encodeByMD5("111111"));
}
}