构建和验证Gigya签名 [英] Constructing and validating a Gigya signature

查看:161
本文介绍了构建和验证Gigya签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于Gigya的构造签名的说明。这是Gigya的 代码:

  string constructSignature字符串时间戳,字符串UID,字符串secretKey){
//构造一个基本字符串用于签名
baseString = timestamp +_+ UID;
//将基本字符串转换为二进制数组
binaryBaseString = ConvertUTF8ToBytes(baseString);
//将secretKey从BASE64转换为二进制数组
binaryKey = ConvertFromBase64ToBytes(secretKey);
//使用HMAC-SHA1算法计算签名
binarySignature = hmacsha1(binaryKey,baseString);
//将签名转换为BASE64
signature = ConvertToBase64(binarySignature);
返回签名;
}

[sic]



这是我的方法(省略异常处理):

  public boolean verifyGigyaSig(String uid,String timestamp,String signature){

//构造
String baseString = timestamp +_+ uid;

//将基本字符串转换为二进制数组
byte [] baseBytes = baseString.getBytes(UTF-8);

//将secretKey从BASE64转换为二进制数组
String secretKey = MyConfig.getGigyaSecretKey();
byte [] secretKeyBytes = Base64.decodeBase64(secretKey);

//使用HMAC-SHA1算法计算签名
Mac mac = Mac.getInstance(HmacSHA1);
mac.init(new SecretKeySpec(secretKeyBytes,HmacSHA1));
byte [] signatureBytes = mac.doFinal(baseBytes);

//将签名转换为BASE64
字符串computedSignature = Base64.encodeBase64String(signatureBytes);

//返回true iff构造签名等于指定签名
返回signature.equals(calculateSignature);
}

此方法返回 false 即使不应该。任何人都可以发现我的执行错误吗?我想知道呼叫者或gigya本身是否有问题 - 您的方法检出是一个有效的答案



我使用的是Apache Commons的 c> Base64 编码类。



进一步(有点冗余)签名信息也可以在 Gigya的常见问题解答中找到,以备帮助。



为了进一步说明这一点 uid timestamp 签名都是从gigya设置的cookie中取出的。为了验证这些不被欺骗,我正在采取 uid timestamp ,并确保签名可以使用我的密钥重建。事实上,它不会在进程中的某个时间点显示错误/格式问题,无论是使用我的方法,前端还是gigya本身。这个问题的目的在于排除上述方法中的错误。



注意:我也尝试过URL编码code> uid :

  String baseString = timestamp +_+ URLEncoder.encode (uid,UTF-8); 

虽然我不会认为这是重要的,因为它只是一个整数。 timestamp 同样如此。



更新:



基本问题已经解决,但问题本身仍然是开放的。有关详细信息,请参阅我的答案



更新2:



原来我很困惑apache的 Base64 我正在使用的类 - 我的代码没有使用 Commons Codec版本 Commons Net版本。这个混乱是由我的项目的大量第三方图书馆产生的,以及我对Apache图书馆多年来许多 Base64 实现的无知 - 我现在意识到的一种情况 Commons Codec 旨在解决。看起来我在编码方面比较晚了。



在切换Commons Codec的版本后,该方法的行为正确。



我将从 @erickson 获得赏金,因为他的答案已经出现了,但请提高他们两个答案的出色见解!我现在要离开赏金,所以他们得到他们应得的关注。

解决方案

我终于从吉他回来了关于这个问题,事实证明,他们自己的服务器端的Java API提供了一个处理这个用例的方法,一个是 SigUtils。 validateUserSignature

  if(SigUtils.validateUserSignature(uid,timestamp,secretKey,signature )){...} 

今天我能够验证这个调用是否正常,所以这解决了当前的问题,并将整个帖子变成了对我的一种表情。



但是:



我仍然有兴趣为什么我自己的家庭滚动方法不起作用(而且我有无论如何奖励奖励)。我将在下周再次考察一下,并将其与 SigUtils 类文件进行比较,以尝试找出出错的情况。


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 psuedo code for doing that:

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;
}

[sic]

Here's my method (exception handling omitted):

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);
}

This method is returning false even when it shouldn't. Can anyone spot something wrong with my implementation? I'm wondering if there could be an issue with the caller or gigya itself - "Your method checks out" is a valid answer.

I'm using Apache Commons' Base64 class for encoding.

Further (somewhat redundant) info on signatures is also found in Gigya's FAQ, in case that helps.

To clarify this further: uid, timestamp, and signature are all being taken from cookies set by gigya. In order to verify these aren't being spoofed, I'm taking uid and timestamp, and making sure signature can be reconstructed using my secret key. The fact that it fails when it shouldn't indicates a bug/format issue at some point in the process, either with my method, in the front-end, or with gigya itself. The purpose of this question is essentially to rule out a bug in the above method.

Note: I've also tried URL-encoding uid:

String baseString = timestamp + "_" + URLEncoder.encode(uid, "UTF-8");

Though I wouldn't think this would matter since it's just an integer. The same goes for timestamp.

Update:

The underlying issue has been solved, however the question itself remains open. See my answer for more details.

Update 2:

It turns out I was confused about which of apache's Base64 classes I was using - my code was not using the Commons Codec version but the Commons Net version. This confusion arose from my project's large amount of third-party libraries and my ignorance of the many Base64 implementations over the years from Apache libraries - a situation I now realize Commons Codec was meant to address. Looks like I'm late to the party when it comes to encoding.

After switching in Commons Codec's version, the method behaves correctly.

I'm going to award the bounty to @erickson since his answer was spot on, but please upvote both answers for their excellent insight! I'll leave the bounty open for now so they get the attention they deserve.

解决方案

Well I finally heard back from gigya yesterday regarding this issue, and it turns out their own server-side Java API exposes a method for handling this use case, SigUtils.validateUserSignature:

if (SigUtils.validateUserSignature(uid, timestamp, secretKey, signature)) { ... }

Today I was able to verify that this call is behaving correctly, so that solves the immediate issue and turns this whole post into a kind of a facepalm moment for me.

However:

I'm still interested in why my own home-rolled method doesn't work (and I have a bounty to award anyway). I'll examine it again this coming week and compare it with the SigUtils class file to try and figure out what went wrong.

这篇关于构建和验证Gigya签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