Longfellow ZK 0290cb32

Loading...
Searching...
No Matches
random.h
1// Copyright 2025 Google LLC.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef PRIVACY_PROOFS_ZK_LIB_RANDOM_RANDOM_H_
16#define PRIVACY_PROOFS_ZK_LIB_RANDOM_RANDOM_H_
17
18#include <cstdint>
19#include <cstdlib>
20#include <optional>
21#include <utility>
22#include <vector>
23
24#include "util/panic.h"
25
26 namespace proofs {
27
28// Our protocols require random coins; this interface provides both prover
29// and verifier components with those coins. Re-implementing this interface
30// allows easily supporting the Fiat-Shamir transform, or for sampling using
31// a system provided RNG such as openssl.
32 class RandomEngine {
33 public:
34 virtual ~RandomEngine() = default;
35 virtual void bytes(uint8_t* buf, size_t n) = 0; // pure virtual
36
37 // Sample a random field element.
38 // TODO [matteof 2025-02-07] Per RFC, we must mask off the high
39 // bits, but this requires changes to the field interface.
40 // Punt for now since the mask is all ones anyway.
41 template <class Field>
42 typename Field::Elt elt(const Field& F) {
43 // Expected constant time.
44 uint8_t buf[Field::kBytes];
45 for (;;) {
46 bytes(buf, sizeof(buf));
47 if (std::optional<typename Field::Elt> maybe = F.of_bytes_field(buf)) {
48 return maybe.value();
49 }
50 }
51 }
52
53 template <class Field>
54 typename Field::Elt subfield_elt(const Field& F) {
55 // Expected constant time.
56 uint8_t buf[Field::kSubFieldBytes];
57 for (;;) {
58 bytes(buf, sizeof(buf));
59 if (std::optional<typename Field::Elt> maybe = F.of_bytes_subfield(buf)) {
60 return maybe.value();
61 }
62 }
63 }
64
65 // Convenience method to sample an array of random field elements.
66 template <class Field>
67 void elt(typename Field::Elt e[/*n*/], size_t n, const Field& F) {
68 for (size_t i = 0; i < n; ++i) e[i] = elt(F);
69 }
70
71 // the minimal bitmask such that (n & mask) == n
72 size_t mask(size_t n) {
73 size_t mask = 0;
74 while ((n & mask) != n) {
75 mask <<= 1;
76 mask |= 1u;
77 }
78 return mask;
79 }
80
81 // random size_t < n
82 size_t nat(size_t n) {
83 check(n > 0, "nat(0)");
84
85 // compute the minimum number of random bytes needed
86 size_t l = 0;
87 size_t nn = n;
88 while (nn != 0) {
89 nn >>= 8;
90 ++l;
91 }
92 check(l <= sizeof(size_t), "l <= sizeof(size_t)");
93
94 size_t msk = mask(n);
95 size_t r;
96 uint8_t buf[sizeof(size_t)];
97
98 // rejection sampling
99 do {
100 // consume L random bytes
101 bytes(buf, l);
102
103 // little-endian read
104 r = 0;
105 for (size_t i = l; i-- > 0;) {
106 r = (r << 8) | buf[i];
107 }
108
109 // mask off high bits
110 r &= msk;
111 } while (r >= n);
112
113 return r;
114 }
115
116 // Choose K distinct random naturals in [0..N).
117 // Textbook algorithm requiring O(N) space
118 void choose(size_t res[/*k*/], size_t n, size_t k) {
119 check(n >= k, "n >= k");
120
121 std::vector<size_t> A(n);
122 for (size_t i = 0; i < n; ++i) {
123 A[i] = i;
124 }
125 for (size_t i = 0; i < k; ++i) {
126 size_t j = i + nat(n - i);
127 std::swap(A[i], A[j]);
128 res[i] = A[i];
129 }
130 }
131};
132} // namespace proofs
133
134#endif // PRIVACY_PROOFS_ZK_LIB_RANDOM_RANDOM_H_
proofs::RandomEngine
Definition random.h:32
proofs::GF2_128::Elt
Definition gf2_128.h:63