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的FAQ中找到,如果有帮助的话。
为了进一步澄清,
uid
、timestamp
和signature
均来自于由Gigya设置的cookie。为了验证这些是否被伪造,我将uid
和timestamp
取出,并确保可以使用我的秘钥重新构建signature
。当它不应该失败时,它的失败表明在过程中存在某个点的错误/格式问题,可能是在我的方法中、前端或者Gigya本身中。本问题的目的实质上是排除上述方法中的错误。注意:我还尝试过对
uid
进行URL编码。String baseString = timestamp + "_" + URLEncoder.encode(uid, "UTF-8");
尽管我认为这并不重要,因为它只是一个整数。对于timestamp
也是如此。
更新:
潜在问题已得到解决,但问题本身仍然存在。有关更多详细信息,请参见我的答案。
更新2:
事实证明,我对apache的Base64
类使用混淆了——我的代码没有使用Commons Codec版本,而是使用了Commons Net版本。这种混淆源于我的项目中大量的第三方库以及我对Apache库多年来的许多Base64
实现的无知,而我现在意识到Commons Codec旨在解决这种情况。看来当涉及编码时,我迟到了。
我将奖励@erickson,因为his answer完全正确,但请为两个答案点赞,以表彰他们出色的见解!我会暂时保留奖励,以便它们得到应有的关注。
binaryBaseString = ConvertUTF8ToBytes(baseString);
的意义是什么?在 gigya 伪代码中,我们所看到的范围内从未使用过 binaryBaseString。但是在您的函数中,您实际上使用了它...mac.doFinal(baseBytes);
然后将返回的字节数组转换为 calculatedSignature... - Youssef G.