Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 14:04:28 +01:00
parent 81b91f4139
commit f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions

View file

@ -0,0 +1,41 @@
# Choosing A Hash Function
> Note: this document is still very much a work-in-progress. Currently missing:
> - recommendations for hashed containers
> - recommendations for a better persistent hash
> - recommendations for a secure hash
If a hash function with unchanging output is needed, please select from one of
the unchanging forever options below.
## Non-cryptographic
name | input | output | unchanging forever | notes
---------------------------------------------|-----------------------------|------------|--------------------|-------
[`Hash()`][hash] | overloaded | `uint32_t` | no | This function is currently being updated to return `size_t`.
[`PersistentHash()`][persistenthash] | overloaded | `uint32_t` | yes | Fairly weak but widely used for persisted hashes.
[`CityHash64()`][cityhash64] | `base::span<const uint8_t>` | `uint64_t` | yes (note 1) | Version 1.0.3. Has some known weaknesses.
[`CityHash64WithSeed()`][cityhash64withseed] | `base::span<const uint8_t>` | `uint64_t` | yes (note 1) | Version 1.0.3. Has some known weaknesses.
## Cryptographic
**There are no hashes in `//base` that provide cryptographic security.**
name | input | output | unchanging forever | notes
-------------------------------|---------------|---------------|--------------------|-------
[`MD5String()`][md5string] | `std::string` | `std::string` | yes | **INSECURE**
[`SHA1HashString`][sha1string] | `std::string` | `std::string` | yes | **INSECURE**
## Deprecated
> Note: CRC32, Murmur2, and Murmur3 will be listed here.
Note 1: While CityHash is not guaranteed unchanging forever, the version used in
Chrome is pinned to version 1.0.3.
[hash]: https://cs.chromium.org/chromium/src/base/hash/hash.h?l=26
[persistenthash]: https://cs.chromium.org/chromium/src/base/hash/hash.h?l=36
[cityhash64]: https://cs.chromium.org/chromium/src/base/hash/city_v103.h?l=19
[cityhash64withseed]: https://cs.chromium.org/chromium/src/base/hash/city_v103.h?l=20
[md5string]: https://cs.chromium.org/chromium/src/base/hash/md5.h?l=74
[sha1string]: https://cs.chromium.org/chromium/src/base/hash/sha1.h?l=22

View file

