I wrote a method to verify a gigya signature against a specified timestamp and UID, based on Gigya\'s instructions for constructing a signature. Here is Gigya\'s psu
I would take a close look at your Base-64 encoding and decoding.
Are you using a third-party library for this? If so, which one? If not, can you post your own implementation or at least some sample input and output (representing bytes with hexadecimal)?
Sometimes there are differences in the "extra" Base-64 characters that are used (substituting characters for '/' and '+'). Padding can also be omitted, which would cause string comparison to fail.
As I suspected, it is the Base-64 encoding that is causing this discrepancy. However, it is trailing whitespace that is causing the problem, not differences in padding or symbols.
The encodeBase64String() method that you are using always appends CRLF to its output. The Gigya signature does not include this trailing whitespace. Comparing these strings for equality fails only because of this difference in whitespace.
Use encodeBase64String() from the Commons Codec library (instead of Commons Net) to create a valid signature.
If we factor out the signature computation, and test its result against the Gigya SDK's verifier, we can see that removing the CRLF creates a valid signature:
public static void main(String... argv)
throws Exception
{
final String u = "";
final String t = "";
final String s = MyConfig.getGigyaSecretKey();
final String signature = sign(u, t, s);
System.out.print("Original valid? ");
/* This prints "false" */
System.out.println(SigUtils.validateUserSignature(u, t, s, signature));
final String stripped = signature.replaceAll("\r\n$", "");
System.out.print("Stripped valid? ");
/* This prints "true" */
System.out.println(SigUtils.validateUserSignature(u, t, s, stripped));
}
/* This is the original computation included in the question. */
static String sign(String uid, String timestamp, String key)
throws Exception
{
String baseString = timestamp + "_" + uid;
byte[] baseBytes = baseString.getBytes("UTF-8");
byte[] secretKeyBytes = Base64.decodeBase64(key);
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec(secretKeyBytes, "HmacSHA1"));
byte[] signatureBytes = mac.doFinal(baseBytes);
return Base64.encodeBase64String(signatureBytes);
}