52class FlatSHA256Circuit {
54 using v8 =
typename Logic::v8;
55 using v256 =
typename Logic::v256;
56 using v32 =
typename Logic::v32;
57 using EltW =
typename Logic::EltW;
58 using Field =
typename Logic::Field;
59 using packed_v32 =
typename BitPlucker::packed_v32;
72 for (
size_t i = 0; i < r.size(); ++i) {
79 for (
size_t k = 0; k < 48; ++k) {
80 outw[k] = packed_input(Q);
82 for (
size_t k = 0; k < 64; ++k) {
83 oute[k] = packed_input(Q);
84 outa[k] = packed_input(Q);
86 for (
size_t k = 0; k < 8; ++k) {
87 h1[k] = packed_input(Q);
92 explicit FlatSHA256Circuit(
const Logic& l) : l_(l), bp_(l_) {}
96 for (
size_t i = 0; i < r.size(); ++i) {
102 void assert_transform_block(
const v32 in[16],
const v32 H0[8],
103 const v32 outw[48],
const v32 oute[64],
104 const v32 outa[64],
const v32 H1[8])
const {
106 BitAdder<Logic, 32> BA(L);
108 std::vector<v32> w(64);
109 for (
size_t i = 0; i < 16; ++i) {
113 for (
size_t i = 16; i < 64; ++i) {
114 auto sw2 = sigma1(w[i - 2]);
115 auto sw15 = sigma0(w[i - 15]);
116 std::vector<v32> terms = {sw2, w[i - 7], sw15, w[i - 16]};
118 BA.assert_eqmod(w[i], BA.add(terms), 4);
130 for (
size_t t = 0; t < 64; ++t) {
131 auto s1e = Sigma1(e);
132 auto ch = L.vCh(&e, &f, g);
133 auto rt = L.vbit32(kSha256Round[t]);
134 std::vector<v32> t1_terms = {h, s1e, ch, rt, w[t]};
135 EltW t1 = BA.add(t1_terms);
136 EltW sigma0 = BA.as_field_element(Sigma0(a));
137 EltW vmaj = BA.as_field_element(L.vMaj(&a, &b, c));
138 EltW t2 = BA.add(&sigma0, vmaj);
144 EltW ed = BA.as_field_element(d);
145 BA.assert_eqmod(e, BA.add(&t1, ed), 6);
150 BA.assert_eqmod(a, BA.add(&t1, t2), 7);
153 BA.assert_eqmod(H1[0], BA.add(H0[0], a), 2);
154 BA.assert_eqmod(H1[1], BA.add(H0[1], b), 2);
155 BA.assert_eqmod(H1[2], BA.add(H0[2], c), 2);
156 BA.assert_eqmod(H1[3], BA.add(H0[3], d), 2);
157 BA.assert_eqmod(H1[4], BA.add(H0[4], e), 2);
158 BA.assert_eqmod(H1[5], BA.add(H0[5], f), 2);
159 BA.assert_eqmod(H1[6], BA.add(H0[6], g), 2);
160 BA.assert_eqmod(H1[7], BA.add(H0[7], h), 2);
165 void assert_transform_block(
const v32 in[16],
const v32 H0[8],
166 const packed_v32 poutw[48],
167 const packed_v32 poute[64],
168 const packed_v32 pouta[64],
169 const packed_v32 pH1[8])
const {
170 std::vector<v32> H1(8);
171 std::vector<v32> outw(48);
172 std::vector<v32> oute(64), outa(64);
173 for (
size_t i = 0; i < 8; ++i) {
174 H1[i] = bp_.unpack_v32(pH1[i]);
176 for (
size_t i = 0; i < 48; ++i) {
177 outw[i] = bp_.unpack_v32(poutw[i]);
179 for (
size_t i = 0; i < 64; ++i) {
180 oute[i] = bp_.unpack_v32(poute[i]);
181 outa[i] = bp_.unpack_v32(pouta[i]);
183 assert_transform_block(in, H0, outw.data(), oute.data(), outa.data(),
188 void assert_transform_block(
const v32 in[16],
const packed_v32 pH0[8],
189 const packed_v32 poutw[48],
190 const packed_v32 poute[64],
191 const packed_v32 pouta[64],
192 const packed_v32 pH1[8])
const {
193 std::vector<v32> H0(8);
194 for (
size_t i = 0; i < 8; ++i) {
195 H0[i] = bp_.unpack_v32(pH0[i]);
197 assert_transform_block(in, H0.data(), poutw, poute, pouta, pH1);
203 void assert_message(
size_t max,
const v8& nb,
const v8 in[],
206 const packed_v32* H =
nullptr;
207 std::vector<v32> tmp(16);
209 for (
size_t b = 0; b < max; ++b) {
210 const v8* inb = &in[64 * b];
211 for (
size_t i = 0; i < 16; ++i) {
215 tmp[i] = L.vappend(L.vappend(inb[4 * i + 3], inb[4 * i + 2]),
216 L.vappend(inb[4 * i + 1], inb[4 * i + 0]));
221 assert_transform_block(tmp.data(), H0, bw[b].outw, bw[b].oute,
222 bw[b].outa, bw[b].h1);
224 assert_transform_block(tmp.data(), H, bw[b].outw, bw[b].oute,
225 bw[b].outa, bw[b].h1);
234 void assert_message_with_prefix(
size_t max,
const v8& nb,
236 const uint8_t prefix[],
size_t len,
239 std::vector<v32> tmp(16);
241 std::vector<v8> bbuf(64 * max);
242 for (
size_t i = 0; i < len; ++i) {
243 L.bits(8, bbuf[i].data(), prefix[i]);
245 for (
size_t i = 0; i + len < 64 * max; ++i) {
246 bbuf[i + len] = in[i];
249 assert_message(max, nb, bbuf.data(), bw);
256 void assert_message_hash(
size_t max,
const v8& nb,
const v8 in[],
259 assert_message(max, nb, in, bw);
260 assert_hash(max, target, nb, bw);
269 void assert_message_hash_with_prefix(
size_t max,
const v8& nb,
271 const uint8_t prefix[],
272 size_t len,
const v256& target,
274 assert_message_with_prefix(max, nb, in, prefix, len, bw);
275 assert_hash(max, target, nb, bw);
282 void assert_hash(
size_t max,
const v256& e,
const v8& nb,
285 for (
size_t b = 0; b < max; ++b) {
286 auto bt = l_.veq(nb, b + 1);
287 auto ebt = l_.eval(bt);
288 for (
size_t i = 0; i < 8; ++i) {
289 for (
size_t k = 0; k < bp_.kNv32Elts; ++k) {
291 x[i][k] = l_.mul(&ebt, bw[b].h1[i][k]);
293 auto maybe_sha = l_.mul(&ebt, bw[b].h1[i][k]);
294 x[i][k] = l_.add(&x[i][k], maybe_sha);
302 for (
size_t j = 0; j < 8; ++j) {
303 auto hj = bp_.unpack_v32(x[j]);
304 for (
size_t k = 0; k < 32; ++k) {
305 mm[((7 - j) * 32 + k)] = hj[k];
308 l_.vassert_eq(&mm, e);
312 void initial_context(v32 H[8])
const {
313 static const uint64_t initial[8] = {0x6a09e667u, 0xbb67ae85u, 0x3c6ef372u,
314 0xa54ff53au, 0x510e527fu, 0x9b05688cu,
315 0x1f83d9abu, 0x5be0cd19u};
316 for (
size_t i = 0; i < 8; i++) {
317 H[i] = l_.template vbit<32>(initial[i]);
321 v32 Sigma0(
const v32& x)
const {
322 auto x2 = l_.vrotr(x, 2);
323 auto x13 = l_.vrotr(x, 13);
324 return l_.vxor3(&x2, &x13, l_.vrotr(x, 22));
327 v32 Sigma1(
const v32& x)
const {
328 auto x6 = l_.vrotr(x, 6);
329 auto x11 = l_.vrotr(x, 11);
330 return l_.vxor3(&x6, &x11, l_.vrotr(x, 25));
333 v32 sigma0(
const v32& x)
const {
334 auto x7 = l_.vrotr(x, 7);
335 auto x18 = l_.vrotr(x, 18);
336 return l_.vxor3(&x7, &x18, l_.vshr(x, 3));
339 v32 sigma1(
const v32& x)
const {
340 auto x17 = l_.vrotr(x, 17);
341 auto x19 = l_.vrotr(x, 19);
342 return l_.vxor3(&x17, &x19, l_.vshr(x, 10));