@ -0,0 +1,167 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/hash/hash.h"
#include "base/rand_util.h"
#include "base/third_party/cityhash/city.h"
#include "build/build_config.h"
// Definition in base/third_party/superfasthash/superfasthash.c. (Third-party
// code did not come with its own header file, so declaring the function here.)
// Note: This algorithm is also in Blink under Source/wtf/StringHasher.h.
extern "C" uint32_t SuperFastHash(const char* data, int len);
namespace base {
namespace {
size_t FastHashImpl(base::span<const uint8_t> data) {
// We use the updated CityHash within our namespace (not the deprecated
// version from third_party/smhasher).
#if defined(ARCH_CPU_64_BITS)
return base::internal::cityhash_v111::CityHash64(
reinterpret_cast<const char*>(data.data()), data.size());
#else
return base::internal::cityhash_v111::CityHash32(
reinterpret_cast<const char*>(data.data()), data.size());
#endif
}
// Implement hashing for pairs of at-most 32 bit integer values.
// When size_t is 32 bits, we turn the 64-bit hash code into 32 bits by using
// multiply-add hashing. This algorithm, as described in
// Theorem 4.3.3 of the thesis "Über die Komplexität der Multiplikation in
// eingeschränkten Branchingprogrammmodellen" by Woelfel, is:
//
// h32(x32, y32) = (h64(x32, y32) * rand_odd64 + rand16 * 2^16) % 2^64 / 2^32
//
// Contact danakj@chromium.org for any questions.
size_t HashInts32Impl(uint32_t value1, uint32_t value2) {
uint64_t value1_64 = value1;
uint64_t hash64 = (value1_64 << 32) | value2;
if (sizeof(size_t) >= sizeof(uint64_t))
return static_cast<size_t>(hash64);
uint64_t odd_random = 481046412LL << 32 | 1025306955LL;
uint32_t shift_random = 10121U << 16;
hash64 = hash64 * odd_random + shift_random;
size_t high_bits =
static_cast<size_t>(hash64 >> (8 * (sizeof(uint64_t) - sizeof(size_t))));
return high_bits;
}
// Implement hashing for pairs of up-to 64-bit integer values.
// We use the compound integer hash method to produce a 64-bit hash code, by
// breaking the two 64-bit inputs into 4 32-bit values:
// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
// Then we reduce our result to 32 bits if required, similar to above.
size_t HashInts64Impl(uint64_t value1, uint64_t value2) {
uint32_t short_random1 = 842304669U;
uint32_t short_random2 = 619063811U;
uint32_t short_random3 = 937041849U;
uint32_t short_random4 = 3309708029U;
uint32_t value1a = static_cast<uint32_t>(value1 & 0xffffffff);
uint32_t value1b = static_cast<uint32_t>((value1 >> 32) & 0xffffffff);
uint32_t value2a = static_cast<uint32_t>(value2 & 0xffffffff);
uint32_t value2b = static_cast<uint32_t>((value2 >> 32) & 0xffffffff);
uint64_t product1 = static_cast<uint64_t>(value1a) * short_random1;
uint64_t product2 = static_cast<uint64_t>(value1b) * short_random2;
uint64_t product3 = static_cast<uint64_t>(value2a) * short_random3;
uint64_t product4 = static_cast<uint64_t>(value2b) * short_random4;
uint64_t hash64 = product1 + product2 + product3 + product4;
if (sizeof(size_t) >= sizeof(uint64_t))
return static_cast<size_t>(hash64);
uint64_t odd_random = 1578233944LL << 32 | 194370989LL;
uint32_t shift_random = 20591U << 16;
hash64 = hash64 * odd_random + shift_random;
size_t high_bits =
static_cast<size_t>(hash64 >> (8 * (sizeof(uint64_t) - sizeof(size_t))));
return high_bits;
}
// The random seed is used to perturb the output of base::FastHash() and
// base::HashInts() so that it is only deterministic within the lifetime of a
// process. This prevents inadvertent dependencies on the underlying
// implementation, e.g. anything that persists the hash value and expects it to
// be unchanging will break.
//
// Note: this is the same trick absl uses to generate a random seed. This is
// more robust than using base::RandBytes(), which can fail inside a sandboxed
// environment. Note that without ASLR, the seed won't be quite as random...
#if DCHECK_IS_ON()
constexpr const void* kSeed = &kSeed;
#endif
template <typename T>
T Scramble(T input) {
#if DCHECK_IS_ON()
return HashInts64Impl(input, reinterpret_cast<uintptr_t>(kSeed));
#else
return input;
#endif
}
} // namespace
size_t FastHash(base::span<const uint8_t> data) {
return Scramble(FastHashImpl(data));
}
uint32_t Hash(const void* data, size_t length) {
// Currently our in-memory hash is the same as the persistent hash. The
// split between in-memory and persistent hash functions is maintained to
// allow the in-memory hash function to be updated in the future.
return PersistentHash(data, length);
}
uint32_t Hash(const std::string& str) {
return PersistentHash(as_bytes(make_span(str)));
}
uint32_t Hash(const string16& str) {
return PersistentHash(as_bytes(make_span(str)));
}
uint32_t PersistentHash(span<const uint8_t> data) {
// This hash function must not change, since it is designed to be persistable
// to disk.
if (data.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
NOTREACHED();
return 0;
}
return ::SuperFastHash(reinterpret_cast<const char*>(data.data()),
static_cast<int>(data.size()));
}
uint32_t PersistentHash(const void* data, size_t length) {
return PersistentHash(make_span(static_cast<const uint8_t*>(data), length));
}
uint32_t PersistentHash(const std::string& str) {
return PersistentHash(str.data(), str.size());
}
size_t HashInts32(uint32_t value1, uint32_t value2) {
return Scramble(HashInts32Impl(value1, value2));
}
// Implement hashing for pairs of up-to 64-bit integer values.
// We use the compound integer hash method to produce a 64-bit hash code, by
// breaking the two 64-bit inputs into 4 32-bit values:
// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
// Then we reduce our result to 32 bits if required, similar to above.
size_t HashInts64(uint64_t value1, uint64_t value2) {
return Scramble(HashInts64Impl(value1, value2));
}
} // namespace base

View file

@ -0,0 +1,86 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_HASH_HASH_H_
#define BASE_HASH_HASH_H_
#include <stddef.h>
#include <stdint.h>
#include <limits>
#include <string>
#include <utility>
#include "base/base_export.h"
#include "base/containers/span.h"
#include "base/logging.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
namespace base {
// WARNING: This hash functions should not be used for any cryptographic
// purpose.
// Deprecated: Computes a hash of a memory buffer, use FastHash() instead.
// If you need to persist a change on disk or between computers, use
// PersistentHash().
// TODO(https://crbug.com/1025358): Migrate client code to new hash function.
BASE_EXPORT uint32_t Hash(const void* data, size_t length);
BASE_EXPORT uint32_t Hash(const std::string& str);
BASE_EXPORT uint32_t Hash(const string16& str);
// Really *fast* and high quality hash.
// Recommended hash function for general use, we pick the best performant
// hash for each build target.
// It is prone to be updated whenever a newer/faster hash function is
// publicly available.
// May changed without warning, do not expect stability of outputs.
BASE_EXPORT size_t FastHash(base::span<const uint8_t> data);
inline size_t FastHash(StringPiece str) {
return FastHash(as_bytes(make_span(str)));
}
// Computes a hash of a memory buffer. This hash function must not change so
// that code can use the hashed values for persistent storage purposes or
// sending across the network. If a new persistent hash function is desired, a
// new version will have to be added in addition.
//
// WARNING: This hash function should not be used for any cryptographic purpose.
BASE_EXPORT uint32_t PersistentHash(base::span<const uint8_t> data);
BASE_EXPORT uint32_t PersistentHash(const void* data, size_t length);
BASE_EXPORT uint32_t PersistentHash(const std::string& str);
// Hash pairs of 32-bit or 64-bit numbers.
BASE_EXPORT size_t HashInts32(uint32_t value1, uint32_t value2);
BASE_EXPORT size_t HashInts64(uint64_t value1, uint64_t value2);
template <typename T1, typename T2>
inline size_t HashInts(T1 value1, T2 value2) {
// This condition is expected to be compile-time evaluated and optimised away
// in release builds.
if (sizeof(T1) > sizeof(uint32_t) || (sizeof(T2) > sizeof(uint32_t)))
return HashInts64(value1, value2);
return HashInts32(static_cast<uint32_t>(value1),
static_cast<uint32_t>(value2));
}
// A templated hasher for pairs of integer types. Example:
//
// using MyPair = std::pair<int32_t, int32_t>;
// std::unordered_set<MyPair, base::IntPairHash<MyPair>> set;
template <typename T>
struct IntPairHash;
template <typename Type1, typename Type2>
struct IntPairHash<std::pair<Type1, Type2>> {
size_t operator()(std::pair<Type1, Type2> value) const {
return HashInts(value.first, value.second);
}
};
} // namespace base
#endif // BASE_HASH_HASH_H_

