Skip to content
This repository was archived by the owner on Feb 17, 2025. It is now read-only.

Commit 2ac117d

Browse files
committed
Finished with marshalling of all supported curves #318
1 parent c5b1b99 commit 2ac117d

File tree

4 files changed

+273
-33
lines changed

4 files changed

+273
-33
lines changed

libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/bls12.hpp

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@
2828
#define CRYPTO3_MARSHALLING_PROCESSING_BLS12_CURVE_ELEMENT_HPP
2929

3030
#include <cstddef>
31-
#include <cstdint>
32-
#include <type_traits>
33-
#include <limits>
34-
#include <iterator>
3531

3632
#include <nil/marshalling/endianness.hpp>
3733
#include <nil/marshalling/status_type.hpp>
@@ -50,6 +46,75 @@ namespace nil {
5046
namespace marshalling {
5147
namespace processing {
5248

49+
50+
/* Specialization for bls12_377::g2_type */
51+
template<typename Coordinates>
52+
struct curve_element_marshalling_params<algebra::curves::bls12_377::
53+
template g2_type<Coordinates, algebra::curves::forms::short_weierstrass> >
54+
{
55+
using group_type = algebra::curves::bls12_381::template
56+
g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
57+
58+
static constexpr std::size_t length() {
59+
return bit_length() / 8 + ((bit_length() % 8) != 0);
60+
}
61+
62+
static constexpr std::size_t min_length() {
63+
return length();
64+
}
65+
66+
static constexpr std::size_t max_length() {
67+
return length();
68+
}
69+
70+
static constexpr std::size_t bit_length() {
71+
constexpr std::size_t modulus_bits_round_up = (group_type::field_type::modulus_bits + 7) & ~7;
72+
return modulus_bits_round_up * group_type::field_type::arity;
73+
}
74+
75+
static constexpr std::size_t min_bit_length() {
76+
return bit_length();
77+
}
78+
79+
static constexpr std::size_t max_bit_length() {
80+
return bit_length();
81+
}
82+
};
83+
84+
/* Specialization for bls12_381::g2_type */
85+
template<typename Coordinates>
86+
struct curve_element_marshalling_params<algebra::curves::bls12_381::
87+
template g2_type<Coordinates, algebra::curves::forms::short_weierstrass> >
88+
{
89+
using group_type = algebra::curves::bls12_381::template
90+
g2_type<Coordinates, algebra::curves::forms::short_weierstrass>;
91+
92+
static constexpr std::size_t length() {
93+
return bit_length() / 8 + ((bit_length() % 8) != 0);
94+
}
95+
96+
static constexpr std::size_t min_length() {
97+
return length();
98+
}
99+
100+
static constexpr std::size_t max_length() {
101+
return length();
102+
}
103+
104+
static constexpr std::size_t bit_length() {
105+
constexpr std::size_t modulus_bits_round_up = (group_type::field_type::modulus_bits + 7) & ~7;
106+
return modulus_bits_round_up * group_type::field_type::arity;
107+
}
108+
109+
static constexpr std::size_t min_bit_length() {
110+
return bit_length();
111+
}
112+
113+
static constexpr std::size_t max_bit_length() {
114+
return bit_length();
115+
}
116+
};
117+
53118
template<typename Endianness, typename Coordinates>
54119
struct curve_element_writer<
55120
Endianness,
@@ -263,7 +328,7 @@ namespace nil {
263328
integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
264329

265330
g1_field_value_type x_mod(x);
266-
g1_field_value_type y2_mod = x_mod.pow(3u) + g1_field_value_type(4u);
331+
g1_field_value_type y2_mod = x_mod.pow(3u) + group_type::params_type::b;
267332
BOOST_ASSERT(y2_mod.is_square());
268333
g1_field_value_type y_mod = y2_mod.sqrt();
269334
bool Y_bit = detail::sign_gf_p<g1_field_type>(y_mod);
@@ -330,7 +395,7 @@ namespace nil {
330395
integral_type x_0 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
331396

332397
g2_field_value_type x_mod(x_0, x_1);
333-
g2_field_value_type y2_mod = x_mod.pow(3u) + g2_field_value_type(4u, 4u);
398+
g2_field_value_type y2_mod = x_mod.pow(3u) + group_type::params_type::b;
334399
BOOST_ASSERT(y2_mod.is_square());
335400
g2_field_value_type y_mod = y2_mod.sqrt();
336401
bool Y_bit = detail::sign_gf_p<g2_field_type>(y_mod);
@@ -392,7 +457,7 @@ namespace nil {
392457
integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
393458

394459
g1_field_value_type x_mod(x);
395-
g1_field_value_type y2_mod = x_mod.pow(3u) + g1_field_value_type(4u);
460+
g1_field_value_type y2_mod = x_mod.pow(3u) + group_type::params_type::b;
396461
BOOST_ASSERT(y2_mod.is_square());
397462
g1_field_value_type y_mod = y2_mod.sqrt();
398463
bool Y_bit = detail::sign_gf_p<g1_field_type>(y_mod);
@@ -459,7 +524,7 @@ namespace nil {
459524
integral_type x_0 = read_data<sizeof_field_element, integral_type, endianness>(read_iter);
460525

461526
g2_field_value_type x_mod(x_0, x_1);
462-
g2_field_value_type y2_mod = x_mod.pow(3u) + g2_field_value_type(4u, 4u);
527+
g2_field_value_type y2_mod = x_mod.pow(3u) + group_type::params_type::b;
463528
BOOST_ASSERT(y2_mod.is_square());
464529
g2_field_value_type y_mod = y2_mod.sqrt();
465530
bool Y_bit = detail::sign_gf_p<g2_field_type>(y_mod);

libs/marshalling/algebra/include/nil/crypto3/marshalling/algebra/processing/secp_k1.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,4 @@ namespace nil {
187187
} // namespace marshalling
188188
} // namespace crypto3
189189
} // namespace nil
190-
#endif // CRYPTO3_MARSHALLING_PROCESSING_secp_k1<Version>_CURVE_ELEMENT_HPP
190+
#endif // CRYPTO3_MARSHALLING_PROCESSING_SECP_K1_CURVE_ELEMENT_HPP
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
//---------------------------------------------------------------------------//
2+
// Copyright (c) 2024 Vasiliy Olekhov <[email protected]>
3+
//
4+
// MIT License
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in all
14+
// copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
// SOFTWARE.
23+
//---------------------------------------------------------------------------//
24+
25+
#ifndef CRYPTO3_MARSHALLING_PROCESSING_SECP_R1_CURVE_ELEMENT_HPP
26+
#define CRYPTO3_MARSHALLING_PROCESSING_SECP_R1_CURVE_ELEMENT_HPP
27+
28+
#include <cstddef>
29+
#include <cstdint>
30+
#include <type_traits>
31+
#include <iterator>
32+
33+
#include <nil/marshalling/endianness.hpp>
34+
#include <nil/marshalling/status_type.hpp>
35+
36+
#include <nil/crypto3/algebra/type_traits.hpp>
37+
#include <nil/crypto3/algebra/curves/detail/secp_r1/types.hpp>
38+
#include <nil/crypto3/algebra/curves/detail/secp_r1/g1.hpp>
39+
#include <nil/crypto3/algebra/curves/secp_r1.hpp>
40+
41+
#include <nil/crypto3/marshalling/multiprecision/processing/integral.hpp>
42+
43+
#include <nil/crypto3/marshalling/algebra/processing/curve_element.hpp>
44+
45+
namespace nil {
46+
namespace crypto3 {
47+
namespace marshalling {
48+
namespace processing {
49+
50+
template<std::size_t Version>
51+
struct curve_element_marshalling_params<
52+
typename algebra::curves::detail::secp_r1_g1<
53+
Version,
54+
algebra::curves::forms::short_weierstrass,
55+
algebra::curves::coordinates::projective>
56+
> {
57+
using group_type = typename algebra::curves::secp_r1<Version>::template g1_type<>;
58+
59+
static constexpr std::size_t length() {
60+
return 1 + bit_length() / 8 + ((bit_length() % 8) != 0);
61+
}
62+
63+
static constexpr std::size_t min_length() {
64+
return length();
65+
}
66+
67+
static constexpr std::size_t max_length() {
68+
return length();
69+
}
70+
71+
static constexpr std::size_t bit_length() {
72+
return group_type::field_type::value_bits;
73+
}
74+
75+
static constexpr std::size_t min_bit_length() {
76+
return bit_length();
77+
}
78+
79+
static constexpr std::size_t max_bit_length() {
80+
return bit_length();
81+
}
82+
};
83+
84+
/*
85+
* Encoding of elliptic curve point according to https://www.secg.org/sec1-v2.pdf
86+
* Curve must be in short weierstrass form, Y^2 = X^3 + A*X + B
87+
* Only X coordinate is encoded, prefixed with either 02 or 03 depending on whether Y is even or odd
88+
* The encoding is big-endian
89+
* Infinity is encoded as 00
90+
* */
91+
template<std::size_t Version>
92+
struct curve_element_writer<
93+
nil::marshalling::endian::big_endian,
94+
typename algebra::curves::detail::secp_r1_g1<
95+
Version,
96+
algebra::curves::forms::short_weierstrass,
97+
algebra::curves::coordinates::projective> > {
98+
using group_type = typename algebra::curves::secp_r1<Version>::template g1_type<>;
99+
using group_value_type = typename group_type::value_type;
100+
using coordinates = typename group_value_type::coordinates;
101+
using form = typename group_value_type::form;
102+
using endianness = nil::marshalling::endian::big_endian;
103+
using params_type = curve_element_marshalling_params<group_type>;
104+
105+
template<typename TIter>
106+
static typename std::enable_if<
107+
std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
108+
nil::marshalling::status_type>::type
109+
process(const group_value_type &point, TIter &iter)
110+
{
111+
if (point.is_zero()) {
112+
*iter++ = 0x00;
113+
return nil::marshalling::status_type::success;
114+
}
115+
typename group_type::curve_type::template g1_type<typename algebra::curves::coordinates::affine, form>::value_type
116+
point_affine = point.to_affine();
117+
118+
*iter++ = (point_affine.Y.data & 1) == 0u ? 0x02 : 0x03;
119+
write_data<params_type::bit_length(), endianness>(
120+
static_cast<typename group_value_type::field_type::integral_type>(point_affine.X.data),
121+
iter);
122+
123+
return nil::marshalling::status_type::success;
124+
}
125+
};
126+
127+
template<typename Coordinates, std::size_t Version>
128+
struct curve_element_reader<
129+
nil::marshalling::endian::big_endian,
130+
typename algebra::curves::detail::secp_r1_g1<Version, algebra::curves::forms::short_weierstrass, Coordinates >> {
131+
132+
using group_type = typename algebra::curves::secp_r1<Version>::template g1_type<>;
133+
using group_value_type = typename group_type::value_type;
134+
using coordinates = typename group_value_type::coordinates;
135+
using form = typename group_value_type::form;
136+
using endianness = nil::marshalling::endian::big_endian;
137+
using params_type = curve_element_marshalling_params<group_type>;
138+
using curve_params = typename group_type::params_type;
139+
using integral_type = typename group_value_type::field_type::integral_type;
140+
using g1_field_type = typename group_value_type::field_type;
141+
using g1_field_value_type = typename g1_field_type::value_type;
142+
143+
template<typename TIter>
144+
static typename std::enable_if<
145+
std::is_same<std::uint8_t, typename std::iterator_traits<TIter>::value_type>::value,
146+
nil::marshalling::status_type>::type
147+
process(group_value_type &point, TIter &iter)
148+
{
149+
using chunk_type = typename TIter::value_type;
150+
151+
const chunk_type prefix = *iter++;
152+
153+
if (0x00 == prefix) {
154+
point = group_value_type::zero();
155+
return nil::marshalling::status_type::success;
156+
}
157+
158+
if (prefix != 0x02 && prefix != 0x03) {
159+
return nil::marshalling::status_type::invalid_msg_data;
160+
}
161+
162+
constexpr static const std::size_t sizeof_field_element =
163+
params_type::bit_length() / (group_value_type::field_type::arity);
164+
integral_type x = read_data<sizeof_field_element, integral_type, endianness>(iter);
165+
166+
g1_field_value_type x_mod(x);
167+
g1_field_value_type y2_mod = x_mod * x_mod * x_mod + curve_params::a * x_mod + curve_params::b;
168+
if (!y2_mod.is_square()) {
169+
return nil::marshalling::status_type::invalid_msg_data;
170+
}
171+
172+
g1_field_value_type y_mod = y2_mod.sqrt();
173+
174+
const chunk_type expected_prefix = (y_mod.data & 1) == 0u ? 0x02 : 0x03;
175+
176+
if (expected_prefix == prefix) {
177+
point = group_value_type(x_mod, y_mod);
178+
} else {
179+
point = group_value_type(x_mod, -y_mod);
180+
}
181+
182+
return nil::marshalling::status_type::success;
183+
}
184+
};
185+
186+
} // namespace processing
187+
} // namespace marshalling
188+
} // namespace crypto3
189+
} // namespace nil
190+
#endif // CRYPTO3_MARSHALLING_PROCESSING_SECP_R1_CURVE_ELEMENT_HPP

libs/marshalling/algebra/test/curve_element.cpp

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
#include <nil/crypto3/marshalling/algebra/processing/vesta.hpp>
8484

8585
#include <nil/crypto3/marshalling/algebra/processing/secp_k1.hpp>
86-
//#include <nil/crypto3/marshalling/algebra/processing/secp_r1.hpp>
86+
#include <nil/crypto3/marshalling/algebra/processing/secp_r1.hpp>
8787

8888
template<typename T, typename endianness>
8989
void test_group_element(T val) {
@@ -104,28 +104,10 @@ void test_group_element(T val) {
104104
std::vector<unit_type> cv = nil::marshalling::pack<endianness>(val, status);
105105
BOOST_CHECK(status == nil::marshalling::status_type::success);
106106

107-
std::cout << "Value: " << std::hex << val.to_affine() << std::endl;
108-
109-
/* */
110-
std::cout << "Serialized as " << cv.size() << " bytes:" << std::endl;
111-
for(auto &x: cv) {
112-
std::cout << std::hex << std::setw(2) << std::setfill('0');
113-
std::cout << (int)x;
114-
}
115-
std::cout << std::endl;
116-
/* */
117-
118107
T test_val = nil::marshalling::pack<endianness>(cv, status);
119108
BOOST_CHECK(status == nil::marshalling::status_type::success);
120109

121110
BOOST_CHECK_EQUAL(val.to_affine(), test_val.to_affine());
122-
if (val == test_val) {
123-
std::cout << "";
124-
} else {
125-
std::cout << "Deserialized: " << std::endl << std::hex << test_val.to_affine() << std::endl;
126-
std::cout << "";
127-
}
128-
std::cout << "========================" << std::endl;
129111
}
130112

131113
template<typename group_type, typename endianness>
@@ -196,7 +178,7 @@ BOOST_AUTO_TEST_CASE(curve_element_bls12_381) {
196178

197179
BOOST_AUTO_TEST_CASE(curve_element_bls12_377) {
198180
// it freezes
199-
// test_pairing_curve<nil::crypto3::algebra::curves::bls12_377, big_endian>("bls12_377");
181+
test_pairing_curve<nil::crypto3::algebra::curves::bls12_377, big_endian>("bls12_377");
200182
}
201183

202184
BOOST_AUTO_TEST_CASE(curve_element_bn254) {
@@ -211,16 +193,19 @@ BOOST_AUTO_TEST_CASE(curve_element_vesta) {
211193
test_curve<nil::crypto3::algebra::curves::vesta, big_endian>("vesta");
212194
}
213195

214-
// TODO: implement marshalling for secp_k1/secp_r1 curves
215196
BOOST_AUTO_TEST_CASE(curve_element_secp_k1) {
216197
test_curve<nil::crypto3::algebra::curves::secp_k1<160>, big_endian>("secp_k1<160>");
198+
test_curve<nil::crypto3::algebra::curves::secp_k1<192>, big_endian>("secp_k1<192>");
199+
test_curve<nil::crypto3::algebra::curves::secp_k1<224>, big_endian>("secp_k1<224>");
200+
test_curve<nil::crypto3::algebra::curves::secp_k1<256>, big_endian>("secp_k1<256>");
217201
}
218202

219-
#if 0
220203
BOOST_AUTO_TEST_CASE(curve_element_secp_r1) {
221-
test_curve<nil::crypto3::algebra::curves::secp_r1<160>>("secp_r1<160>");
204+
test_curve<nil::crypto3::algebra::curves::secp_r1<160>, big_endian>("secp_r1<160>");
205+
test_curve<nil::crypto3::algebra::curves::secp_r1<192>, big_endian>("secp_r1<192>");
206+
test_curve<nil::crypto3::algebra::curves::secp_r1<224>, big_endian>("secp_r1<224>");
207+
test_curve<nil::crypto3::algebra::curves::secp_r1<256>, big_endian>("secp_r1<256>");
222208
}
223-
#endif
224209

225210
BOOST_AUTO_TEST_CASE(curve_element_jubjub) {
226211
test_curve<nil::crypto3::algebra::curves::jubjub, little_endian>("jubjub");

0 commit comments

Comments
 (0)