xref: /aosp_15_r20/external/cronet/net/base/hash_value.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/base/hash_value.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <algorithm>
10*6777b538SAndroid Build Coastguard Worker #include <ostream>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/base64.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_split.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
18*6777b538SAndroid Build Coastguard Worker #include "crypto/sha2.h"
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker namespace net {
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker namespace {
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker constexpr std::string_view kSha256Slash = "sha256/";
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker // LessThan comparator for use with std::binary_search() in determining
27*6777b538SAndroid Build Coastguard Worker // whether a SHA-256 HashValue appears within a sorted array of
28*6777b538SAndroid Build Coastguard Worker // SHA256HashValues.
29*6777b538SAndroid Build Coastguard Worker struct SHA256ToHashValueComparator {
operator ()net::__anon4a6dfd150111::SHA256ToHashValueComparator30*6777b538SAndroid Build Coastguard Worker   bool operator()(const SHA256HashValue& lhs, const HashValue& rhs) const {
31*6777b538SAndroid Build Coastguard Worker     DCHECK_EQ(HASH_VALUE_SHA256, rhs.tag());
32*6777b538SAndroid Build Coastguard Worker     return memcmp(lhs.data, rhs.data(), rhs.size()) < 0;
33*6777b538SAndroid Build Coastguard Worker   }
34*6777b538SAndroid Build Coastguard Worker 
operator ()net::__anon4a6dfd150111::SHA256ToHashValueComparator35*6777b538SAndroid Build Coastguard Worker   bool operator()(const HashValue& lhs, const SHA256HashValue& rhs) const {
36*6777b538SAndroid Build Coastguard Worker     DCHECK_EQ(HASH_VALUE_SHA256, lhs.tag());
37*6777b538SAndroid Build Coastguard Worker     return memcmp(lhs.data(), rhs.data, lhs.size()) < 0;
38*6777b538SAndroid Build Coastguard Worker   }
39*6777b538SAndroid Build Coastguard Worker };
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker }  // namespace
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker 
HashValue(const SHA256HashValue & hash)44*6777b538SAndroid Build Coastguard Worker HashValue::HashValue(const SHA256HashValue& hash)
45*6777b538SAndroid Build Coastguard Worker     : HashValue(HASH_VALUE_SHA256) {
46*6777b538SAndroid Build Coastguard Worker   fingerprint.sha256 = hash;
47*6777b538SAndroid Build Coastguard Worker }
48*6777b538SAndroid Build Coastguard Worker 
FromString(std::string_view value)49*6777b538SAndroid Build Coastguard Worker bool HashValue::FromString(std::string_view value) {
50*6777b538SAndroid Build Coastguard Worker   if (!value.starts_with(kSha256Slash)) {
51*6777b538SAndroid Build Coastguard Worker     return false;
52*6777b538SAndroid Build Coastguard Worker   }
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker   std::string_view base64_str = value.substr(kSha256Slash.size());
55*6777b538SAndroid Build Coastguard Worker 
56*6777b538SAndroid Build Coastguard Worker   auto decoded = base::Base64Decode(base64_str);
57*6777b538SAndroid Build Coastguard Worker   if (!decoded || decoded->size() != size()) {
58*6777b538SAndroid Build Coastguard Worker     return false;
59*6777b538SAndroid Build Coastguard Worker   }
60*6777b538SAndroid Build Coastguard Worker   tag_ = HASH_VALUE_SHA256;
61*6777b538SAndroid Build Coastguard Worker   memcpy(data(), decoded->data(), size());
62*6777b538SAndroid Build Coastguard Worker   return true;
63*6777b538SAndroid Build Coastguard Worker }
64*6777b538SAndroid Build Coastguard Worker 
ToString() const65*6777b538SAndroid Build Coastguard Worker std::string HashValue::ToString() const {
66*6777b538SAndroid Build Coastguard Worker   std::string base64_str = base::Base64Encode(base::make_span(data(), size()));
67*6777b538SAndroid Build Coastguard Worker   switch (tag_) {
68*6777b538SAndroid Build Coastguard Worker     case HASH_VALUE_SHA256:
69*6777b538SAndroid Build Coastguard Worker       return std::string(kSha256Slash) + base64_str;
70*6777b538SAndroid Build Coastguard Worker   }
71*6777b538SAndroid Build Coastguard Worker 
72*6777b538SAndroid Build Coastguard Worker   NOTREACHED_NORETURN();
73*6777b538SAndroid Build Coastguard Worker }
74*6777b538SAndroid Build Coastguard Worker 
size() const75*6777b538SAndroid Build Coastguard Worker size_t HashValue::size() const {
76*6777b538SAndroid Build Coastguard Worker   switch (tag_) {
77*6777b538SAndroid Build Coastguard Worker     case HASH_VALUE_SHA256:
78*6777b538SAndroid Build Coastguard Worker       return sizeof(fingerprint.sha256.data);
79*6777b538SAndroid Build Coastguard Worker   }
80*6777b538SAndroid Build Coastguard Worker 
81*6777b538SAndroid Build Coastguard Worker   NOTREACHED_NORETURN();
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker 
data()84*6777b538SAndroid Build Coastguard Worker unsigned char* HashValue::data() {
85*6777b538SAndroid Build Coastguard Worker   return const_cast<unsigned char*>(const_cast<const HashValue*>(this)->data());
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker 
data() const88*6777b538SAndroid Build Coastguard Worker const unsigned char* HashValue::data() const {
89*6777b538SAndroid Build Coastguard Worker   switch (tag_) {
90*6777b538SAndroid Build Coastguard Worker     case HASH_VALUE_SHA256:
91*6777b538SAndroid Build Coastguard Worker       return fingerprint.sha256.data;
92*6777b538SAndroid Build Coastguard Worker   }
93*6777b538SAndroid Build Coastguard Worker 
94*6777b538SAndroid Build Coastguard Worker   NOTREACHED_NORETURN();
95*6777b538SAndroid Build Coastguard Worker }
96*6777b538SAndroid Build Coastguard Worker 
operator ==(const HashValue & lhs,const HashValue & rhs)97*6777b538SAndroid Build Coastguard Worker bool operator==(const HashValue& lhs, const HashValue& rhs) {
98*6777b538SAndroid Build Coastguard Worker   if (lhs.tag_ != rhs.tag_)
99*6777b538SAndroid Build Coastguard Worker     return false;
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker   switch (lhs.tag_) {
102*6777b538SAndroid Build Coastguard Worker     case HASH_VALUE_SHA256:
103*6777b538SAndroid Build Coastguard Worker       return lhs.fingerprint.sha256 == rhs.fingerprint.sha256;
104*6777b538SAndroid Build Coastguard Worker   }
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker   NOTREACHED_NORETURN();
107*6777b538SAndroid Build Coastguard Worker }
108*6777b538SAndroid Build Coastguard Worker 
operator !=(const HashValue & lhs,const HashValue & rhs)109*6777b538SAndroid Build Coastguard Worker bool operator!=(const HashValue& lhs, const HashValue& rhs) {
110*6777b538SAndroid Build Coastguard Worker   return !(lhs == rhs);
111*6777b538SAndroid Build Coastguard Worker }
112*6777b538SAndroid Build Coastguard Worker 
operator <(const HashValue & lhs,const HashValue & rhs)113*6777b538SAndroid Build Coastguard Worker bool operator<(const HashValue& lhs, const HashValue& rhs) {
114*6777b538SAndroid Build Coastguard Worker   if (lhs.tag_ != rhs.tag_)
115*6777b538SAndroid Build Coastguard Worker     return lhs.tag_ < rhs.tag_;
116*6777b538SAndroid Build Coastguard Worker 
117*6777b538SAndroid Build Coastguard Worker   switch (lhs.tag_) {
118*6777b538SAndroid Build Coastguard Worker     case HASH_VALUE_SHA256:
119*6777b538SAndroid Build Coastguard Worker       return lhs.fingerprint.sha256 < rhs.fingerprint.sha256;
120*6777b538SAndroid Build Coastguard Worker   }
121*6777b538SAndroid Build Coastguard Worker 
122*6777b538SAndroid Build Coastguard Worker   NOTREACHED();
123*6777b538SAndroid Build Coastguard Worker   return false;
124*6777b538SAndroid Build Coastguard Worker }
125*6777b538SAndroid Build Coastguard Worker 
operator >(const HashValue & lhs,const HashValue & rhs)126*6777b538SAndroid Build Coastguard Worker bool operator>(const HashValue& lhs, const HashValue& rhs) {
127*6777b538SAndroid Build Coastguard Worker   return rhs < lhs;
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker 
operator <=(const HashValue & lhs,const HashValue & rhs)130*6777b538SAndroid Build Coastguard Worker bool operator<=(const HashValue& lhs, const HashValue& rhs) {
131*6777b538SAndroid Build Coastguard Worker   return !(lhs > rhs);
132*6777b538SAndroid Build Coastguard Worker }
133*6777b538SAndroid Build Coastguard Worker 
operator >=(const HashValue & lhs,const HashValue & rhs)134*6777b538SAndroid Build Coastguard Worker bool operator>=(const HashValue& lhs, const HashValue& rhs) {
135*6777b538SAndroid Build Coastguard Worker   return !(lhs < rhs);
136*6777b538SAndroid Build Coastguard Worker }
137*6777b538SAndroid Build Coastguard Worker 
IsSHA256HashInSortedArray(const HashValue & hash,base::span<const SHA256HashValue> array)138*6777b538SAndroid Build Coastguard Worker bool IsSHA256HashInSortedArray(const HashValue& hash,
139*6777b538SAndroid Build Coastguard Worker                                base::span<const SHA256HashValue> array) {
140*6777b538SAndroid Build Coastguard Worker   return std::binary_search(array.begin(), array.end(), hash,
141*6777b538SAndroid Build Coastguard Worker                             SHA256ToHashValueComparator());
142*6777b538SAndroid Build Coastguard Worker }
143*6777b538SAndroid Build Coastguard Worker 
IsAnySHA256HashInSortedArray(base::span<const HashValue> hashes,base::span<const SHA256HashValue> array)144*6777b538SAndroid Build Coastguard Worker bool IsAnySHA256HashInSortedArray(base::span<const HashValue> hashes,
145*6777b538SAndroid Build Coastguard Worker                                   base::span<const SHA256HashValue> array) {
146*6777b538SAndroid Build Coastguard Worker   for (const auto& hash : hashes) {
147*6777b538SAndroid Build Coastguard Worker     if (hash.tag() != HASH_VALUE_SHA256)
148*6777b538SAndroid Build Coastguard Worker       continue;
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker     if (IsSHA256HashInSortedArray(hash, array))
151*6777b538SAndroid Build Coastguard Worker       return true;
152*6777b538SAndroid Build Coastguard Worker   }
153*6777b538SAndroid Build Coastguard Worker   return false;
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker 
156*6777b538SAndroid Build Coastguard Worker }  // namespace net
157