View file

@ -0,0 +1,23 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/hash/legacy_hash.h"
#include "base/third_party/cityhash_v103/src/city_v103.h"
namespace base {
namespace legacy {
uint64_t CityHash64(base::span<const uint8_t> data) {
return internal::cityhash_v103::CityHash64(
reinterpret_cast<const char*>(data.data()), data.size());
}
uint64_t CityHash64WithSeed(base::span<const uint8_t> data, uint64_t seed) {
return internal::cityhash_v103::CityHash64WithSeed(
reinterpret_cast<const char*>(data.data()), data.size(), seed);
}
} // namespace legacy
} // namespace base

View file

@ -0,0 +1,25 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_HASH_LEGACY_HASH_H_
#define BASE_HASH_LEGACY_HASH_H_
#include <stdint.h>
#include "base/base_export.h"
#include "base/containers/span.h"
namespace base {
namespace legacy {
// Implementation is fixed at CityHash v1.0.3.
// Unchanging forever: yes
BASE_EXPORT uint64_t CityHash64(base::span<const uint8_t> data);
BASE_EXPORT uint64_t CityHash64WithSeed(base::span<const uint8_t> data,
uint64_t seed);
} // namespace legacy
} // namespace base
#endif // BASE_HASH_LEGACY_HASH_H_

View file

@ -0,0 +1,69 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_HASH_MD5_H_
#define BASE_HASH_MD5_H_
#include <string>
#include "base/base_export.h"
#include "base/strings/string_piece.h"
#include "build/build_config.h"
#if defined(OS_NACL)
#include "base/hash/md5_nacl.h"
#else
#include "base/hash/md5_boringssl.h"
#endif
// MD5 stands for Message Digest algorithm 5.
// MD5 is a robust hash function, designed for cyptography, but often used
// for file checksums. The code is complex and slow, but has few
// collisions.
// See Also:
// http://en.wikipedia.org/wiki/MD5
// These functions perform MD5 operations. The simplest call is MD5Sum() to
// generate the MD5 sum of the given data.
//
// You can also compute the MD5 sum of data incrementally by making multiple
// calls to MD5Update():
// MD5Context ctx; // intermediate MD5 data: do not use
// MD5Init(&ctx);
// MD5Update(&ctx, data1, length1);
// MD5Update(&ctx, data2, length2);
// ...
//
// MD5Digest digest; // the result of the computation
// MD5Final(&digest, &ctx);
//
// You can call MD5DigestToBase16() to generate a string of the digest.
namespace base {
// Initializes the given MD5 context structure for subsequent calls to
// MD5Update().
BASE_EXPORT void MD5Init(MD5Context* context);
// For the given buffer of |data| as a StringPiece, updates the given MD5
// context with the sum of the data. You can call this any number of times
// during the computation, except that MD5Init() must have been called first.
BASE_EXPORT void MD5Update(MD5Context* context, const StringPiece& data);
// Finalizes the MD5 operation and fills the buffer with the digest.
BASE_EXPORT void MD5Final(MD5Digest* digest, MD5Context* context);
// Converts a digest into human-readable hexadecimal.
BASE_EXPORT std::string MD5DigestToBase16(const MD5Digest& digest);
// Computes the MD5 sum of the given data buffer with the given length.
// The given 'digest' structure will be filled with the result data.
BASE_EXPORT void MD5Sum(const void* data, size_t length, MD5Digest* digest);
// Returns the MD5 (in hexadecimal) of a string.
BASE_EXPORT std::string MD5String(const StringPiece& str);
} // namespace base
#endif // BASE_HASH_MD5_H_

View file

