Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(427)

Unified Diff: content/browser/experiments/api_key.cc

Issue 1522813002: Add public key and signature verification to browser-side API keys (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@keys
Patch Set: Add TODOs for future work Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..f7dfc53e7d59b3bb447531e7a45be1d4c54bcc2b 100644
--- a/content/browser/experiments/api_key.cc
+++ b/content/browser/experiments/api_key.cc
@@ -12,6 +12,31 @@
#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 {
+
+// This is the default public key used for validating signatures.
+// TODO(iclelland): Move this to the embedder, and provide a mechanism to allow
+// for multiple signing keys. https://crbug.com/543220
+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-----";
davidben 2015/12/18 22:23:17 Here, use this: static const uint8_t kPublicKey[]
iclelland 2015/12/22 05:45:28 Thanks, done. I wanted something paste-able from a
+
+/* By RFC 3447, the maximum salt length for RSAPSS is
+ * ceil((keySize-1)/8) - hashSize/8 - 2
+ */
davidben 2015/12/18 22:23:17 Nit: This can use // for comments
iclelland 2015/12/22 05:45:28 Done.
+const size_t kSaltLength = ((2048 + 6) >> 3) - (256 >> 3) - 2;
davidben 2015/12/18 22:23:16 So, I'm not all that familiar with RSA-PSS, but I
iclelland 2015/12/22 05:45:28 I used the max length, and ensured that this was i
+
+} // namespace
namespace content {
@@ -59,8 +84,49 @@ 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 {
davidben 2015/12/18 22:23:16 public_key_pem
iclelland 2015/12/22 05:45:28 Done.
+ 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)) {
davidben 2015/12/18 22:23:16 Does base::Base64Decode not check this for you?
iclelland 2015/12/22 05:45:28 Yes. Yes I suppose it does, in a roundabout way (n
+ return false;
+ }
+ if (!base::Base64Decode(signatureText, &signature)) {
+ return false;
+ }
+
+ net::PEMTokenizer pem_tokenizer(publicKeyPEM, {"PUBLIC KEY"});
davidben 2015/12/18 22:23:17 I don't thiiink we get initializer lists yet? (Hop
iclelland 2015/12/22 05:45:28 Acknowledged. PEMTokenizer is gone.
+ if (!pem_tokenizer.GetNext()) {
+ NOTREACHED();
+ }
+ std::string publicKey = pem_tokenizer.data();
davidben 2015/12/18 22:23:16 public_key
iclelland 2015/12/22 05:45:28 Done.
+ std::string dataInUTF8 = data;
davidben 2015/12/18 22:23:17 data_in_utf8, but it looks like you can just data.
iclelland 2015/12/22 05:45:28 It's ported from my original attempt at this code,
+ crypto::SignatureVerifier sv;
davidben 2015/12/18 22:23:17 verifier
iclelland 2015/12/22 05:45:28 Done.
+ // TODO(iclelland): Switch to SubjectPublicKeyInfo to determine hash algorithm
+ // https://crbug.com/570684
davidben 2015/12/18 22:23:17 Commented on the bug, but this seems just fine. Al
iclelland 2015/12/22 05:45:28 Removed, thanks :)
+ sv.VerifyInitRSAPSS(
davidben 2015/12/18 22:23:17 Check for failure. Shouldn't happen, but still.
iclelland 2015/12/22 05:45:28 Done.
+ crypto::SignatureVerifier::SHA256, crypto::SignatureVerifier::SHA256,
+ kSaltLength, reinterpret_cast<const uint8*>(signature.data()),
davidben 2015/12/18 22:23:17 uint8_t for new code (I should go and fix //crypto
iclelland 2015/12/22 05:45:28 Done.
+ 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

Powered by Google App Engine
This is Rietveld 408576698