Index: content/browser/experiments/api_key.cc |
diff --git a/content/browser/experiments/api_key.cc b/content/browser/experiments/api_key.cc |
index 5ab842b68e0325e7bb40cac9adb2418f75e1d0fc..70433e349a246cff5acb3d9beb4b1c2b8d9f4f72 100644 |
--- a/content/browser/experiments/api_key.cc |
+++ b/content/browser/experiments/api_key.cc |
@@ -12,6 +12,28 @@ |
#include "base/strings/string_util.h" |
#include "base/strings/utf_string_conversions.h" |
#include "base/time/time.h" |
+#include "crypto/signature_verifier.h" |
+#include "net/cert/pem_tokenizer.h" |
+ |
+namespace { |
+ |
+const char kPublicKeyPEM[] = |
+ "-----BEGIN PUBLIC KEY-----" |
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA38CwBHcz8YoCnPVwhH1p" |
+ "jzmz/TKFu1ggI0+gzugBE+esApjm4I9N1PJ3/GLa+qpzp/VpgyzWqXiRoGM/RCZA" |
+ "V5U+kDaoukxA33GdeA3BUrcYBIaspGRx6xXX36HLLPJF6YdjxbEByYprzecXhNUI" |
+ "ql5VW3D0IR4frU5FzPy/XB5iblFxZAG4682IRRL5KdGL4OWFAPuzaKOMq7ojeKA9" |
+ "y8Gu29huRknKALuScxqk+Jn5Qf3zWckLTpwyPoooXDQ116vs0b9ssalRSuBSRh4Q" |
+ "tjzoQ6S1S5Zqw+2rvXfYhVZ65iiR1zzz6nBXIuUm9HAzIIF43LE6akG9E/F93ZYN" |
+ "mwIDAQAB" |
+ "-----END PUBLIC KEY-----"; |
+ |
+/* By RFC 3447, the maximum salt length for RSAPSS is |
+ * ceil((keySize-1)/8) - hashSize/8 - 2 |
+ */ |
+const size_t kSaltLength = ((2048 + 6) >> 3) - (256 >> 3) - 2; |
+ |
+} // namespace |
namespace content { |
@@ -59,8 +81,47 @@ ApiKey::ApiKey(const std::string& signature, |
expiry_timestamp_(expiry_timestamp) {} |
bool ApiKey::IsValidNow(const base::Time& now) const { |
+ return ValidateDate(now) && ValidateSignature(kPublicKeyPEM); |
+} |
+ |
+bool ApiKey::ValidateDate(const base::Time& now) const { |
base::Time expiry_time = base::Time::FromDoubleT((double)expiry_timestamp_); |
return expiry_time > now; |
} |
+bool ApiKey::ValidateSignature(const char* publicKeyPEM) const { |
+ return ValidateSignature(signature_, data_, publicKeyPEM); |
+} |
+ |
+// static |
+bool ApiKey::ValidateSignature(const std::string& signatureText, |
+ const std::string& data, |
+ const char* publicKeyPEM) { |
+ std::string signature; |
+ // signature is base64-encoded |
+ if (!base::IsStringASCII(signatureText)) { |
+ return false; |
+ } |
+ if (!base::Base64Decode(signatureText, &signature)) { |
+ return false; |
+ } |
+ |
+ net::PEMTokenizer pem_tokenizer(publicKeyPEM, {"PUBLIC KEY"}); |
+ if (!pem_tokenizer.GetNext()) { |
+ NOTREACHED(); |
+ } |
+ std::string publicKey = pem_tokenizer.data(); |
+ std::string dataInUTF8 = data; |
+ crypto::SignatureVerifier sv; |
+ sv.VerifyInitRSAPSS( |
+ crypto::SignatureVerifier::SHA256, crypto::SignatureVerifier::SHA256, |
chasej
2015/12/17 14:13:58
Nit: add a TODO to indicate that this will eventua
iclelland
2015/12/17 15:46:02
Done.
|
+ kSaltLength, reinterpret_cast<const uint8*>(signature.data()), |
+ signature.length(), reinterpret_cast<const uint8*>(publicKey.data()), |
+ publicKey.length()); |
+ sv.VerifyUpdate(reinterpret_cast<const uint8*>(dataInUTF8.data()), |
+ dataInUTF8.length()); |
+ // TODO(iclelland): Support Key revocation through CRL |
+ return sv.VerifyFinal(); |
+} |
+ |
} // namespace |