@ -0,0 +1,37 @@
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/hash/md5.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
namespace base {
void MD5Init(MD5Context* context) {
MD5_Init(context);
}
void MD5Update(MD5Context* context, const StringPiece& data) {
MD5_Update(context, reinterpret_cast<const uint8_t*>(data.data()),
data.size());
}
void MD5Final(MD5Digest* digest, MD5Context* context) {
MD5_Final(digest->a, context);
}
std::string MD5DigestToBase16(const MD5Digest& digest) {
return ToLowerASCII(HexEncode(digest.a, MD5_DIGEST_LENGTH));
}
void MD5Sum(const void* data, size_t length, MD5Digest* digest) {
MD5(reinterpret_cast<const uint8_t*>(data), length, digest->a);
}
std::string MD5String(const StringPiece& str) {
MD5Digest digest;
MD5Sum(str.data(), str.size(), &digest);
return MD5DigestToBase16(digest);
}
} // namespace base

View file

@ -0,0 +1,25 @@
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_HASH_MD5_BORINGSSL_H_
#define BASE_HASH_MD5_BORINGSSL_H_
#include <stdint.h>
#include "third_party/boringssl/src/include/openssl/md5.h"
namespace base {
// The output of an MD5 operation.
struct MD5Digest {
uint8_t a[MD5_DIGEST_LENGTH];
};
// Used for storing intermediate data during an MD5 computation. Callers
// should not access the data.
typedef MD5_CTX MD5Context;
} // namespace base
#endif // BASE_HASH_MD5_BORINGSSL_H_

View file

@ -0,0 +1,44 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_HASH_MD5_CONSTEXPR_H_
#define BASE_HASH_MD5_CONSTEXPR_H_
#include "base/hash/md5.h"
#include "base/hash/md5_constexpr_internal.h"
namespace base {
// An constexpr implementation of the MD5 hash function. This is no longer
// considered cryptographically secure, but it is useful as a string hashing
// primitive.
//
// This is not the most efficient implementation, so it is not intended to be
// used at runtime. If you do attempt to use it at runtime you will see
// errors about missing symbols.
// Calculates the MD5 digest of the provided data. When passing |string| with
// no explicit length the terminating null will not be processed.
constexpr MD5Digest MD5SumConstexpr(const char* string);
constexpr MD5Digest MD5SumConstexpr(const char* data, uint32_t length);
// Calculates the first 32/64 bits of the MD5 digest of the provided data,
// returned as a uint32_t/uint64_t. When passing |string| with no explicit
// length the terminating null will not be processed. This abstracts away
// endianness so that the integer will read as the first 4 or 8 bytes of the
// MD5 sum, ensuring that the following outputs are equivalent for
// convenience:
//
// printf("%08x\n", MD5HashConstexpr32("foo"));
//
// MD5Digest d = MD5SumConstexpr("foo");
// printf("%02x%02x%02x%02x\n", d.a[0], d.a[1], d.a[2], d.a[3]);
constexpr uint64_t MD5Hash64Constexpr(const char* string);
constexpr uint64_t MD5Hash64Constexpr(const char* data, uint32_t length);
constexpr uint32_t MD5Hash32Constexpr(const char* string);
constexpr uint32_t MD5Hash32Constexpr(const char* data, uint32_t length);
} // namespace base
#endif // BASE_HASH_MD5_CONSTEXPR_H_

View file

