OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "net/cert/ct_log_verifier.h" | 5 #include "net/cert/ct_log_verifier.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <string> | 10 #include <string> |
11 #include <vector> | |
11 | 12 |
13 #include "base/macros.h" | |
Ryan Sleevi
2016/07/26 19:33:44
? for what?
Rob Percival
2016/07/28 05:18:47
arraysize is used in this code. I added the #inclu
Ryan Sleevi
2016/07/28 14:54:49
There's a threshold to use judgement, but whenever
| |
12 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
13 #include "base/time/time.h" | 15 #include "base/time/time.h" |
14 #include "crypto/secure_hash.h" | 16 #include "crypto/secure_hash.h" |
15 #include "net/base/hash_value.h" | 17 #include "net/base/hash_value.h" |
16 #include "net/cert/ct_log_verifier_util.h" | 18 #include "net/cert/ct_log_verifier_util.h" |
19 #include "net/cert/merkle_audit_proof.h" | |
17 #include "net/cert/merkle_consistency_proof.h" | 20 #include "net/cert/merkle_consistency_proof.h" |
18 #include "net/cert/signed_certificate_timestamp.h" | 21 #include "net/cert/signed_certificate_timestamp.h" |
19 #include "net/cert/signed_tree_head.h" | 22 #include "net/cert/signed_tree_head.h" |
20 #include "net/test/ct_test_util.h" | 23 #include "net/test/ct_test_util.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
22 | 25 |
23 namespace net { | 26 namespace net { |
24 | 27 |
25 namespace { | 28 namespace { |
26 | 29 |
(...skipping 27 matching lines...) Expand all Loading... | |
54 size_t proof_length; | 57 size_t proof_length; |
55 TestVector proof[3]; | 58 TestVector proof[3]; |
56 }; | 59 }; |
57 | 60 |
58 // All test data replicated from | 61 // All test data replicated from |
59 // https://github.com/google/certificate-transparency/blob/c41b090ecc14ddd6b3531 dc7e5ce36b21e253fdd/cpp/merkletree/merkle_tree_test.cc | 62 // https://github.com/google/certificate-transparency/blob/c41b090ecc14ddd6b3531 dc7e5ce36b21e253fdd/cpp/merkletree/merkle_tree_test.cc |
60 // A hash of the empty string. | 63 // A hash of the empty string. |
61 const TestVector kSHA256EmptyTreeHash = { | 64 const TestVector kSHA256EmptyTreeHash = { |
62 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", 32}; | 65 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", 32}; |
63 | 66 |
67 // Hashes of the leaf data for the sample tree (8 leaves). | |
68 const TestVector kSHA256LeafHashes[8] = { | |
69 {"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, | |
70 {"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", 32}, | |
71 {"0298d122906dcfc10892cb53a73992fc5b9f493ea4c9badb27b791b4127a7fe7", 32}, | |
72 {"07506a85fd9dd2f120eb694f86011e5bb4662e5c415a62917033d4a9624487e7", 32}, | |
73 {"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", 32}, | |
74 {"4271a26be0d8a84f0bd54c8c302e7cb3a3b5d1fa6780a40bcce2873477dab658", 32}, | |
75 {"b08693ec2e721597130641e8211e7eedccb4c26413963eee6c1e2ed16ffb1a5f", 32}, | |
76 {"46f6ffadd3d06a09ff3c5860d2755c8b9819db7df44251788c7d8e3180de8eb1", 32}, | |
77 }; | |
78 | |
64 // Incremental roots from building the sample tree of size 8 leaf-by-leaf. | 79 // Incremental roots from building the sample tree of size 8 leaf-by-leaf. |
65 // The first entry is the root at size 0, the last is the root at size 8. | 80 // The first entry is the root at size 0, the last is the root at size 8. |
66 const TestVector kSHA256Roots[8] = { | 81 const TestVector kSHA256Roots[8] = { |
67 {"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, | 82 {"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, |
68 {"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", 32}, | 83 {"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", 32}, |
69 {"aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", 32}, | 84 {"aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", 32}, |
70 {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", 32}, | 85 {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", 32}, |
71 {"4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4", 32}, | 86 {"4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4", 32}, |
72 {"76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef", 32}, | 87 {"76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef", 32}, |
73 {"ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", 32}, | 88 {"ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", 32}, |
(...skipping 23 matching lines...) Expand all Loading... | |
97 32}}}, | 112 32}}}, |
98 // Consistency proof between tree of size 2 and tree of size 5, with 2 | 113 // Consistency proof between tree of size 2 and tree of size 5, with 2 |
99 // nodes in the proof. | 114 // nodes in the proof. |
100 {2, | 115 {2, |
101 5, | 116 5, |
102 2, | 117 2, |
103 {{"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, | 118 {{"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, |
104 {"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", 32}, | 119 {"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", 32}, |
105 {"", 0}}}}; | 120 {"", 0}}}}; |
106 | 121 |
122 // A single audit proof. Contains the leaf index (leaf), tree size (snapshot), | |
123 // the length of the proof (proof_length) and at most 3 proof nodes (all test | |
124 // proofs will be for a tree of size 8). | |
125 struct PathTestVector { | |
126 int leaf; | |
127 int snapshot; | |
Ryan Sleevi
2016/07/26 19:33:44
Why are these stored as int, and then force-coerce
Rob Percival
2016/07/28 05:18:47
The answer to most of your following comments is t
| |
128 int path_length; | |
Ryan Sleevi
2016/07/26 19:33:45
path_length should be size_t
Rob Percival
2016/08/25 17:44:59
Done.
| |
129 TestVector path[3]; | |
130 }; | |
131 | |
132 // A collection of audit proofs for various leaves and sub-trees of the tree | |
133 // defined by |kSHA256Roots|. | |
134 const PathTestVector kSHA256Paths[6] = { | |
135 {0, 0, 0, {{"", 0}, {"", 0}, {"", 0}}}, | |
136 {1, 1, 0, {{"", 0}, {"", 0}, {"", 0}}}, | |
137 {1, | |
138 8, | |
139 3, | |
140 {{"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", 32}, | |
141 {"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, | |
142 {"6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4", | |
143 32}}}, | |
144 {6, | |
145 8, | |
146 3, | |
147 {{"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", 32}, | |
148 {"ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0", 32}, | |
149 {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", | |
150 32}}}, | |
151 {3, | |
152 3, | |
153 1, | |
154 {{"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", 32}, | |
155 {"", 0}, | |
156 {"", 0}}}, | |
157 {2, | |
158 5, | |
159 3, | |
160 {{"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, | |
161 {"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, | |
162 {"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", | |
163 32}}}}; | |
164 | |
107 // Decodes a hexadecimal string into the binary data it represents. | 165 // Decodes a hexadecimal string into the binary data it represents. |
108 std::string HexToBytes(const char* hex_data, size_t hex_data_length) { | 166 std::string HexToBytes(const char* hex_data, size_t hex_data_length) { |
109 std::vector<uint8_t> output; | 167 std::vector<uint8_t> output; |
110 std::string result; | 168 std::string result; |
111 std::string hex_data_input(hex_data, hex_data_length); | 169 std::string hex_data_input(hex_data, hex_data_length); |
112 if (base::HexStringToBytes(hex_data, &output)) | 170 if (base::HexStringToBytes(hex_data, &output)) |
113 result.assign(reinterpret_cast<const char*>(&output[0]), output.size()); | 171 result.assign(reinterpret_cast<const char*>(&output[0]), output.size()); |
114 return result; | 172 return result; |
115 } | 173 } |
116 | 174 |
(...skipping 14 matching lines...) Expand all Loading... | |
131 const std::string& old_tree_root, | 189 const std::string& old_tree_root, |
132 uint64_t new_tree_size, | 190 uint64_t new_tree_size, |
133 const std::string& new_tree_root, | 191 const std::string& new_tree_root, |
134 const std::vector<std::string>& proof) { | 192 const std::vector<std::string>& proof) { |
135 return log->VerifyConsistencyProof( | 193 return log->VerifyConsistencyProof( |
136 ct::MerkleConsistencyProof(log->key_id(), proof, old_tree_size, | 194 ct::MerkleConsistencyProof(log->key_id(), proof, old_tree_size, |
137 new_tree_size), | 195 new_tree_size), |
138 old_tree_root, new_tree_root); | 196 old_tree_root, new_tree_root); |
139 } | 197 } |
140 | 198 |
199 bool VerifyAuditProof(scoped_refptr<const CTLogVerifier> log, | |
200 uint64_t leaf, | |
201 uint64_t tree_size, | |
202 const std::vector<std::string>& proof, | |
203 const std::string& tree_root, | |
204 const std::string& leaf_hash) { | |
205 // Test vectors use a 1-based leaf index, but our code uses a 0-based index. | |
Ryan Sleevi
2016/07/26 19:33:45
https://groups.google.com/a/chromium.org/d/msg/chr
Rob Percival
2016/07/28 05:18:47
I'll improve this, though I'd like to get rid of t
| |
206 if (leaf == 0) | |
207 return false; | |
208 return log->VerifyAuditProof(ct::MerkleAuditProof(leaf - 1, tree_size, proof), | |
209 tree_root, leaf_hash); | |
210 } | |
211 | |
141 class CTLogVerifierTest : public ::testing::Test { | 212 class CTLogVerifierTest : public ::testing::Test { |
142 public: | 213 public: |
143 CTLogVerifierTest() {} | 214 CTLogVerifierTest() {} |
144 | 215 |
145 void SetUp() override { | 216 void SetUp() override { |
146 log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog", | 217 log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog", |
147 "https://ct.example.com", "ct.example.com"); | 218 "https://ct.example.com", "ct.example.com"); |
148 | 219 |
149 ASSERT_TRUE(log_); | 220 ASSERT_TRUE(log_); |
150 ASSERT_EQ(ct::GetTestPublicKeyId(), log_->key_id()); | 221 ASSERT_EQ(ct::GetTestPublicKeyId(), log_->key_id()); |
151 ASSERT_EQ("ct.example.com", log_->dns_domain()); | 222 ASSERT_EQ("ct.example.com", log_->dns_domain()); |
152 } | 223 } |
153 | 224 |
225 // Given an audit proof for a leaf in the tree, asserts that it verifies and | |
226 // no other combination of leaves, snapshots and proof nodes verifies. | |
Ryan Sleevi
2016/07/26 19:33:44
Every one of these checks should be separate tests
Rob Percival
2016/07/28 05:18:47
Again, inherited from the original tests. If I fin
Ryan Sleevi
2016/07/28 16:40:47
Well, whether or not we split it out to parameteri
Rob Percival
2016/08/25 17:44:59
That should be sufficient, but Eran is quite passi
| |
227 void VerifierCheck(int leaf, | |
228 int tree_size, | |
229 const std::vector<std::string>& path, | |
230 const std::string& root, | |
231 const std::string& leaf_hash) { | |
232 // Verify the original path. | |
233 EXPECT_TRUE(VerifyAuditProof(log_, leaf, tree_size, path, root, leaf_hash)); | |
234 | |
235 // Wrong leaf index. | |
236 EXPECT_FALSE( | |
237 VerifyAuditProof(log_, leaf - 1, tree_size, path, root, leaf_hash)); | |
238 EXPECT_FALSE( | |
239 VerifyAuditProof(log_, leaf + 1, tree_size, path, root, leaf_hash)); | |
240 EXPECT_FALSE( | |
241 VerifyAuditProof(log_, leaf ^ 2, tree_size, path, root, leaf_hash)); | |
242 | |
243 // Wrong tree height. | |
244 EXPECT_FALSE( | |
245 VerifyAuditProof(log_, leaf, tree_size * 2, path, root, leaf_hash)); | |
246 EXPECT_FALSE( | |
247 VerifyAuditProof(log_, leaf, tree_size / 2, path, root, leaf_hash)); | |
248 | |
249 // Wrong root. | |
250 EXPECT_FALSE(VerifyAuditProof(log_, leaf, tree_size, path, | |
251 HexToBytes(kSHA256EmptyTreeHash), leaf_hash)); | |
252 | |
253 // Wrong paths. | |
254 std::vector<std::string> wrong_path; | |
255 | |
256 // Modify a single element on the path. | |
257 for (size_t j = 0; j < path.size(); ++j) { | |
258 wrong_path = path; | |
259 wrong_path[j] = HexToBytes(kSHA256EmptyTreeHash); | |
260 EXPECT_FALSE( | |
261 VerifyAuditProof(log_, leaf, tree_size, wrong_path, root, leaf_hash)); | |
262 } | |
263 | |
264 // Add garbage at the end of the path. | |
265 wrong_path = path; | |
266 wrong_path.push_back(std::string()); | |
267 EXPECT_FALSE( | |
268 VerifyAuditProof(log_, leaf, tree_size, wrong_path, root, leaf_hash)); | |
269 wrong_path.pop_back(); | |
270 | |
271 wrong_path.push_back(root); | |
272 EXPECT_FALSE( | |
273 VerifyAuditProof(log_, leaf, tree_size, wrong_path, root, leaf_hash)); | |
274 wrong_path.pop_back(); | |
275 | |
276 // Remove a node from the end. | |
277 if (!wrong_path.empty()) { | |
278 wrong_path.pop_back(); | |
279 EXPECT_FALSE( | |
280 VerifyAuditProof(log_, leaf, tree_size, wrong_path, root, leaf_hash)); | |
281 } | |
282 | |
283 // Add garbage in the beginning of the path. | |
284 wrong_path.clear(); | |
285 wrong_path.push_back(std::string()); | |
286 wrong_path.insert(wrong_path.end(), path.begin(), path.end()); | |
287 EXPECT_FALSE( | |
288 VerifyAuditProof(log_, leaf, tree_size, wrong_path, root, leaf_hash)); | |
289 | |
290 wrong_path[0] = root; | |
291 EXPECT_FALSE( | |
292 VerifyAuditProof(log_, leaf, tree_size, wrong_path, root, leaf_hash)); | |
293 } | |
294 | |
154 // Given a consistency proof between two snapshots of the tree, asserts that | 295 // Given a consistency proof between two snapshots of the tree, asserts that |
155 // it verifies and no other combination of snapshots and proof nodes verifies. | 296 // it verifies and no other combination of snapshots and proof nodes verifies. |
156 void VerifierConsistencyCheck(int snapshot1, | 297 void VerifierConsistencyCheck(int snapshot1, |
157 int snapshot2, | 298 int snapshot2, |
158 const std::string& root1, | 299 const std::string& root1, |
159 const std::string& root2, | 300 const std::string& root2, |
160 const std::vector<std::string>& proof) { | 301 const std::vector<std::string>& proof) { |
161 // Verify the original consistency proof. | 302 // Verify the original consistency proof. |
162 EXPECT_TRUE( | 303 EXPECT_TRUE( |
163 VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, root2, proof)) | 304 VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, root2, proof)) |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
432 if (input_size == 1) | 573 if (input_size == 1) |
433 return TreeHasher::HashLeaf(inputs[0]); | 574 return TreeHasher::HashLeaf(inputs[0]); |
434 | 575 |
435 const uint64_t split = CalculateNearestPowerOfTwo(input_size); | 576 const uint64_t split = CalculateNearestPowerOfTwo(input_size); |
436 | 577 |
437 return ct::internal::HashNodes( | 578 return ct::internal::HashNodes( |
438 ReferenceMerkleTreeHash(&inputs[0], split), | 579 ReferenceMerkleTreeHash(&inputs[0], split), |
439 ReferenceMerkleTreeHash(&inputs[split], input_size - split)); | 580 ReferenceMerkleTreeHash(&inputs[split], input_size - split)); |
440 } | 581 } |
441 | 582 |
583 // Reference implementation of Merkle paths. Path from leaf to root, | |
584 // excluding the leaf and root themselves. Returns an audit proof for the tree | |
585 // leaf with index |leaf| (1-based). The tree is designated by |inputs|. | |
586 std::vector<std::string> ReferenceMerklePath(std::string* inputs, | |
587 uint64_t input_size, | |
588 uint64_t leaf) { | |
589 std::vector<std::string> path; | |
590 if (leaf > input_size || leaf == 0) | |
591 return path; | |
592 | |
593 if (input_size == 1) | |
594 return path; | |
595 | |
596 const uint64_t split = CalculateNearestPowerOfTwo(input_size); | |
597 | |
598 std::vector<std::string> subpath; | |
599 if (leaf <= split) { | |
600 subpath = ReferenceMerklePath(&inputs[0], split, leaf); | |
601 path.insert(path.end(), subpath.begin(), subpath.end()); | |
602 path.push_back(ReferenceMerkleTreeHash(&inputs[split], input_size - split)); | |
603 } else { | |
604 subpath = | |
605 ReferenceMerklePath(&inputs[split], input_size - split, leaf - split); | |
606 path.insert(path.end(), subpath.begin(), subpath.end()); | |
607 path.push_back(ReferenceMerkleTreeHash(&inputs[0], split)); | |
608 } | |
609 | |
610 return path; | |
611 } | |
612 | |
442 // Reference implementation of snapshot consistency. Returns a | 613 // Reference implementation of snapshot consistency. Returns a |
443 // consistency proof between two snapshots of the tree designated | 614 // consistency proof between two snapshots of the tree designated |
444 // by |inputs|. | 615 // by |inputs|. |
445 // Call with have_root1 = true. | 616 // Call with have_root1 = true. |
446 std::vector<std::string> ReferenceSnapshotConsistency(std::string* inputs, | 617 std::vector<std::string> ReferenceSnapshotConsistency(std::string* inputs, |
447 uint64_t snapshot2, | 618 uint64_t snapshot2, |
448 uint64_t snapshot1, | 619 uint64_t snapshot1, |
449 bool have_root1) { | 620 bool have_root1) { |
450 std::vector<std::string> proof; | 621 std::vector<std::string> proof; |
451 if (snapshot1 == 0 || snapshot1 > snapshot2) | 622 if (snapshot1 == 0 || snapshot1 > snapshot2) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
497 TEST_F(CTLogVerifierTest, | 668 TEST_F(CTLogVerifierTest, |
498 MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator) { | 669 MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator) { |
499 std::vector<std::string> data; | 670 std::vector<std::string> data; |
500 for (int i = 0; i < 256; ++i) | 671 for (int i = 0; i < 256; ++i) |
501 data.push_back(std::string(1, i)); | 672 data.push_back(std::string(1, i)); |
502 | 673 |
503 std::vector<std::string> proof; | 674 std::vector<std::string> proof; |
504 std::string root1, root2; | 675 std::string root1, root2; |
505 // More tests with reference proof generator. | 676 // More tests with reference proof generator. |
506 for (size_t tree_size = 1; tree_size <= data.size() / 2; ++tree_size) { | 677 for (size_t tree_size = 1; tree_size <= data.size() / 2; ++tree_size) { |
678 SCOPED_TRACE(tree_size); | |
507 root2 = ReferenceMerkleTreeHash(data.data(), tree_size); | 679 root2 = ReferenceMerkleTreeHash(data.data(), tree_size); |
508 // Repeat for each snapshot in range. | 680 // Repeat for each snapshot in range. |
509 for (size_t snapshot = 1; snapshot <= tree_size; ++snapshot) { | 681 for (size_t snapshot = 1; snapshot <= tree_size; ++snapshot) { |
682 SCOPED_TRACE(snapshot); | |
510 proof = | 683 proof = |
511 ReferenceSnapshotConsistency(data.data(), tree_size, snapshot, true); | 684 ReferenceSnapshotConsistency(data.data(), tree_size, snapshot, true); |
512 root1 = ReferenceMerkleTreeHash(data.data(), snapshot); | 685 root1 = ReferenceMerkleTreeHash(data.data(), snapshot); |
513 VerifierConsistencyCheck(snapshot, tree_size, root1, root2, proof); | 686 VerifierConsistencyCheck(snapshot, tree_size, root1, root2, proof); |
514 } | 687 } |
515 } | 688 } |
516 } | 689 } |
517 | 690 |
691 TEST_F(CTLogVerifierTest, VerifiesAuditProofEdgeCases_EmptyProof) { | |
692 std::vector<std::string> path; | |
693 // Various invalid paths. | |
694 EXPECT_FALSE( | |
695 VerifyAuditProof(log_, 0, 0, path, std::string(), std::string())); | |
696 EXPECT_FALSE( | |
697 VerifyAuditProof(log_, 0, 1, path, std::string(), std::string())); | |
698 EXPECT_FALSE( | |
699 VerifyAuditProof(log_, 1, 0, path, std::string(), std::string())); | |
700 EXPECT_FALSE( | |
701 VerifyAuditProof(log_, 2, 1, path, std::string(), std::string())); | |
Ryan Sleevi
2016/07/26 19:33:44
All should be grouped into a new test; this seems
Rob Percival
2016/08/25 17:44:59
Done. The cases with a leaf index of 0 were pointl
| |
702 | |
703 const std::string empty_hash = HexToBytes(kSHA256EmptyTreeHash); | |
704 EXPECT_FALSE(VerifyAuditProof(log_, 0, 0, path, empty_hash, std::string())); | |
705 EXPECT_FALSE(VerifyAuditProof(log_, 0, 1, path, empty_hash, std::string())); | |
706 EXPECT_FALSE(VerifyAuditProof(log_, 1, 0, path, empty_hash, std::string())); | |
707 EXPECT_FALSE(VerifyAuditProof(log_, 2, 1, path, empty_hash, std::string())); | |
708 } | |
709 | |
710 TEST_F(CTLogVerifierTest, VerifiesValidAuditProofs) { | |
711 std::vector<std::string> path; | |
712 // Known good paths. | |
713 // i = 0 is an invalid path. | |
714 for (int i = 1; i < 6; ++i) { | |
715 SCOPED_TRACE(i); | |
716 // Construct the path. | |
717 path.clear(); | |
718 for (int j = 0; j < kSHA256Paths[i].path_length; ++j) | |
719 path.push_back(HexToBytes(kSHA256Paths[i].path[j])); | |
720 const TestVector& root_hash = kSHA256Roots[kSHA256Paths[i].snapshot - 1]; | |
721 VerifierCheck(kSHA256Paths[i].leaf, kSHA256Paths[i].snapshot, path, | |
722 HexToBytes(root_hash), | |
723 HexToBytes(kSHA256LeafHashes[kSHA256Paths[i].leaf - 1])); | |
724 } | |
725 } | |
726 | |
727 TEST_F(CTLogVerifierTest, VerifiesValidAuditProofsFromReferenceGenerator) { | |
728 std::vector<std::string> data; | |
729 for (size_t i = 0; i < 256; ++i) | |
730 data.emplace_back(1, i); | |
731 | |
732 // More tests with reference path generator. | |
733 std::string root; | |
734 std::vector<std::string> path; | |
735 for (size_t tree_size = 1; tree_size <= data.size() / 2; ++tree_size) { | |
736 SCOPED_TRACE(tree_size); | |
737 // Repeat for each leaf in range. | |
738 for (size_t leaf = 1; leaf <= tree_size; ++leaf) { | |
739 SCOPED_TRACE(leaf); | |
740 path = ReferenceMerklePath(data.data(), tree_size, leaf); | |
741 root = ReferenceMerkleTreeHash(data.data(), tree_size); | |
742 VerifierCheck(leaf, tree_size, path, root, | |
743 TreeHasher::HashLeaf(data[leaf - 1])); | |
744 } | |
745 } | |
746 } | |
747 | |
518 } // namespace | 748 } // namespace |
519 | 749 |
520 } // namespace net | 750 } // namespace net |
OLD | NEW |