From edffafc7508f146a9a6d0433e9f875a9d412e839 Mon Sep 17 00:00:00 2001 From: mschoenebeck Date: Fri, 2 Jun 2023 03:09:08 -0500 Subject: [PATCH] added more serde methods for pvk --- include/groth16.hpp | 18 +++++--- src/fp.cpp | 92 +++++++++++++++++++-------------------- src/groth16.cpp | 104 ++++++++++++++++++++++++++++++++++++++++---- test/unittests.cpp | 5 +++ 4 files changed, 159 insertions(+), 60 deletions(-) diff --git a/include/groth16.hpp b/include/groth16.hpp index cd07ae7..ad57eaf 100644 --- a/include/groth16.hpp +++ b/include/groth16.hpp @@ -109,12 +109,18 @@ namespace groth16 const std::vector& ic ); PreparedVerifyingKey(const PreparedVerifyingKey& pvk); - static PreparedVerifyingKey fromBytesBE(const uint8_t* in, const bool check = false, const bool raw = false); - static PreparedVerifyingKey fromBytesLE(const uint8_t* in, const bool check = false, const bool raw = false); - void toBytesBE(uint8_t* out, const bool raw = false) const; - void toBytesLE(uint8_t* out, const bool raw = false) const; - std::vector toBytesBE(const bool raw = false) const; - std::vector toBytesLE(const bool raw = false) const; + static PreparedVerifyingKey fromJacobianBytesBE(const uint8_t* in, const bool check = false, const bool raw = false); + static PreparedVerifyingKey fromJacobianBytesLE(const uint8_t* in, const bool check = false, const bool raw = false); + static PreparedVerifyingKey fromAffineBytesBE(const uint8_t* in, const bool check = false, const bool raw = false); + static PreparedVerifyingKey fromAffineBytesLE(const uint8_t* in, const bool check = false, const bool raw = false); + void toJacobianBytesBE(uint8_t* out, const bool raw = false) const; + void toJacobianBytesLE(uint8_t* out, const bool raw = false) const; + void toAffineBytesBE(uint8_t* out, const bool raw = false) const; + void toAffineBytesLE(uint8_t* out, const bool raw = false) const; + std::vector toJacobianBytesBE(const bool raw = false) const; + std::vector toJacobianBytesLE(const bool raw = false) const; + std::vector toAffineBytesBE(const bool raw = false) const; + std::vector toAffineBytesLE(const bool raw = false) const; bool equal(const PreparedVerifyingKey& pvk) const; }; diff --git a/src/fp.cpp b/src/fp.cpp index a76b2ed..9e794e7 100644 --- a/src/fp.cpp +++ b/src/fp.cpp @@ -235,12 +235,12 @@ bool fp::isQuadraticNonResidue() const bool fp::isLexicographicallyLargest() const { array halfQ = { - 0x0D0088F51CBFF34D, - 0x258DD3DB21A5D66B, - 0xB23BA5C279C2895F, - 0xB39869507B587B12, - 0x0F55FFFF58A9FFFF, - 0xDCFF7FFFFFFFD556 + 0x0D00'88F5'1CBF'F34D, + 0x258D'D3DB'21A5'D66B, + 0xB23B'A5C2'79C2'895F, + 0xB398'6950'7B58'7B12, + 0x0F55'FFFF'58A9'FFFF, + 0xDCFF'7FFF'FFFF'D556 }; array yValue = fromMont().d; @@ -296,46 +296,46 @@ const fp fp::B = fp({ }); const fp fp::twoInv = fp({ - 0x1804000000015554, - 0x855000053ab00001, - 0x633cb57c253c276f, - 0x6e22d1ec31ebb502, - 0xd3916126f2d14ca2, - 0x17fbb8571a006596 + 0x1804'0000'0001'5554, + 0x8550'0005'3ab0'0001, + 0x633c'b57c'253c'276f, + 0x6e22'd1ec'31eb'b502, + 0xd391'6126'f2d1'4ca2, + 0x17fb'b857'1a00'6596 }); const array fp::Q = { - 0xffffffff00000001, - 0x53bda402fffe5bfe, - 0x3339d80809a1d805, - 0x73eda753299d7d48 + 0xffff'ffff'0000'0001, + 0x53bd'a402'fffe'5bfe, + 0x3339'd808'09a1'd805, + 0x73ed'a753'299d'7d48 }; const array fp::pPlus1Over4 = { - 0xee7fbfffffffeaab, - 0x07aaffffac54ffff, - 0xd9cc34a83dac3d89, - 0xd91dd2e13ce144af, - 0x92c6e9ed90d2eb35, - 0x0680447a8e5ff9a6 + 0xee7f'bfff'ffff'eaab, + 0x07aa'ffff'ac54'ffff, + 0xd9cc'34a8'3dac'3d89, + 0xd91d'd2e1'3ce1'44af, + 0x92c6'e9ed'90d2'eb35, + 0x0680'447a'8e5f'f9a6 }; const array fp::pMinus1Over2 = { - 0xdcff7fffffffd555, - 0x0f55ffff58a9ffff, - 0xb39869507b587b12, - 0xb23ba5c279c2895f, - 0x258dd3db21a5d66b, - 0x0d0088f51cbff34d + 0xdcff'7fff'ffff'd555, + 0x0f55'ffff'58a9'ffff, + 0xb398'6950'7b58'7b12, + 0xb23b'a5c2'79c2'895f, + 0x258d'd3db'21a5'd66b, + 0x0d00'88f5'1cbf'f34d }; const array fp::pMinus3Over4 = { - 0xee7fbfffffffeaaa, - 0x07aaffffac54ffff, - 0xd9cc34a83dac3d89, - 0xd91dd2e13ce144af, - 0x92c6e9ed90d2eb35, - 0x0680447a8e5ff9a6 + 0xee7f'bfff'ffff'eaaa, + 0x07aa'ffff'ac54'ffff, + 0xd9cc'34a8'3dac'3d89, + 0xd91d'd2e1'3ce1'44af, + 0x92c6'e9ed'90d2'eb35, + 0x0680'447a'8e5f'f9a6 }; fp2::fp2() : c0(fp()), c1(fp()) @@ -646,20 +646,20 @@ bool fp2::isLexicographicallyLargest() const const fp2 fp2::negativeOne2 = fp2({ fp({ - 0x43f5fffffffcaaae, - 0x32b7fff2ed47fffd, - 0x07e83a49a2e99d69, - 0xeca8f3318332bb7a, - 0xef148d1ea0f4c069, - 0x040ab3263eff0206 + 0x43f5'ffff'fffc'aaae, + 0x32b7'fff2'ed47'fffd, + 0x07e8'3a49'a2e9'9d69, + 0xeca8'f331'8332'bb7a, + 0xef14'8d1e'a0f4'c069, + 0x040a'b326'3eff'0206 }), fp({ - 0x0000000000000000, - 0x0000000000000000, - 0x0000000000000000, - 0x0000000000000000, - 0x0000000000000000, - 0x0000000000000000 + 0x0000'0000'0000'0000, + 0x0000'0000'0000'0000, + 0x0000'0000'0000'0000, + 0x0000'0000'0000'0000, + 0x0000'0000'0000'0000, + 0x0000'0000'0000'0000 }), }); diff --git a/src/groth16.cpp b/src/groth16.cpp index 0ecfbbc..803203e 100644 --- a/src/groth16.cpp +++ b/src/groth16.cpp @@ -485,7 +485,7 @@ PreparedVerifyingKey::PreparedVerifyingKey(const PreparedVerifyingKey& pvk) : { } -PreparedVerifyingKey PreparedVerifyingKey::fromBytesBE(const uint8_t* in, const bool check, const bool raw) +PreparedVerifyingKey PreparedVerifyingKey::fromJacobianBytesBE(const uint8_t* in, const bool check, const bool raw) { fp12 alpha_g1_beta_g2 = fp12::fromBytesBE(span(&in[ 0], &in[ 576]), check, raw); g2 neg_gamma_g2 = g2::fromJacobianBytesBE(span(&in[ 576], &in[ 864]), check, raw); @@ -505,7 +505,7 @@ PreparedVerifyingKey PreparedVerifyingKey::fromBytesBE(const uint8_t* in, const ); } -PreparedVerifyingKey PreparedVerifyingKey::fromBytesLE(const uint8_t* in, const bool check, const bool raw) +PreparedVerifyingKey PreparedVerifyingKey::fromJacobianBytesLE(const uint8_t* in, const bool check, const bool raw) { fp12 alpha_g1_beta_g2 = fp12::fromBytesLE(span(&in[ 0], &in[ 576]), check, raw); g2 neg_gamma_g2 = g2::fromJacobianBytesLE(span(&in[ 576], &in[ 864]), check, raw); @@ -525,7 +525,47 @@ PreparedVerifyingKey PreparedVerifyingKey::fromBytesLE(const uint8_t* in, const ); } -void PreparedVerifyingKey::toBytesBE(uint8_t* out, const bool raw) const +PreparedVerifyingKey PreparedVerifyingKey::fromAffineBytesBE(const uint8_t* in, const bool check, const bool raw) +{ + fp12 alpha_g1_beta_g2 = fp12::fromBytesBE(span(&in[ 0], &in[576]), check, raw); + g2 neg_gamma_g2 = g2::fromAffineBytesBE(span(&in[576], &in[768]), check, raw); + g2 neg_delta_g2 = g2::fromAffineBytesBE(span(&in[768], &in[960]), check, raw); + vector ic; + uint32_t n_ic = in[960] << 24 | in[961] << 16 | in[962] << 8 | in[963]; + ic.reserve(n_ic); + for(uint32_t i = 0; i < n_ic; i++) + { + ic.push_back(g1::fromAffineBytesBE(span(&in[964 + i*96], &in[964 + (i+1)*96]), check, raw)); + } + return PreparedVerifyingKey( + alpha_g1_beta_g2, + neg_gamma_g2, + neg_delta_g2, + ic + ); +} + +PreparedVerifyingKey PreparedVerifyingKey::fromAffineBytesLE(const uint8_t* in, const bool check, const bool raw) +{ + fp12 alpha_g1_beta_g2 = fp12::fromBytesLE(span(&in[ 0], &in[576]), check, raw); + g2 neg_gamma_g2 = g2::fromAffineBytesLE(span(&in[576], &in[768]), check, raw); + g2 neg_delta_g2 = g2::fromAffineBytesLE(span(&in[768], &in[960]), check, raw); + vector ic; + uint32_t n_ic = in[960] | in[961] << 8 | in[962] << 16 | in[963] << 24; + ic.reserve(n_ic); + for(uint32_t i = 0; i < n_ic; i++) + { + ic.push_back(g1::fromAffineBytesLE(span(&in[964 + i*96], &in[964 + (i+1)*96]), check, raw)); + } + return PreparedVerifyingKey( + alpha_g1_beta_g2, + neg_gamma_g2, + neg_delta_g2, + ic + ); +} + +void PreparedVerifyingKey::toJacobianBytesBE(uint8_t* out, const bool raw) const { memcpy(&out[ 0], &alpha_g1_beta_g2.toBytesBE(raw)[0], 576); memcpy(&out[ 576], &neg_gamma_g2.toJacobianBytesBE(raw)[0], 288); @@ -541,7 +581,7 @@ void PreparedVerifyingKey::toBytesBE(uint8_t* out, const bool raw) const } } -void PreparedVerifyingKey::toBytesLE(uint8_t* out, const bool raw) const +void PreparedVerifyingKey::toJacobianBytesLE(uint8_t* out, const bool raw) const { memcpy(&out[ 0], &alpha_g1_beta_g2.toBytesLE(raw)[0], 576); memcpy(&out[ 576], &neg_gamma_g2.toJacobianBytesLE(raw)[0], 288); @@ -557,19 +597,67 @@ void PreparedVerifyingKey::toBytesLE(uint8_t* out, const bool raw) const } } -std::vector PreparedVerifyingKey::toBytesBE(const bool raw) const +void PreparedVerifyingKey::toAffineBytesBE(uint8_t* out, const bool raw) const +{ + memcpy(&out[ 0], &alpha_g1_beta_g2.toBytesBE(raw)[0], 576); + memcpy(&out[576], &neg_gamma_g2.toAffineBytesBE(raw)[0], 192); + memcpy(&out[768], &neg_delta_g2.toAffineBytesBE(raw)[0], 192); + uint32_t n_ic = ic.size(); + out[960] = n_ic >> 24; + out[961] = n_ic >> 16; + out[962] = n_ic >> 8; + out[963] = n_ic; + for(uint32_t i = 0; i < n_ic; i++) + { + memcpy(&out[964 + i*96], &ic[i].toAffineBytesBE(raw)[0], 96); + } +} + +void PreparedVerifyingKey::toAffineBytesLE(uint8_t* out, const bool raw) const +{ + memcpy(&out[ 0], &alpha_g1_beta_g2.toBytesLE(raw)[0], 576); + memcpy(&out[576], &neg_gamma_g2.toAffineBytesLE(raw)[0], 192); + memcpy(&out[768], &neg_delta_g2.toAffineBytesLE(raw)[0], 192); + uint32_t n_ic = ic.size(); + out[960] = n_ic; + out[961] = n_ic >> 8; + out[962] = n_ic >> 16; + out[963] = n_ic >> 24; + for(uint32_t i = 0; i < n_ic; i++) + { + memcpy(&out[964 + i*96], &ic[i].toAffineBytesLE(raw)[0], 96); + } +} + +std::vector PreparedVerifyingKey::toJacobianBytesBE(const bool raw) const { vector out; out.resize(1152 + 4 + ic.size()*144); - toBytesBE(out.data(), raw); + toJacobianBytesBE(out.data(), raw); return out; } -std::vector PreparedVerifyingKey::toBytesLE(const bool raw) const +std::vector PreparedVerifyingKey::toJacobianBytesLE(const bool raw) const { vector out; out.resize(1152 + 4 + ic.size()*144); - toBytesLE(out.data(), raw); + toJacobianBytesLE(out.data(), raw); + return out; +} + +std::vector PreparedVerifyingKey::toAffineBytesBE(const bool raw) const +{ + vector out; + out.resize(960 + 4 + ic.size()*96); + toAffineBytesBE(out.data(), raw); + return out; +} + +std::vector PreparedVerifyingKey::toAffineBytesLE(const bool raw) const +{ + vector out; + out.resize(960 + 4 + ic.size()*96); + toAffineBytesLE(out.data(), raw); return out; } diff --git a/test/unittests.cpp b/test/unittests.cpp index 76a0dae..9c282d0 100644 --- a/test/unittests.cpp +++ b/test/unittests.cpp @@ -1709,6 +1709,11 @@ void TestGroth16() if(!groth16::VerifyingKey::fromCompressedBytesBE(vk.toCompressedBytesBE().data()).equal(vk)) throw invalid_argument("Groth16, vk: CompressedBytesBE error"); groth16::PreparedVerifyingKey pvk = groth16::prepare_verifying_key(vk); + if(!groth16::PreparedVerifyingKey::fromJacobianBytesBE(pvk.toJacobianBytesBE().data()).equal(pvk)) throw invalid_argument("Groth16, pvk: JacobianBytesBE error"); + if(!groth16::PreparedVerifyingKey::fromJacobianBytesLE(pvk.toJacobianBytesLE().data()).equal(pvk)) throw invalid_argument("Groth16, pvk: JacobianBytesLE error"); + if(!groth16::PreparedVerifyingKey::fromAffineBytesBE(pvk.toAffineBytesBE().data()).equal(pvk)) throw invalid_argument("Groth16, pvk: AffineBytesBE error"); + if(!groth16::PreparedVerifyingKey::fromAffineBytesLE(pvk.toAffineBytesLE().data()).equal(pvk)) throw invalid_argument("Groth16, pvk: AffineBytesLE error"); + vector> public_inputs = {scalar::fromBytesLE<4>(hexToBytes("2912224b7353476a255f2aeeb0c57b39d5a8e721225bba6620cc2b2011c42245"))}; if(!groth16::verify_proof(pvk, proof, public_inputs)) throw invalid_argument("Groth16: proof invalid"); }