@ -0,0 +1,326 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_HASH_MD5_CONSTEXPR_INTERNAL_H_
#define BASE_HASH_MD5_CONSTEXPR_INTERNAL_H_
#include <array>
#include <cstddef>
#include <cstdint>
#include "base/hash/md5.h"
#include "base/logging.h"
namespace base {
namespace internal {
// The implementation here is based on the pseudocode provided by Wikipedia:
// https://en.wikipedia.org/wiki/MD5#Pseudocode
struct MD5CE {
//////////////////////////////////////////////////////////////////////////////
// DATA STRUCTURES
// The data representation at each round is a 4-tuple of uint32_t.
struct IntermediateData {
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
};
// The input data for a single round consists of 16 uint32_t (64 bytes).
using RoundData = std::array<uint32_t, 16>;
//////////////////////////////////////////////////////////////////////////////
// CONSTANTS
static constexpr std::array<uint32_t, 64> kConstants = {
{0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a,
0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340,
0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8,
0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa,
0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92,
0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391}};
static constexpr std::array<uint32_t, 16> kShifts = {
{7, 12, 17, 22, 5, 9, 14, 20, 4, 11, 16, 23, 6, 10, 15, 21}};
// The initial intermediate data.
static constexpr IntermediateData kInitialIntermediateData{
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476};
//////////////////////////////////////////////////////////////////////////////
// PADDED MESSAGE GENERATION / EXTRACTION
// Given the message length, calculates the padded message length. There has
// to be room for the 1-byte end-of-message marker, plus 8 bytes for the
// uint64_t encoded message length, all rounded up to a multiple of 64 bytes.
static constexpr uint32_t GetPaddedMessageLength(const uint32_t n) {
return (((n + 1 + 8) + 63) / 64) * 64;
}
// Extracts the |i|th byte of a uint64_t, where |i == 0| extracts the least
// significant byte. It is expected that 0 <= i < 8.
static constexpr uint8_t ExtractByte(const uint64_t value, const uint32_t i) {
DCHECK(i < 8);
return static_cast<uint8_t>((value >> (i * 8)) & 0xff);
}
// Extracts the |i|th byte of a message of length |n|.
static constexpr uint8_t GetPaddedMessageByte(const char* data,
const uint32_t n,
const uint32_t m,
const uint32_t i) {
DCHECK(i < m);
DCHECK(n < m);
DCHECK(m % 64 == 0);
if (i < n) {
// Emit the message itself...
return data[i];
} else if (i == n) {
// ...followed by the end of message marker.
return 0x80;
} else if (i >= m - 8) {
// The last 8 bytes encode the original message length times 8.
return ExtractByte(n * 8, i - (m - 8));
} else {
// And everything else is just empyt padding.
return 0;
}
}
// Extracts the uint32_t starting at position |i| from the padded message
// generate by the provided input |data| of length |n|. The bytes are treated
// in little endian order.
static constexpr uint32_t GetPaddedMessageWord(const char* data,
const uint32_t n,
const uint32_t m,
const uint32_t i) {
DCHECK(i % 4 == 0);
DCHECK(i < m);
DCHECK(n < m);
DCHECK(m % 64 == 0);
return static_cast<uint32_t>(GetPaddedMessageByte(data, n, m, i)) |
static_cast<uint32_t>((GetPaddedMessageByte(data, n, m, i + 1))
<< 8) |
static_cast<uint32_t>((GetPaddedMessageByte(data, n, m, i + 2))
<< 16) |
static_cast<uint32_t>((GetPaddedMessageByte(data, n, m, i + 3))
<< 24);
}
// Given an input buffer of length |n| bytes, extracts one round worth of data
// starting at offset |i|.
static constexpr RoundData GetRoundData(const char* data,
const uint32_t n,
const uint32_t m,
const uint32_t i) {
DCHECK(i % 64 == 0);
DCHECK(i < m);
DCHECK(n < m);
DCHECK(m % 64 == 0);
return RoundData{{GetPaddedMessageWord(data, n, m, i),
GetPaddedMessageWord(data, n, m, i + 4),
GetPaddedMessageWord(data, n, m, i + 8),
GetPaddedMessageWord(data, n, m, i + 12),
GetPaddedMessageWord(data, n, m, i + 16),
GetPaddedMessageWord(data, n, m, i + 20),
GetPaddedMessageWord(data, n, m, i + 24),
GetPaddedMessageWord(data, n, m, i + 28),
GetPaddedMessageWord(data, n, m, i + 32),
GetPaddedMessageWord(data, n, m, i + 36),
GetPaddedMessageWord(data, n, m, i + 40),
GetPaddedMessageWord(data, n, m, i + 44),
GetPaddedMessageWord(data, n, m, i + 48),
GetPaddedMessageWord(data, n, m, i + 52),
GetPaddedMessageWord(data, n, m, i + 56),
GetPaddedMessageWord(data, n, m, i + 60)}};
}
//////////////////////////////////////////////////////////////////////////////
// HASH IMPLEMENTATION
// Mixes elements |b|, |c| and |d| at round |i| of the calculation.
static constexpr uint32_t CalcF(const uint32_t i,
const uint32_t b,
const uint32_t c,
const uint32_t d) {
DCHECK(i < 64);
if (i < 16) {
return d ^ (b & (c ^ d));
} else if (i < 32) {
return c ^ (d & (b ^ c));
} else if (i < 48) {
return b ^ c ^ d;
} else {
return c ^ (b | (~d));
}
}
static constexpr uint32_t CalcF(const uint32_t i,
const IntermediateData& intermediate) {
return CalcF(i, intermediate.b, intermediate.c, intermediate.d);
}
// Calculates the indexing function at round |i|.
static constexpr uint32_t CalcG(const uint32_t i) {
DCHECK(i < 64);
if (i < 16) {
return i;
} else if (i < 32) {
return (5 * i + 1) % 16;
} else if (i < 48) {
return (3 * i + 5) % 16;
} else {
return (7 * i) % 16;
}
}
// Calculates the rotation to be applied at round |i|.
static constexpr uint32_t GetShift(const uint32_t i) {
DCHECK(i < 64);
return kShifts[(i / 16) * 4 + (i % 4)];
}
// Rotates to the left the given |value| by the given |bits|.
static constexpr uint32_t LeftRotate(const uint32_t value,
const uint32_t bits) {
DCHECK(bits < 32);
return (value << bits) | (value >> (32 - bits));
}
// Applies the ith step of mixing.
static constexpr IntermediateData ApplyStep(
const uint32_t i,
const RoundData& data,
const IntermediateData& intermediate) {
DCHECK(i < 64);
const uint32_t g = CalcG(i);
DCHECK(g < 16);
const uint32_t f =
CalcF(i, intermediate) + intermediate.a + kConstants[i] + data[g];
const uint32_t s = GetShift(i);
return IntermediateData{/* a */ intermediate.d,
/* b */ intermediate.b + LeftRotate(f, s),
/* c */ intermediate.b,
/* d */ intermediate.c};
}
// Adds two IntermediateData together.
static constexpr IntermediateData Add(const IntermediateData& intermediate1,
const IntermediateData& intermediate2) {
return IntermediateData{
intermediate1.a + intermediate2.a, intermediate1.b + intermediate2.b,
intermediate1.c + intermediate2.c, intermediate1.d + intermediate2.d};
}
// Processes an entire message.
static constexpr IntermediateData ProcessMessage(const char* message,
const uint32_t n) {
const uint32_t m = GetPaddedMessageLength(n);
IntermediateData intermediate0 = kInitialIntermediateData;
for (uint32_t offset = 0; offset < m; offset += 64) {
RoundData data = GetRoundData(message, n, m, offset);
IntermediateData intermediate1 = intermediate0;
for (uint32_t i = 0; i < 64; ++i)
intermediate1 = ApplyStep(i, data, intermediate1);
intermediate0 = Add(intermediate0, intermediate1);
}
return intermediate0;
}
//////////////////////////////////////////////////////////////////////////////
// HELPER FUNCTIONS
// Converts an IntermediateData to a final digest.
static constexpr MD5Digest IntermediateDataToMD5Digest(
const IntermediateData& intermediate) {
return MD5Digest{{static_cast<uint8_t>((intermediate.a >> 0) & 0xff),
static_cast<uint8_t>((intermediate.a >> 8) & 0xff),
static_cast<uint8_t>((intermediate.a >> 16) & 0xff),
static_cast<uint8_t>((intermediate.a >> 24) & 0xff),
static_cast<uint8_t>((intermediate.b >> 0) & 0xff),
static_cast<uint8_t>((intermediate.b >> 8) & 0xff),
static_cast<uint8_t>((intermediate.b >> 16) & 0xff),
static_cast<uint8_t>((intermediate.b >> 24) & 0xff),
static_cast<uint8_t>((intermediate.c >> 0) & 0xff),
static_cast<uint8_t>((intermediate.c >> 8) & 0xff),
static_cast<uint8_t>((intermediate.c >> 16) & 0xff),
static_cast<uint8_t>((intermediate.c >> 24) & 0xff),
static_cast<uint8_t>((intermediate.d >> 0) & 0xff),
static_cast<uint8_t>((intermediate.d >> 8) & 0xff),
static_cast<uint8_t>((intermediate.d >> 16) & 0xff),
static_cast<uint8_t>((intermediate.d >> 24) & 0xff)}};
}
static constexpr uint32_t StringLength(const char* string) {
const char* end = string;
while (*end != 0)
++end;
// Double check that the precision losing conversion is safe.
DCHECK(end >= string);
DCHECK(static_cast<std::ptrdiff_t>(static_cast<uint32_t>(end - string)) ==
(end - string));
return static_cast<uint32_t>(end - string);
}
static constexpr uint32_t SwapEndian(uint32_t a) {
return ((a & 0xff) << 24) | (((a >> 8) & 0xff) << 16) |
(((a >> 16) & 0xff) << 8) | ((a >> 24) & 0xff);
}
//////////////////////////////////////////////////////////////////////////////
// WRAPPER FUNCTIONS
static constexpr MD5Digest Sum(const char* data, uint32_t n) {
return IntermediateDataToMD5Digest(ProcessMessage(data, n));
}
static constexpr uint64_t Hash64(const char* data, uint32_t n) {
IntermediateData intermediate = ProcessMessage(data, n);
return (static_cast<uint64_t>(SwapEndian(intermediate.a)) << 32) |
static_cast<uint64_t>(SwapEndian(intermediate.b));
}
static constexpr uint32_t Hash32(const char* data, uint32_t n) {
IntermediateData intermediate = ProcessMessage(data, n);
return SwapEndian(intermediate.a);
}
};
} // namespace internal
// Implementations of the functions exposed in the public header.
constexpr MD5Digest MD5SumConstexpr(const char* string) {
return internal::MD5CE::Sum(string, internal::MD5CE::StringLength(string));
}
constexpr MD5Digest MD5SumConstexpr(const char* string, uint32_t length) {
return internal::MD5CE::Sum(string, length);
}
constexpr uint64_t MD5Hash64Constexpr(const char* string) {
return internal::MD5CE::Hash64(string, internal::MD5CE::StringLength(string));
}
constexpr uint64_t MD5Hash64Constexpr(const char* string, uint32_t length) {
return internal::MD5CE::Hash64(string, length);
}
constexpr uint32_t MD5Hash32Constexpr(const char* string) {
return internal::MD5CE::Hash32(string, internal::MD5CE::StringLength(string));
}
constexpr uint32_t MD5Hash32Constexpr(const char* string, uint32_t length) {
return internal::MD5CE::Hash32(string, length);
}
} // namespace base
#endif // BASE_HASH_MD5_CONSTEXPR_INTERNAL_H_

