forked from RobotLocomotion/drake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsha256.h
79 lines (64 loc) · 2.68 KB
/
sha256.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#pragma once
#include <array>
#include <cstdint>
#include <cstring>
#include <iosfwd>
#include <optional>
#include <string>
#include "drake/common/drake_copyable.h"
namespace drake {
/** Represents a SHA-256 cryptographic checksum.
See also https://en.wikipedia.org/wiki/SHA-2.
This class is not bound in pydrake, because Python programmers should prefer
using https://docs.python.org/3/library/hashlib.html instead. */
class Sha256 final {
public:
DRAKE_DEFAULT_COPY_AND_MOVE_AND_ASSIGN(Sha256);
/** Constructs an all-zero checksum.
Note that this is NOT the same as the checksum of empty (zero-sized) data. */
Sha256() { bytes_.fill(0); }
/** Computes the checksum of the given `data` buffer. */
static Sha256 Checksum(std::string_view data);
/** Computes the checksum of the given `stream`.
Does not check for istream errors; that is the responsibility of the caller.
@pre stream != nullptr. */
static Sha256 Checksum(std::istream* stream);
/** Parses the 64-character ASCII hex representation of a SHA-256 checksum.
Returns std::nullopt if the argument is an invalid checksum. */
static std::optional<Sha256> Parse(std::string_view sha256);
/** Returns the 64-character ASCII hex representation of this checksum. */
std::string to_string() const;
// Offer typical comparison operations.
bool operator==(const Sha256& other) const { return bytes_ == other.bytes_; }
bool operator!=(const Sha256& other) const { return bytes_ != other.bytes_; }
bool operator<(const Sha256& other) const { return bytes_ < other.bytes_; }
private:
friend class std::hash<Sha256>;
std::array<uint8_t, 32> bytes_;
};
} // namespace drake
namespace std {
/** The STL container hash for Sha256 objects. This implementation avoids using
drake::hash_append for performance. The checksum should already be well-mixed,
so we can just squash it down into the required size. */
template <>
struct hash<drake::Sha256> {
size_t operator()(const drake::Sha256& x) const noexcept {
constexpr int kInputSize = sizeof(x.bytes_);
constexpr int kWordSize = sizeof(size_t);
static_assert(kInputSize % kWordSize == 0);
constexpr int kNumSteps = kInputSize / kWordSize;
size_t result = 0;
for (int i = 0; i < kNumSteps; ++i) {
// A memcpy is the canonical tool to convert raw memory between different
// compile-time types -- compilers will always optimize it away in release
// builds. The whole operator() implementation compiles down to just four
// instructions (the xor'ing of four 64-bit words).
size_t temp;
std::memcpy(&temp, x.bytes_.data() + i * kWordSize, kWordSize);
result = result ^ temp;
}
return result;
}
};
} // namespace std