Home | History | Annotate | Download | only in base
      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.
     19 int CompareSHA1Hashes(const void* a, const void* b) {
     20   return memcmp(a, b, base::kSHA1Length);
     21 }
     22 
     23 }  // namespace
     24 
     25 
     26 bool SHA1HashValue::Equals(const SHA1HashValue& other) const {
     27   return memcmp(data, other.data, sizeof(data)) == 0;
     28 }
     29 
     30 bool SHA256HashValue::Equals(const SHA256HashValue& other) const {
     31   return memcmp(data, other.data, sizeof(data)) == 0;
     32 }
     33 
     34 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 
     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 
     68 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 
     83 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 
     98 unsigned char* HashValue::data() {
     99   return const_cast<unsigned char*>(const_cast<const HashValue*>(this)->data());
    100 }
    101 
    102 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 
    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