View file

@ -0,0 +1,291 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// The original file was copied from sqlite, and was in the public domain.
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
#include <stddef.h>
#include "base/hash/md5.h"
namespace {
struct Context {
uint32_t buf[4];
uint32_t bits[2];
uint8_t in[64];
};
/*
* Note: this code is harmless on little-endian machines.
*/
void byteReverse(uint8_t* buf, unsigned longs) {
do {
uint32_t temp =
static_cast<uint32_t>(static_cast<unsigned>(buf[3]) << 8 | buf[2])
<< 16 |
(static_cast<unsigned>(buf[1]) << 8 | buf[0]);
*reinterpret_cast<uint32_t*>(buf) = temp;
buf += 4;
} while (--longs);
}
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
(w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x)
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void MD5Transform(uint32_t buf[4], const uint32_t in[16]) {
uint32_t a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
} // namespace
namespace base {
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void MD5Init(MD5Context* context) {
struct Context* ctx = reinterpret_cast<struct Context*>(context);
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void MD5Update(MD5Context* context, const StringPiece& data) {
struct Context* ctx = reinterpret_cast<struct Context*>(context);
const uint8_t* buf = reinterpret_cast<const uint8_t*>(data.data());
size_t len = data.size();
/* Update bitcount */
uint32_t t = ctx->bits[0];
if ((ctx->bits[0] = t + (static_cast<uint32_t>(len) << 3)) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += static_cast<uint32_t>(len >> 29);
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
uint8_t* p = static_cast<uint8_t*>(ctx->in + t);
t = 64 - t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in));
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in));
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void MD5Final(MD5Digest* digest, MD5Context* context) {
struct Context* ctx = reinterpret_cast<struct Context*>(context);
unsigned count;
uint8_t* p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in));
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
memcpy(&ctx->in[14 * sizeof(ctx->bits[0])], &ctx->bits[0],
sizeof(ctx->bits[0]));
memcpy(&ctx->in[15 * sizeof(ctx->bits[1])], &ctx->bits[1],
sizeof(ctx->bits[1]));
MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in));
byteReverse(reinterpret_cast<uint8_t*>(ctx->buf), 4);
memcpy(digest->a, ctx->buf, 16);
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
}
std::string MD5DigestToBase16(const MD5Digest& digest) {
static char const zEncode[] = "0123456789abcdef";
std::string ret;
ret.resize(32);
for (int i = 0, j = 0; i < 16; i++, j += 2) {
uint8_t a = digest.a[i];
ret[j] = zEncode[(a >> 4) & 0xf];
ret[j + 1] = zEncode[a & 0xf];
}
return ret;
}
void MD5Sum(const void* data, size_t length, MD5Digest* digest) {
MD5Context ctx;
MD5Init(&ctx);
MD5Update(&ctx, StringPiece(reinterpret_cast<const char*>(data), length));
MD5Final(digest, &ctx);
}
std::string MD5String(const StringPiece& str) {
MD5Digest digest;
MD5Sum(str.data(), str.length(), &digest);
return MD5DigestToBase16(digest);
}
} // namespace base

