前段时间做一个项目,涉及到与一个第三方平台对接。对方平台是java开发的,没有提供C#的sdk,由于涉及到签名问题,所有不得不翻看他们的java sdk,并按照他们的算法翻译成C#。有些问题百度半天也没找到答案,最后好不容易搞定了,特此记录下。
public static String makeSig(TreeMap param,String key){
try{
String str = OAuthUtil.sigParam(param);
String mac = new BigInteger(Coder.encryptHMAC((str).getBytes("utf-8"), key)).toString();
System.out.println("InterfaceService >> MAC :"+mac);
return mac;
}catch(Exception e){
e.printStackTrace();
return null;
}
}
private static String sigParam(TreeMap param){
String str = "";
//1 排序 2组串
Set set = param.keySet();
Iterator it = set.iterator();
while(it.hasNext()){
String key = (String)it.next();
str+=key+"="+param.get(key);
}
return str;
}
/**
* HMAC加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptHMAC(byte[] data, String key) throws Exception {
SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
mac.init(secretKey);
return mac.doFinal(data);
}
/**
* BASE64解密
*
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptBASE64(String key) throws Exception {
return (new BASE64Decoder()).decodeBuffer(key);
}
Java相关的代码基本就是这些了,然后用C#进行翻译。
public static string ComputeSign(SortedDictionary parameters,string key)
{
if (parameters.Count == 0)
{
return string.Empty;
}
var list = parameters.Select(r => $"{r.Key}={r.Value}").ToList();
var toSignString = string.Join("", list.Select(r => r));
var keyBy = Convert.FromBase64String(key);
var hmac = new HMACSHA1(keyBy);
hmac.Initialize();
hmac.ComputeHash(Encoding.UTF8.GetBytes(toSignString));
var bigInteger = new BigInteger(hmac.Hash.Reverse().ToArray());
return bigInteger.ToString();
}
其中 C#中的 BigInteger 位于 System.Numerics 下,需要添加引用
最后,进行测试
Java:
public static void main(String[] args) {
try {
TreeMap dic = new TreeMap();
dic.put("client_id", "826");
dic.put("grant_type", "authorization_code");
dic.put("code", "abcd123ef");
dic.put("state", "ktsvdafz");
String sig = makeSig(dic, "b6b3c0699dd0920f263eade3df2aad11");
System.out.println("Sig: " + sig);
} catch (Exception e) {
e.printStackTrace();
}
}
结果:Sig: -76040878703683626175778032011774713322908319476
C#:
var paras = new SortedDictionary
{
{"client_id", "826"},
{"grant_type", "authorization_code"},
{"code", "abcd123ef"},
{"state", "ktsvdafz"}
};
var sig = OpenAuthBaseEx.ComputeSign(paras, "b6b3c0699dd0920f263eade3df2aad11");
Console.WriteLine(sig);
结果:Sig: -76040878703683626175778032011774713322908319476
结果也是惊人的一致,完美收官!