Chromium Code Reviews| 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 |