View file

@ -0,0 +1,23 @@
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_HASH_MD5_NACL_H_
#define BASE_HASH_MD5_NACL_H_
#include <stdint.h>
namespace base {
// The output of an MD5 operation.
struct MD5Digest {
uint8_t a[16];
};
// Used for storing intermediate data during an MD5 computation. Callers
// should not access the data.
typedef char MD5Context[88];
} // namespace base
#endif // BASE_HASH_MD5_NACL_H_

View file

@ -0,0 +1,211 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/hash/sha1.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "base/sys_byteorder.h"
namespace base {
// Implementation of SHA-1. Only handles data in byte-sized blocks,
// which simplifies the code a fair bit.
// Identifier names follow notation in FIPS PUB 180-3, where you'll
// also find a description of the algorithm:
// http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf
// Usage example:
//
// SecureHashAlgorithm sha;
// while(there is data to hash)
// sha.Update(moredata, size of data);
// sha.Final();
// memcpy(somewhere, sha.Digest(), 20);
//
// to reuse the instance of sha, call sha.Init();
class SecureHashAlgorithm {
public:
SecureHashAlgorithm() { Init(); }
static const int kDigestSizeBytes;
void Init();
void Update(const void* data, size_t nbytes);
void Final();
// 20 bytes of message digest.
const unsigned char* Digest() const {
return reinterpret_cast<const unsigned char*>(H);
}
private:
void Pad();
void Process();
uint32_t A, B, C, D, E;
uint32_t H[5];
union {
uint32_t W[80];
uint8_t M[64];
};
uint32_t cursor;
uint64_t l;
};
static inline uint32_t f(uint32_t t, uint32_t B, uint32_t C, uint32_t D) {
if (t < 20)
return (B & C) | ((~B) & D);
if (t < 40)
return B ^ C ^ D;
if (t < 60)
return (B & C) | (B & D) | (C & D);
return B ^ C ^ D;
}
static inline uint32_t S(uint32_t n, uint32_t X) {
return (X << n) | (X >> (32 - n));
}
static inline uint32_t K(uint32_t t) {
if (t < 20)
return 0x5a827999;
if (t < 40)
return 0x6ed9eba1;
if (t < 60)
return 0x8f1bbcdc;
return 0xca62c1d6;
}
const int SecureHashAlgorithm::kDigestSizeBytes = 20;
void SecureHashAlgorithm::Init() {
A = 0;
B = 0;
C = 0;
D = 0;
E = 0;
cursor = 0;
l = 0;
H[0] = 0x67452301;
H[1] = 0xefcdab89;
H[2] = 0x98badcfe;
H[3] = 0x10325476;
H[4] = 0xc3d2e1f0;
}
void SecureHashAlgorithm::Final() {
Pad();
Process();
for (auto& t : H)
t = ByteSwap(t);
}
void SecureHashAlgorithm::Update(const void* data, size_t nbytes) {
const uint8_t* d = reinterpret_cast<const uint8_t*>(data);
while (nbytes--) {
M[cursor++] = *d++;
if (cursor >= 64)
Process();
l += 8;
}
}
void SecureHashAlgorithm::Pad() {
M[cursor++] = 0x80;
if (cursor > 64 - 8) {
// pad out to next block
while (cursor < 64)
M[cursor++] = 0;
Process();
}
while (cursor < 64 - 8)
M[cursor++] = 0;
M[cursor++] = (l >> 56) & 0xff;
M[cursor++] = (l >> 48) & 0xff;
M[cursor++] = (l >> 40) & 0xff;
M[cursor++] = (l >> 32) & 0xff;
M[cursor++] = (l >> 24) & 0xff;
M[cursor++] = (l >> 16) & 0xff;
M[cursor++] = (l >> 8) & 0xff;
M[cursor++] = l & 0xff;
}
void SecureHashAlgorithm::Process() {
uint32_t t;
// Each a...e corresponds to a section in the FIPS 180-3 algorithm.
// a.
//
// W and M are in a union, so no need to memcpy.
// memcpy(W, M, sizeof(M));
for (t = 0; t < 16; ++t)
W[t] = ByteSwap(W[t]);
// b.
for (t = 16; t < 80; ++t)
W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
// c.
A = H[0];
B = H[1];
C = H[2];
D = H[3];
E = H[4];
// d.
for (t = 0; t < 80; ++t) {
uint32_t TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t);
E = D;
D = C;
C = S(30, B);
B = A;
A = TEMP;
}
// e.
H[0] += A;
H[1] += B;
H[2] += C;
H[3] += D;
H[4] += E;
cursor = 0;
}
SHA1Digest SHA1HashSpan(span<const uint8_t> data) {
SHA1Digest hash;
SHA1HashBytes(data.data(), data.size(), hash.data());
return hash;
}
std::string SHA1HashString(const std::string& str) {
char hash[SecureHashAlgorithm::kDigestSizeBytes];
SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()),
str.length(), reinterpret_cast<unsigned char*>(hash));
return std::string(hash, SecureHashAlgorithm::kDigestSizeBytes);
}
void SHA1HashBytes(const unsigned char* data, size_t len, unsigned char* hash) {
SecureHashAlgorithm sha;
sha.Update(data, len);
sha.Final();
memcpy(hash, sha.Digest(), SecureHashAlgorithm::kDigestSizeBytes);
}
} // namespace base

