• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/base/hash_value.h"
6 
7 #include "base/base64.h"
8 #include "base/logging.h"
9 #include "base/sha1.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/string_util.h"
12 
13 namespace net {
14 
15 namespace {
16 
17 // CompareSHA1Hashes is a helper function for using bsearch() with an array of
18 // SHA1 hashes.
CompareSHA1Hashes(const void * a,const void * b)19 int CompareSHA1Hashes(const void* a, const void* b) {
20   return memcmp(a, b, base::kSHA1Length);
21 }
22 
23 }  // namespace
24 
25 
Equals(const SHA1HashValue & other) const26 bool SHA1HashValue::Equals(const SHA1HashValue& other) const {
27   return memcmp(data, other.data, sizeof(data)) == 0;
28 }
29 
Equals(const SHA256HashValue & other) const30 bool SHA256HashValue::Equals(const SHA256HashValue& other) const {
31   return memcmp(data, other.data, sizeof(data)) == 0;
32 }
33 
Equals(const HashValue & other) const34 bool HashValue::Equals(const HashValue& other) const {
35   if (tag != other.tag)
36     return false;
37   switch (tag) {
38     case HASH_VALUE_SHA1:
39       return fingerprint.sha1.Equals(other.fingerprint.sha1);
40     case HASH_VALUE_SHA256:
41       return fingerprint.sha256.Equals(other.fingerprint.sha256);
42     default:
43       NOTREACHED() << "Unknown HashValueTag " << tag;
44       return false;
45   }
46 }
47 
FromString(const base::StringPiece value)48 bool HashValue::FromString(const base::StringPiece value) {
49   base::StringPiece base64_str;
50   if (value.starts_with("sha1/")) {
51     tag = HASH_VALUE_SHA1;
52     base64_str = value.substr(5);
53   } else if (value.starts_with("sha256/")) {
54     tag = HASH_VALUE_SHA256;
55     base64_str = value.substr(7);
56   } else {
57     return false;
58   }
59 
60   std::string decoded;
61   if (!base::Base64Decode(base64_str, &decoded) || decoded.size() != size())
62     return false;
63 
64   memcpy(data(), decoded.data(), size());
65   return true;
66 }
67 
ToString() const68 std::string HashValue::ToString() const {
69   std::string base64_str;
70   base::Base64Encode(base::StringPiece(reinterpret_cast<const char*>(data()),
71                                        size()), &base64_str);
72   switch (tag) {
73   case HASH_VALUE_SHA1:
74     return std::string("sha1/") + base64_str;
75   case HASH_VALUE_SHA256:
76     return std::string("sha256/") + base64_str;
77   default:
78     NOTREACHED() << "Unknown HashValueTag " << tag;
79     return std::string("unknown/" + base64_str);
80   }
81 }
82 
size() const83 size_t HashValue::size() const {
84   switch (tag) {
85     case HASH_VALUE_SHA1:
86       return sizeof(fingerprint.sha1.data);
87     case HASH_VALUE_SHA256:
88       return sizeof(fingerprint.sha256.data);
89     default:
90       NOTREACHED() << "Unknown HashValueTag " << tag;
91       // While an invalid tag should not happen, return a non-zero length
92       // to avoid compiler warnings when the result of size() is
93       // used with functions like memset.
94       return sizeof(fingerprint.sha1.data);
95   }
96 }
97 
data()98 unsigned char* HashValue::data() {
99   return const_cast<unsigned char*>(const_cast<const HashValue*>(this)->data());
100 }
101 
data() const102 const unsigned char* HashValue::data() const {
103   switch (tag) {
104     case HASH_VALUE_SHA1:
105       return fingerprint.sha1.data;
106     case HASH_VALUE_SHA256:
107       return fingerprint.sha256.data;
108     default:
109       NOTREACHED() << "Unknown HashValueTag " << tag;
110       return NULL;
111   }
112 }
113 
IsSHA1HashInSortedArray(const SHA1HashValue & hash,const uint8 * array,size_t array_byte_len)114 bool IsSHA1HashInSortedArray(const SHA1HashValue& hash,
115                              const uint8* array,
116                              size_t array_byte_len) {
117   DCHECK_EQ(0u, array_byte_len % base::kSHA1Length);
118   const size_t arraylen = array_byte_len / base::kSHA1Length;
119   return NULL != bsearch(hash.data, array, arraylen, base::kSHA1Length,
120                          CompareSHA1Hashes);
121 }
122 
123 }  // namespace net
124