署名を作成するための 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 の FAQにもあります。
これをさらに明確にするために、uid
、timestamp
、およびsignature
はすべて gigya によって設定された Cookie から取得されています。これらがなりすましではないことを確認するために、 と を取得uid
し、秘密鍵を使用して再構築できることtimestamp
を確認します。signature
私の方法、フロントエンド、または gigya 自体のいずれかで、プロセスのある時点でバグ/フォーマットの問題を示してはならないときに失敗するという事実。この質問の目的は、基本的に上記の方法のバグを除外することです。
注: URLエンコーディングも試しましたuid
:
String baseString = timestamp + "_" + URLEncoder.encode(uid, "UTF-8");
単なる整数なので、これは問題ではないと思いますが。についても同様ですtimestamp
。
アップデート:
根本的な問題は解決されましたが、質問自体は未解決のままです。詳細については、私の回答を参照してください。
更新 2:
Base64
私が使用していた Apache のクラスについて混乱していたことが判明しました。私のコードは、 Commons Codec バージョンではなく、Commons Net バージョンを使用していました。この混乱は、私のプロジェクトの大量のサードパーティ ライブラリと、何Base64
年にもわたって Apache ライブラリからの多くの実装を知らなかったことから生じました。Commons Codecが対処することを意図した状況であることがわかりました。エンコーディングに関しては、パーティーに遅れているようです。
Commons Codec のバージョンに切り替えた後、メソッドは正しく動作します。
@ericksonの回答は的を射ていたので、報奨金を授与しますが、優れた洞察のために両方の回答に賛成票を投じてください! 彼らが当然の注目を集めるように、私は今のところ懸賞金を開いたままにします。