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

Side by Side Diff: content/common/experiments/api_key_unittest.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: Switch to Ed25519 for signature verification Created 4 years, 11 months 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/common/experiments/api_key.h" 5 #include "content/common/experiments/api_key.h"
6 6
7 #include "base/macros.h" 7 #include "base/macros.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 #include "base/test/simple_test_clock.h" 10 #include "base/test/simple_test_clock.h"
11 #include "base/time/time.h" 11 #include "base/time/time.h"
12 #include "testing/gtest/include/gtest/gtest.h" 12 #include "testing/gtest/include/gtest/gtest.h"
13 13
14 namespace content { 14 namespace content {
15 15
16 namespace { 16 namespace {
17 17
18 /*
19 This is a sample public key for testing the API. The corresponding private
20 key (use this to generate new samples for this test file) is
21
22 0x83, 0x67, 0xf4, 0xcd, 0x2a, 0x1f, 0x0e, 0x04, 0x0d, 0x43,
23 0x13, 0x4c, 0x67, 0xc4, 0xf4, 0x28, 0xc9, 0x90, 0x15, 0x02,
24 0xe2, 0xba, 0xfd, 0xbb, 0xfa, 0xbc, 0x92, 0x76, 0x8a, 0x2c,
25 0x4b, 0xc7, 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9,
26 0x28, 0x70, 0xd2, 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b,
27 0xb7, 0xd5, 0xca, 0x1f, 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0,
28 0x56, 0x3a, 0x04, 0xd0
29 */
30 const uint8_t kTestPublicKey[] = {
31 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2,
32 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f,
33 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
34 };
35 const size_t kTestPublicKeyLength = sizeof(kTestPublicKey);
chasej 2016/01/11 16:11:25 This can be removed, once the key length parameter
iclelland 2016/01/11 18:59:40 Done.
36
37 // This is a good key, signed with the above test private key.
18 const char* kSampleAPIKey = 38 const char* kSampleAPIKey =
19 "Signature|https://valid.example.com|Frobulate|1458766277"; 39 "UsEO0cNxoUtBnHDJdGPWTlXuLENjXcEIPL7Bs7sbvicPCcvAtyqhQuTJ9h/u1R3VZpWigtI+S"
20 40 "dUwk7Dyk/qbDw==|https://valid.example.com|Frobulate|1458766277";
21 const char* kExpectedAPIKeySignature = "Signature"; 41 const char* kExpectedAPIKeySignature =
42 "UsEO0cNxoUtBnHDJdGPWTlXuLENjXcEIPL7Bs7sbvicPCcvAtyqhQuTJ9h/u1R3VZpWigtI+S"
43 "dUwk7Dyk/qbDw==";
22 const char* kExpectedAPIKeyData = 44 const char* kExpectedAPIKeyData =
23 "https://valid.example.com|Frobulate|1458766277"; 45 "https://valid.example.com|Frobulate|1458766277";
24 const char* kExpectedAPIName = "Frobulate"; 46 const char* kExpectedAPIName = "Frobulate";
25 const char* kExpectedOrigin = "https://valid.example.com"; 47 const char* kExpectedOrigin = "https://valid.example.com";
26 const uint64_t kExpectedExpiry = 1458766277; 48 const uint64_t kExpectedExpiry = 1458766277;
27 49
28 // The key should not be valid for this origin, or for this API. 50 // The key should not be valid for this origin, or for this API.
29 const char* kInvalidOrigin = "https://invalid.example.com"; 51 const char* kInvalidOrigin = "https://invalid.example.com";
30 const char* kInsecureOrigin = "http://valid.example.com"; 52 const char* kInsecureOrigin = "http://valid.example.com";
31 const char* kInvalidAPIName = "Grokalyze"; 53 const char* kInvalidAPIName = "Grokalyze";
32 54
33 // The key should be valid if the current time is kValidTimestamp or earlier. 55 // The key should be valid if the current time is kValidTimestamp or earlier.
34 double kValidTimestamp = 1458766276.0; 56 double kValidTimestamp = 1458766276.0;
35 57
36 // The key should be invalid if the current time is kInvalidTimestamp or later. 58 // The key should be invalid if the current time is kInvalidTimestamp or later.
37 double kInvalidTimestamp = 1458766278.0; 59 double kInvalidTimestamp = 1458766278.0;
38 60
61 // Well-formed API key with an invalid signature.
62 const char* kInvalidSignatureAPIKey =
63 "CO8hDne98QeFeOJ0DbRZCBN3uE0nyaPgaLlkYhSWnbRoDfEAg+TXELaYfQPfEvKYFauBg/hnx"
64 "mba765hz0mXMc==|https://valid.example.com|Frobulate|1458766277";
65
39 // Various ill-formed API keys. These should all fail to parse. 66 // Various ill-formed API keys. These should all fail to parse.
40 const char* kInvalidAPIKeys[] = { 67 const char* kInvalidAPIKeys[] = {
41 // Invalid - only one part 68 // Invalid - only one part
42 "abcde", 69 "abcde",
43 // Not enough parts 70 // Not enough parts
44 "https://valid.example.com|APIName|1458766277", 71 "https://valid.example.com|APIName|1458766277",
45 // Delimiter in API Name 72 // Delimiter in API Name
46 "Signature|https://valid.example.com|API|Name|1458766277", 73 "Signature|https://valid.example.com|API|Name|1458766277",
47 // Extra string field 74 // Extra string field
48 "Signature|https://valid.example.com|APIName|1458766277|SomethingElse", 75 "Signature|https://valid.example.com|APIName|1458766277|SomethingElse",
(...skipping 18 matching lines...) Expand all
67 return api_key->ValidateOrigin(origin); 94 return api_key->ValidateOrigin(origin);
68 } 95 }
69 96
70 bool ValidateApiName(ApiKey* api_key, const char* api_name) { 97 bool ValidateApiName(ApiKey* api_key, const char* api_name) {
71 return api_key->ValidateApiName(api_name); 98 return api_key->ValidateApiName(api_name);
72 } 99 }
73 100
74 bool ValidateDate(ApiKey* api_key, const base::Time& now) { 101 bool ValidateDate(ApiKey* api_key, const base::Time& now) {
75 return api_key->ValidateDate(now); 102 return api_key->ValidateDate(now);
76 } 103 }
104
105 bool ValidateSignature(ApiKey* api_key,
106 const uint8_t* public_key,
107 size_t public_key_length) {
108 return api_key->ValidateSignature(public_key, public_key_length);
109 }
77 }; 110 };
78 111
79 TEST_F(ApiKeyTest, ParseEmptyString) { 112 TEST_F(ApiKeyTest, ParseEmptyString) {
80 scoped_ptr<ApiKey> empty_key = ApiKey::Parse(""); 113 scoped_ptr<ApiKey> empty_key = ApiKey::Parse("");
81 EXPECT_FALSE(empty_key); 114 EXPECT_FALSE(empty_key);
82 } 115 }
83 116
84 TEST_F(ApiKeyTest, ParseInvalidStrings) { 117 TEST_F(ApiKeyTest, ParseInvalidStrings) {
85 for (size_t i = 0; i < kNumInvalidAPIKeys; ++i) { 118 for (size_t i = 0; i < kNumInvalidAPIKeys; ++i) {
86 scoped_ptr<ApiKey> empty_key = ApiKey::Parse(kInvalidAPIKeys[i]); 119 scoped_ptr<ApiKey> empty_key = ApiKey::Parse(kInvalidAPIKeys[i]);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 EXPECT_TRUE(key->IsAppropriate(kExpectedOrigin, kExpectedAPIName)); 152 EXPECT_TRUE(key->IsAppropriate(kExpectedOrigin, kExpectedAPIName));
120 EXPECT_TRUE(key->IsAppropriate(kExpectedOrigin, 153 EXPECT_TRUE(key->IsAppropriate(kExpectedOrigin,
121 base::ToUpperASCII(kExpectedAPIName))); 154 base::ToUpperASCII(kExpectedAPIName)));
122 EXPECT_TRUE(key->IsAppropriate(kExpectedOrigin, 155 EXPECT_TRUE(key->IsAppropriate(kExpectedOrigin,
123 base::ToLowerASCII(kExpectedAPIName))); 156 base::ToLowerASCII(kExpectedAPIName)));
124 EXPECT_FALSE(key->IsAppropriate(kInvalidOrigin, kExpectedAPIName)); 157 EXPECT_FALSE(key->IsAppropriate(kInvalidOrigin, kExpectedAPIName));
125 EXPECT_FALSE(key->IsAppropriate(kInsecureOrigin, kExpectedAPIName)); 158 EXPECT_FALSE(key->IsAppropriate(kInsecureOrigin, kExpectedAPIName));
126 EXPECT_FALSE(key->IsAppropriate(kExpectedOrigin, kInvalidAPIName)); 159 EXPECT_FALSE(key->IsAppropriate(kExpectedOrigin, kInvalidAPIName));
127 } 160 }
128 161
162 TEST_F(ApiKeyTest, ValidateValidSignature) {
163 scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey);
164 ASSERT_TRUE(key);
165 EXPECT_TRUE(
166 ValidateSignature(key.get(), kTestPublicKey, kTestPublicKeyLength));
167 }
168
169 TEST_F(ApiKeyTest, ValidateInvalidSignature) {
170 scoped_ptr<ApiKey> key = ApiKey::Parse(kInvalidSignatureAPIKey);
171 ASSERT_TRUE(key);
172 EXPECT_FALSE(
173 ValidateSignature(key.get(), kTestPublicKey, kTestPublicKeyLength));
174 }
175
176 TEST_F(ApiKeyTest, ValidateSignatureOnWrongKey) {
177 scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey);
178 ASSERT_TRUE(key);
179 // Signature will be invalid if tested against the real public key
180 EXPECT_FALSE(key->IsValid(base::Time::FromDoubleT(kInvalidTimestamp)));
chasej 2016/01/11 16:11:25 Should this be passing kValidTimestamp? Otherwise
iclelland 2016/01/11 18:59:40 Thanks, that was a typo introduced back in PS#4. F
181 }
chasej 2016/01/11 16:11:25 Do we need more tests for ApiKey.IsValid()? I kno
iclelland 2016/01/11 18:59:40 IsValid is deliberately kept very simple, and by d
182
183 TEST_F(ApiKeyTest, ValidateWhenNotExpired) {
184 scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey);
185 ASSERT_TRUE(key);
186 }
187
129 } // namespace content 188 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698