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 /* |
| 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"; |
| 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 |