View file

@ -0,0 +1,40 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_HASH_SHA1_H_
#define BASE_HASH_SHA1_H_
#include <stddef.h>
#include <array>
#include <string>
#include "base/base_export.h"
#include "base/containers/span.h"
namespace base {
// These functions perform SHA-1 operations.
enum { kSHA1Length = 20 }; // Length in bytes of a SHA-1 hash.
// The output of a SHA-1 operation.
using SHA1Digest = std::array<uint8_t, kSHA1Length>;
// Computes the SHA-1 hash of the input |data| and returns the full hash.
BASE_EXPORT SHA1Digest SHA1HashSpan(span<const uint8_t> data);
// Computes the SHA-1 hash of the input string |str| and returns the full
// hash.
BASE_EXPORT std::string SHA1HashString(const std::string& str);
// Computes the SHA-1 hash of the |len| bytes in |data| and puts the hash
// in |hash|. |hash| must be kSHA1Length bytes long.
BASE_EXPORT void SHA1HashBytes(const unsigned char* data,
size_t len,
unsigned char* hash);
} // namespace base
#endif // BASE_HASH_SHA1_H_

View file

@ -0,0 +1,35 @@
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/hash/sha1.h"
#include <stdint.h>
#include "base/strings/string_util.h"
#include "third_party/boringssl/src/include/openssl/crypto.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
namespace base {
SHA1Digest SHA1HashSpan(span<const uint8_t> data) {
CRYPTO_library_init();
SHA1Digest digest;
SHA1(data.data(), data.size(), digest.data());
return digest;
}
std::string SHA1HashString(const std::string& str) {
CRYPTO_library_init();
std::string digest;
SHA1(reinterpret_cast<const uint8_t*>(str.data()), str.size(),
reinterpret_cast<uint8_t*>(WriteInto(&digest, kSHA1Length + 1)));
return digest;
}
void SHA1HashBytes(const unsigned char* data, size_t len, unsigned char* hash) {
CRYPTO_library_init();
SHA1(data, len, hash);
}
} // namespace base