当Facebook发送实时更新时,它们在HTTP标头中包含X-Hub-Signature。根据他们的文档(http://developers.facebook.com/docs/api/realtime),他们使用SHA1和应用程序密钥作为密钥。我试着像这样验证签名:
public void MyAction() {
string signature = request.Headers["X-Hub-Signature"];
request.InputStream.Position = 0;
StreamReader reader = new StreamReader(request.InputStream);
string json = reader.ReadToEnd();
var hmac = SignWithHmac(UTF8Encoding.UTF8.GetBytes(json), UTF8Encoding.UTF8.GetBytes("MySecret"));
var hmacBase64 = ToUrlBase64String(hmac);
bool isValid = signature.Split('=')[1] == hmacBase64;
}
private static byte[] SignWithHmac(byte[] dataToSign, byte[] keyBody) {
using (var hmacAlgorithm = new System.Security.Cryptography.HMACSHA1(keyBody)) {
hmacAlgorithm.ComputeHash(dataToSign);
return hmacAlgorithm.Hash;
}
}
private static string ToUrlBase64String(byte[] Input) {
return Convert.ToBase64String(Input).Replace("=", String.Empty)
.Replace('+', '-')
.Replace('/', '_');
}
但我似乎无法让这一点得到验证。对我做错了什么的想法?
提前致谢。
答案 0 :(得分:8)
如果有人需要此信息:
Kelvin提供的可能有用,但看起来非常麻烦。 您只需使用ConvertToHexadecimal函数,而不是使用ToUrlBase64String函数。
请参阅下面的完整更新代码:
public void MyAction() {
string signature = request.Headers["X-Hub-Signature"];
request.InputStream.Position = 0;
StreamReader reader = new StreamReader(request.InputStream);
string json = reader.ReadToEnd();
var hmac = SignWithHmac(UTF8Encoding.UTF8.GetBytes(json), UTF8Encoding.UTF8.GetBytes("MySecret"));
var hmacHex = ConvertToHexadecimal(hmac);
bool isValid = signature.Split('=')[1] == hmacHex ;
}
private static byte[] SignWithHmac(byte[] dataToSign, byte[] keyBody) {
using (var hmacAlgorithm = new System.Security.Cryptography.HMACSHA1(keyBody)) {
return hmacAlgorithm.ComputeHash(dataToSign);
}
}
private static string ConvertToHexadecimal(IEnumerable<byte> bytes)
{
var builder = new StringBuilder();
foreach (var b in bytes)
{
builder.Append(b.ToString("x2"));
}
return builder.ToString();
}
答案 1 :(得分:1)
以下代码将为您解决问题:
public String hmacSha1(String keyString, byte[] in) throws GeneralSecurityException {
Mac hmac = Mac.getInstance("HmacSHA1");
int keySize = keyString.length();
byte[] keyBytes = new byte[keySize];
for (int i = 0; i < keyString.length(); i++) {
keyBytes[i] = (byte) keyString.charAt(i);
}
Key key = new SecretKeySpec(keyBytes, "HmacSHA1");
hmac.init(key);
hmac.update(in);
byte[] bb = hmac.doFinal();
StringBuilder v = new StringBuilder();
for (int i = 0; i < bb.length; i++) {
int ch = bb[i];
int d1 = (ch >> 4) & 0xf;
int d2 = (ch) & 0xf;
if (d1 < 10) {
v.append((char) ('0' + d1));
} else {
v.append((char) ('a' + d1 - 10));
}
if (d2 < 10) {
v.append((char) ('0' + d2));
} else {
v.append((char) ('a' + d2 - 10));
}
}
return v.toString();
}
public String callback(HttpServletRequest request) throws IOException {
InputStream in = request.getInputStream();
StringBuilder builder = new StringBuilder();
byte[] buffer = new byte[1024];
while (in.read(buffer) > 0) {
builder.append(new String(buffer));
}
String signature = request.getHeader("X-Hub-Signature");
try {
String signed = subscriptionService.hmacSha1("YOUR_SECRET", builder.toString().getBytes());
if (signature.startsWith("sha1=") && signature.substring(4).equals(signed)) {
// process the update
....
}
} catch (GeneralSecurityException ex) {
log.warn(ex.getMessage());
}
return null;
}