OLD | NEW |
---|---|
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/browser/experiments/api_key.h" | 5 #include "content/browser/experiments/api_key.h" |
6 | 6 |
7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "base/test/simple_test_clock.h" | 8 #include "base/test/simple_test_clock.h" |
9 #include "base/time/time.h" | 9 #include "base/time/time.h" |
10 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
11 | 11 |
12 namespace content { | 12 namespace content { |
13 | 13 |
14 namespace { | 14 namespace { |
15 | 15 |
16 /* | |
davidben
2015/12/18 22:23:17
Nit: I think // is more common, though I don't ter
iclelland
2015/12/22 05:45:28
Ack. I deliberately chose /* */ here so that anyon
| |
17 This is a sample public key for testing the API. The corresponding private | |
18 key (use this to generate new samples for this test file) is | |
19 | |
20 -----BEGIN RSA PRIVATE KEY----- | |
21 MIIEogIBAAKCAQEA6LVGtcy5JJnH7PHREKHTp3hnmg5cFTmQwG0BdgC81Ew9p4fl | |
22 ovmxRuV6iMNPOJoHLdflQnAJhEZAt0dQURSlC6X0nSqxdD0yrvB64sJKfZEsMWFH | |
23 8r3AMYVJN+v2yrYe7JxEKkESmPVIijXVafWz6gW1LnOTKYgtiJtaJ7DlkCucKdT2 | |
24 Jezlj9PuzXs0AEUG0m584G6g4q6kHw9XQGItMm7R1LlU7Gw0Zy72+L6uXOliLO1x | |
25 Q/mvAr1oNYCcYtPQdZyMW2ikBIKZO3ElSHR+LC3ZVVb8euwoSPJkpIMwc14/cGud | |
26 9nFckY3DQFhT9uf6ZTv49surG3P3uT1lNSSu5wIDAQABAoIBACWzyQMHai+t4qBX | |
27 BWJGdb46Wb6x+OVPcE5c2tG9iNp0h8Cu2duvzLMJ1vJ1gk5PVj5tLi23bTNLFo0b | |
28 Nr4MNDlQ5/LWye1lROLm/2HhzKPPc3OEqV2AtLTRPW2cA14QZ646GyklZdf2VYxe | |
29 8Ha8YivWROaDvyIJeCcb1F194ZObzhKoZQRSNd4GvbKGh7bIr0+dtvffe9K39YmI | |
30 nSvisgorLlQE8pte/aAfNdVhl9aAkZRBS6wF3F4qrIT3pFGRgp6RNnx/EN8Z6tcj | |
31 MwufnzvNWM62E+8kaEwF89iW6wVgqG63BjwmJ0n97BKmo2f9kCgg34ywM7nsS9CA | |
32 i08yJZECgYEA+ffw8KUOmteh7THUc0BpLQt0/H7XU7EbDO5lAzXaEpO0hs/egQ0a | |
33 8B58fnSs3KD5hz88IOpuHSqNKpwv2kK3EgmLSfzcJZMLGdPtay3fc2CiI8SiMhYk | |
34 OxbLplj5LO0DLoIPuJ3XyOhLb4ucaErK4K8GGCRXjm6aSgege6XSfsUCgYEA7lK3 | |
35 nmRK4PejYM/eP5WoG7wmCu1estYoGh6gnnsUkhafFcFQ5z/EZF8lxA/4O7gqfR7n | |
36 d3j+82SUeTUcQ5Ek43QHG48qVU66t7+D3gIFqdarqhZmINKeLnm0LP7BI3zQ30eU | |
37 Pf6QVQUWyGJ0HqAuEgEF6DXXSmJ+mORIlIGLEbsCgYBLu+M0Bc42+74Dr2U+xfUX | |
38 wLDhD00N/krD0DaqklZP6pB3h+NSFjZjKdluNstozRzM7Uu6bUyPaaT7k/armir9 | |
39 PAcHk6TffX2PhbYZEvzwaAa374t0wWCYxn9NFwfnpKeiH6XDuY73P+obEaGBt6dg | |
40 C6c9CUW90aTNaSImVEdCQQKBgFx9aZlk3tJ0CMnXoi8XC4jH+hOfj3LkPef1Huyi | |
41 Y5dWhCLTRWyZiMRTULrIX9P9Yy/vwHDTWk5nKF/pxrBKMgC71M5TP2CgD0KkZq7Q | |
42 JhaFo1V9H+F5G755qP0VWStGk2EzzEpK8wSr1u2pl9sS2w5Nq1c1HfpWQz9eyPQp | |
43 WillAoGAQ1DjFXgiTFeBILj8JIys/6noXVgGhkdhfXfbdgHYiGBv+ItSyIEfnPB2 | |
44 aY/BAXFmlXEtnCPOYMb15lz1ThEO09c98BfEES8cgpdr2rdTkYTjX2Uhte/iiDgx | |
45 KWOeBEhre0kx4HKyO5qvccclK9mRpCGiL/bQZKgSrrG9HbrSk9g= | |
46 -----END RSA PRIVATE KEY----- | |
47 */ | |
48 const char* kTestPublicKeyPEM = | |
49 "-----BEGIN PUBLIC KEY-----" | |
50 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6LVGtcy5JJnH7PHREKHT" | |
51 "p3hnmg5cFTmQwG0BdgC81Ew9p4flovmxRuV6iMNPOJoHLdflQnAJhEZAt0dQURSl" | |
52 "C6X0nSqxdD0yrvB64sJKfZEsMWFH8r3AMYVJN+v2yrYe7JxEKkESmPVIijXVafWz" | |
53 "6gW1LnOTKYgtiJtaJ7DlkCucKdT2Jezlj9PuzXs0AEUG0m584G6g4q6kHw9XQGIt" | |
54 "Mm7R1LlU7Gw0Zy72+L6uXOliLO1xQ/mvAr1oNYCcYtPQdZyMW2ikBIKZO3ElSHR+" | |
55 "LC3ZVVb8euwoSPJkpIMwc14/cGud9nFckY3DQFhT9uf6ZTv49surG3P3uT1lNSSu" | |
56 "5wIDAQAB" | |
57 "-----END PUBLIC KEY-----"; | |
58 | |
59 // This is a good key, signed with the above test private key | |
16 const char* kSampleAPIKey = | 60 const char* kSampleAPIKey = |
17 "Signature|https://valid.example.com|Frobulate|1458766277"; | 61 "fsnbBl0XwKysvzH3d4TtIomsD9teP0PFfqxIYIAksfipEjB+cXAwI0tUzkYES4H0zZUZ2S982" |
18 | 62 "cZVEmrv0uX2LYKmsfXUhgZCwm46Xx6ZzX3BIg/U1noIlr50O+eB0iHAxe98Ph1NM1gPIlyaev" |
19 const char* kExpectedAPIKeySignature = "Signature"; | 63 "Lw75PPmXT5kUh15lJy+UPkKB8q52p3TKa2024Q3D2kGUWZ8DBD2zR5G+oHRtnKqfAh5fcTQyL" |
64 "Oa37NL66h0kTZ8WfvzATfTuAaAYuw+H5sYYeYTLrrVxhDuYqu/+kRzlQ42jlpNA0xkKEqRiIz" | |
65 "X0erG2umU/l8SQpvdXBC87JtOIseHS9dSUoKKRO1XWnmgXX9dA==|https://valid.exampl" | |
66 "e.com|Frobulate|1458766277"; | |
davidben
2015/12/18 22:23:17
FWIW, there's much much smaller signature schemes
iclelland
2015/12/22 05:45:28
That's a great idea, and I appreciate you enabling
| |
67 const char* kExpectedAPIKeySignature = | |
68 "fsnbBl0XwKysvzH3d4TtIomsD9teP0PFfqxIYIAksfipEjB+cXAwI0tUzkYES4H0zZUZ2S982" | |
69 "cZVEmrv0uX2LYKmsfXUhgZCwm46Xx6ZzX3BIg/U1noIlr50O+eB0iHAxe98Ph1NM1gPIlyaev" | |
70 "Lw75PPmXT5kUh15lJy+UPkKB8q52p3TKa2024Q3D2kGUWZ8DBD2zR5G+oHRtnKqfAh5fcTQyL" | |
71 "Oa37NL66h0kTZ8WfvzATfTuAaAYuw+H5sYYeYTLrrVxhDuYqu/+kRzlQ42jlpNA0xkKEqRiIz" | |
72 "X0erG2umU/l8SQpvdXBC87JtOIseHS9dSUoKKRO1XWnmgXX9dA=="; | |
20 const char* kExpectedAPIKeyData = | 73 const char* kExpectedAPIKeyData = |
21 "https://valid.example.com|Frobulate|1458766277"; | 74 "https://valid.example.com|Frobulate|1458766277"; |
22 const char* kExpectedAPIName = "Frobulate"; | 75 const char* kExpectedAPIName = "Frobulate"; |
23 const char* kExpectedOrigin = "https://valid.example.com"; | 76 const char* kExpectedOrigin = "https://valid.example.com"; |
24 const uint64_t kExpectedExpiry = 1458766277; | 77 const uint64_t kExpectedExpiry = 1458766277; |
25 | 78 |
26 double kValidTimestamp = 1458766276.0; | 79 double kValidTimestamp = 1458766276.0; |
27 double kInvalidTimestamp = 1458766278.0; | 80 double kInvalidTimestamp = 1458766278.0; |
28 | 81 |
82 // Well-formed API key with an invalid signature | |
83 const char* kInvalidSignatureAPIKey = | |
84 "CO8hDne98QeFeOJ0DbRZCBN3uE0nyaPgaLlkYhSWnbRoDfEAg+TXELaYfQPfEvKY" | |
85 "FauBg/hnxmba765hz0mXMco40xqjzo2r0o29s7ri7OklUsHXEUGCmVt31y5Zq3Qp" | |
86 "36aDM4D9JL6bkA4ESM2DR6KjVU76bFOZcT7nAFYFz5vpC3WuPu2qqvcW2o9v2JXu" | |
87 "fDYeySNZ3HrV5xmr8roqRMTiqMk99wEiUN+Dy4ddaE6XT+yzK+7C0XZxCf01RIiO" | |
88 "XKubdZbYvssq9CaYUJAS1N9BB9K2nxitL5VbDhNxbGVBK1EzzvtppNd9IQe34Bwp" | |
89 "f8iGJciYrfSOdoS753X8aw==|https://valid.example.com|Frobulate|145" | |
90 "8766277000"; | |
91 | |
29 } // namespace | 92 } // namespace |
30 | 93 |
31 class ApiKeyTest : public testing::Test {}; | 94 class ApiKeyTest : public testing::Test { |
95 protected: | |
96 bool ValidateDate(ApiKey* api_key, const base::Time& now) { | |
97 return api_key->ValidateDate(now); | |
98 } | |
99 | |
100 bool ValidateSignature(ApiKey* api_key, const char* publicKeyPEM) { | |
101 return api_key->ValidateSignature(publicKeyPEM); | |
102 } | |
103 }; | |
32 | 104 |
33 TEST_F(ApiKeyTest, ParseNullString) { | 105 TEST_F(ApiKeyTest, ParseNullString) { |
34 scoped_ptr<ApiKey> empty_key = ApiKey::Parse(std::string()); | 106 scoped_ptr<ApiKey> empty_key = ApiKey::Parse(std::string()); |
35 EXPECT_FALSE(empty_key); | 107 EXPECT_FALSE(empty_key); |
36 } | 108 } |
37 | 109 |
38 TEST_F(ApiKeyTest, ParseEmptyString) { | 110 TEST_F(ApiKeyTest, ParseEmptyString) { |
39 scoped_ptr<ApiKey> empty_key = ApiKey::Parse(""); | 111 scoped_ptr<ApiKey> empty_key = ApiKey::Parse(""); |
40 EXPECT_FALSE(empty_key); | 112 EXPECT_FALSE(empty_key); |
41 } | 113 } |
42 | 114 |
43 TEST_F(ApiKeyTest, ParseInvalidString) { | 115 TEST_F(ApiKeyTest, ParseInvalidString) { |
44 scoped_ptr<ApiKey> empty_key = ApiKey::Parse("abcdef"); | 116 scoped_ptr<ApiKey> empty_key = ApiKey::Parse("abcdef"); |
45 EXPECT_FALSE(empty_key); | 117 EXPECT_FALSE(empty_key); |
46 } | 118 } |
47 | 119 |
48 TEST_F(ApiKeyTest, ParseValidKeyString) { | 120 TEST_F(ApiKeyTest, ParseValidKeyString) { |
49 scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey); | 121 scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey); |
50 ASSERT_TRUE(key); | 122 ASSERT_TRUE(key); |
51 EXPECT_EQ(kExpectedAPIName, key->api_name()); | 123 EXPECT_EQ(kExpectedAPIName, key->api_name()); |
52 EXPECT_EQ(kExpectedAPIKeySignature, key->signature()); | 124 EXPECT_EQ(kExpectedAPIKeySignature, key->signature()); |
53 EXPECT_EQ(kExpectedAPIKeyData, key->data()); | 125 EXPECT_EQ(kExpectedAPIKeyData, key->data()); |
54 EXPECT_EQ(GURL(kExpectedOrigin), key->origin()); | 126 EXPECT_EQ(GURL(kExpectedOrigin), key->origin()); |
55 EXPECT_EQ(kExpectedExpiry, key->expiry_timestamp()); | 127 EXPECT_EQ(kExpectedExpiry, key->expiry_timestamp()); |
56 } | 128 } |
57 | 129 |
130 // Test internal validation methods | |
131 | |
132 TEST_F(ApiKeyTest, ValidateValidSignature) { | |
133 scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey); | |
134 ASSERT_TRUE(key); | |
135 EXPECT_TRUE(ValidateSignature(key.get(), kTestPublicKeyPEM)); | |
136 } | |
137 | |
138 TEST_F(ApiKeyTest, ValidateInvalidSignature) { | |
139 scoped_ptr<ApiKey> key = ApiKey::Parse(kInvalidSignatureAPIKey); | |
140 ASSERT_TRUE(key); | |
141 EXPECT_FALSE(ValidateSignature(key.get(), kTestPublicKeyPEM)); | |
142 } | |
143 | |
144 TEST_F(ApiKeyTest, ValidateSignatureOnWrongKey) { | |
145 scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey); | |
146 ASSERT_TRUE(key); | |
147 // Signature will be invalid if tested against the real public key | |
148 EXPECT_FALSE(key->IsValidNow(base::Time::FromDoubleT(kInvalidTimestamp))); | |
149 } | |
150 | |
58 TEST_F(ApiKeyTest, ValidateWhenNotExpired) { | 151 TEST_F(ApiKeyTest, ValidateWhenNotExpired) { |
59 scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey); | 152 scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey); |
60 ASSERT_TRUE(key); | 153 ASSERT_TRUE(key); |
61 EXPECT_TRUE(key->IsValidNow(base::Time::FromDoubleT(kValidTimestamp))); | 154 EXPECT_TRUE( |
155 ValidateDate(key.get(), base::Time::FromDoubleT(kValidTimestamp))); | |
62 } | 156 } |
63 | 157 |
64 TEST_F(ApiKeyTest, ValidateWhenExpired) { | 158 TEST_F(ApiKeyTest, ValidateWhenExpired) { |
65 scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey); | 159 scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey); |
66 ASSERT_TRUE(key); | 160 ASSERT_TRUE(key); |
67 EXPECT_FALSE(key->IsValidNow(base::Time::FromDoubleT(kInvalidTimestamp))); | 161 EXPECT_FALSE( |
162 ValidateDate(key.get(), base::Time::FromDoubleT(kInvalidTimestamp))); | |
68 } | 163 } |
69 | 164 |
70 } // namespace content | 165 } // namespace content |
OLD | NEW |