auth 0.0.1
Authenticated computation with C++26 modules
Loading...
Searching...
No Matches
auth.ccm
Go to the documentation of this file.
1// SPDX-FileType: Source
2// SPDX-FileCopyrightText: 2026 Edward Kmett <ekmett@gmail.com>
3// SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0
4
8module;
9#include <array>
10#include <concepts>
11#include <compare>
12#include <cstdint>
13#include <exception>
14#include <span>
15#include <type_traits>
16#include <utility>
17#include <vector>
18
19export module auth;
20export import auth.error;
21import auth.hash;
23
24namespace auth {
25
27export struct prover {
32 template<class T>
33 class sealed {
34 T value;
35 digest hash{};
36
38 sealed(T value, digest hash) : value(std::move(value)), hash(hash) {}
39 friend struct prover;
40
41 public:
43 bool operator==(const sealed& other) const { return hash == other.hash; }
45 auto operator<=>(const sealed& other) const { return hash <=> other.hash; }
46
47 private:
48 friend struct auth::writer;
49 friend struct auth::reader;
50
52 template<class Stream>
53 void serialize(Stream& stream) const {
54 // Invariant: prover sealed values are only serialized with a writing stream.
55 stream(hash);
56 }
57 };
58
60
66 template<class T>
67 sealed<T> seal(T value) const {
68 auto hash = sha256(encode(value));
69 return {std::move(value), hash};
70 }
71
78 template<class T>
80 auto data = encode(p.value);
81 proof.insert(proof.end(), data.begin(), data.end());
82 return std::move(p.value);
83 }
84};
85
89export struct verifier {
93 template<class T>
94 class sealed {
95 digest hash{};
97 explicit sealed(digest hash) : hash(hash) {}
98 friend struct verifier;
99
100 public:
102 sealed() = default;
104 auto operator<=>(const sealed&) const = default;
105
106 private:
107 friend struct auth::writer;
108 friend struct auth::reader;
109
111 template<class Self, class Stream>
112 void serialize(this Self& self, Stream& stream) { stream(self.hash); }
113 };
114
118 explicit verifier(std::span<const std::uint8_t> proof)
119 : position(proof.data()), end(proof.subspan(proof.size()).data()) {}
120
121 verifier(bytes&&) = delete;
122
128 template<class T>
129 sealed<T> seal(T value) const {
130 return sealed<T>{sha256(encode(value))};
131 }
132
140 template<class T>
142 auto [value, next] = decode<T>({position, end});
143 if (sha256({position, next}) != p.hash) throw auth_error("sealed hash mismatch");
144 if constexpr (std::is_nothrow_move_constructible_v<T>) {
145 position = next;
146 return std::move(value);
147 } else {
148 // Return construction precedes local destruction; commit only on success.
149 struct advance_on_success {
150 const std::uint8_t*& position;
151 const std::uint8_t* next;
152 int exceptions = std::uncaught_exceptions();
153 ~advance_on_success() {
154 if (std::uncaught_exceptions() == exceptions) position = next;
155 }
156 } advance{position, next};
157 return std::move(value);
158 }
159 }
160
164 void finish() const {
165 if (position != end) throw auth_error("unused proof bytes");
166 }
167
168private:
169 const std::uint8_t* position;
170 const std::uint8_t* const end;
171};
172
183export template<class D>
184concept db = requires(D& database, std::uint32_t value,
185 typename std::remove_cvref_t<D>::template sealed<std::uint32_t> p) {
186 { database.seal(value) } ->
187 std::same_as<typename std::remove_cvref_t<D>::template sealed<std::uint32_t>>;
188 { database.unseal(std::move(p)) } -> std::same_as<std::uint32_t>;
189};
190
195export template<db DB, class T>
196using sealed = typename std::remove_cvref_t<DB>::template sealed<T>;
197
198} // namespace auth
typename std::remove_cvref_t< DB >::template sealed< T > sealed
Selects a database's associated sealed type.
Definition auth.ccm:196
A resident value and its digest; copyability follows T.
Definition auth.ccm:33
auto operator<=>(const sealed &other) const
Orders sealed values lexicographically by digest.
Definition auth.ccm:45
bool operator==(const sealed &other) const
Compares digests without comparing resident values.
Definition auth.ccm:43
A copyable digest commitment with no resident payload.
Definition auth.ccm:94
auto operator<=>(const sealed &) const =default
Compares and orders sealed values by digest.
sealed()=default
Initializes an all-zero digest, ready for deserialization.
A database with associated sealed types and seal/unseal operations. D is the database type,...
Definition auth.ccm:184
std::array< std::uint8_t, 32 > digest
The 32 bytes of a SHA-256 digest in hash output order.
Definition hash.ccm:20
digest sha256(std::span< const std::uint8_t > data)
Hashes exactly the supplied bytes with OpenSSL's SHA-256 implementation.
Definition hash.ccm:27
bytes encode(const T &value)
Serializes a value to an owned byte buffer.
std::vector< std::uint8_t > bytes
An owned buffer of serialized bytes.
std::pair< T, const std::uint8_t * > decode(std::span< const std::uint8_t > data)
Decodes one value, leaving subsequent bytes for the caller.
Reports malformed input, invalid proofs, or hashing failures.
Definition error.ccm:16
Records serialized openings in an owned proof buffer.
Definition auth.ccm:27
T unseal(sealed< T > p)
Appends an opening to the proof and returns its resident value.
Definition auth.ccm:79
bytes proof
Concatenated openings, without external framing.
Definition auth.ccm:59
sealed< T > seal(T value) const
Hashes a value and retains it in a sealed value without changing the proof.
Definition auth.ccm:67
Reads checked fields from borrowed bytes, advancing a byte offset.
verifier(bytes &&)=delete
Rejects a temporary owning buffer that would leave dangling pointers.
verifier(std::span< const std::uint8_t > proof)
Starts replay at the beginning of a borrowed proof.
Definition auth.ccm:118
sealed< T > seal(T value) const
Computes a digest-only sealed value without reading the proof.
Definition auth.ccm:129
void finish() const
Checks that replay consumed every proof byte.
Definition auth.ccm:164
T unseal(sealed< T > p)
Decodes the next value and checks the digest of exactly its consumed bytes.
Definition auth.ccm:141
Appends deterministic, byte-aligned fields to an owned buffer.