根据 Gigya 的构造签名的说明,我编写了一个方法来根据指定的时间戳和 UID 验证 gigya 签名。这是 Gigya 的伪代码:
string constructSignature(string timestamp, string UID, string secretKey) {
// Construct a "base string" for signing
baseString = timestamp + "_" + UID;
// Convert the base string into a binary array
binaryBaseString = ConvertUTF8ToBytes(baseString);
// Convert secretKey from BASE64 to a binary array
binaryKey = ConvertFromBase64ToBytes(secretKey);
// Use the HMAC-SHA1 algorithm to calculate the signature
binarySignature = hmacsha1(binaryKey, baseString);
// Convert the signature to a BASE64
signature = ConvertToBase64(binarySignature);
return signature;
}
这是我的方法(省略异常处理):
public boolean verifyGigyaSig(String uid, String timestamp, String signature) {
// Construct the "base string"
String baseString = timestamp + "_" + uid;
// Convert the base string into a binary array
byte[] baseBytes = baseString.getBytes("UTF-8");
// Convert secretKey from BASE64 to a binary array
String secretKey = MyConfig.getGigyaSecretKey();
byte[] secretKeyBytes = Base64.decodeBase64(secretKey);
// Use the HMAC-SHA1 algorithm to calculate the signature
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec(secretKeyBytes, "HmacSHA1"));
byte[] signatureBytes = mac.doFinal(baseBytes);
// Convert the signature to a BASE64
String calculatedSignature = Base64.encodeBase64String(signatureBytes);
// Return true iff constructed signature equals specified signature
return signature.equals(calculatedSignature);
}
false
即使不应该,此方法也会返回。任何人都可以发现我的实施有问题吗?我想知道调用者或 gigya 本身是否存在问题 - “您的方法已检出”是一个有效的答案。
我正在使用 Apache Commons 的Base64
类进行编码。
在Gigya 的常见问题解答中还可以找到有关签名的更多(有些多余的)信息,以防万一。
为了进一步澄清这一点:uid
、、timestamp
和signature
都取自 gigya 设置的 cookie。为了验证这些没有被欺骗,我正在使用uid
and timestamp
,并确保signature
可以使用我的密钥进行重建。当它不应该在过程中的某个时刻指示错误/格式问题时,它失败的事实,无论是使用我的方法,在前端,还是使用 gigya 本身。这个问题的目的本质上是排除上述方法中的错误。
注意:我也尝试过 URL-encoding uid
:
String baseString = timestamp + "_" + URLEncoder.encode(uid, "UTF-8");
虽然我认为这并不重要,因为它只是一个整数。也是如此timestamp
。
更新:
根本问题已经解决,但问题本身仍然悬而未决。有关更多详细信息,请参阅我的答案。
更新 2:
事实证明,我对我使用的是哪个 apacheBase64
类感到困惑——我的代码使用的不是Commons Codec 版本,而是Commons Net 版本。这种困惑源于我的项目中有大量第三方库,以及我Base64
多年来对 Apache 库的许多实现一无所知——我现在意识到Commons Codec旨在解决这种情况。看来我在编码方面迟到了。
在切换 Commons Codec 的版本后,该方法的行为正确。
我将把赏金奖励给@erickson,因为他的回答很到位,但请为他们出色的洞察力投票支持这两个答案!我将暂时开放赏金,以便他们得到应有的关注。