Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ec_scalar: add non-const accessor and construct by value #1080

Merged
merged 1 commit into from
Dec 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/bitcoin/bitcoin/math/ec_scalar.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class BC_API ec_scalar
/// Constructors.
ec_scalar();
ec_scalar(const ec_secret& secret);
ec_scalar(uint64_t value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This constructor was removed from the original pull request. There is no mapping from a 64 bit value to an ec_secret nor should a 64 bit value ever be considered a secret. If the caller intends to implement such a mapping it should be implemented outside of this class and passed in as an ec_secret.


/// Operators.
// TODO: add equality and inequality operators.
Expand All @@ -49,6 +50,7 @@ class BC_API ec_scalar

/// Accessors.
const ec_secret& secret() const;
ec_secret& secret();

protected:
// These should be const, apart from the need to implement assignment.
Expand Down
12 changes: 12 additions & 0 deletions src/math/ec_scalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ ec_scalar::ec_scalar(const ec_secret& secret)
{
}

ec_scalar::ec_scalar(uint64_t value)
: valid_(true)
{
secret_ = zero;
auto serial = make_unsafe_serializer(secret_.end() - 4);
serial.write_4_bytes_big_endian(value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Writing 4 bytes casted from an 8 byte value, as big endian, into the high order bytes of a 32 byte value appears completely arbitrary and unrelated to the behavior of an ec scalar.

}

// Operators.
// ----------------------------------------------------------------------------

Expand Down Expand Up @@ -128,5 +136,9 @@ const ec_secret& ec_scalar::secret() const
{
return secret_;
}
ec_secret& ec_scalar::secret()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This allows the caller to modify ec_scalar internals, which should only be done via the assignment operator (which btw is equally efficient).

{
return secret_;
}

} // namespace libbitcoin
68 changes: 8 additions & 60 deletions test/math/ec_point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,71 +21,19 @@

using namespace bc;

BOOST_AUTO_TEST_SUITE(ec_scalar_tests)
BOOST_AUTO_TEST_SUITE(ec_point_tests)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch.


#define SECRET1A "b9d22ea0ed7e3d53cc9e1b3d436bb9260fc3211634c821f6bb3cb3a73ee7a0b5"
#define SECRET1B "f9416cd856d81a00366ad7234a7b5e5dbda61812e56effcb4cde0695bc092380"
#define SUM1 "b3139b79445657540308f2608de7178512ba5c426aee818648485bb02aba82f4"
#define PRODUCT1 "aba800424dd618d36a42bf6d6d3156a38a74298b9e4519bbba34cf0d7dce4d4f"
#define POINTX "0245dbb7e2cd3a5de19fde8d556fd567a036f9c377ecf69a9202aa4affce41c623"
#define POINTY "02cfc43e064c50cfd1896766ef70e7da82b16e8cfebd8d5dec618212d0db1e6d12"
#define SUM "03332bf6821c7c0e1080efc131d2b745760a8245c0b91a05f13308ff8600d30525"

#define POSITIVE_ONE "0000000000000000000000000000000000000000000000000000000000000001"
#define POSITIVE_TWO "0000000000000000000000000000000000000000000000000000000000000002"
#define NEGATIVE_ONE "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140"

#define SECRET2 "8010b1bb119ad37d4b65a1022a314897b1b3614b345974332cb1b9582cf03536"
#define COMPRESSED2 "0309ba8621aefd3b6ba4ca6d11a4746e8df8d35d9b51b383338f627ba7fc732731"

BOOST_AUTO_TEST_CASE(ec_scalar__zero__multiply_g__fail)
{
const auto product = ec_scalar::zero * ec_point::G;
BOOST_REQUIRE(!product);
}

BOOST_AUTO_TEST_CASE(ec_scalar__add__valid__expected)
BOOST_AUTO_TEST_CASE(ec_point__sum__valid__expected)
{
const ec_scalar x{ base16_literal(SECRET1A) };
const ec_scalar y{ base16_literal(SECRET1B) };
const ec_point x{ base16_literal(POINTX) };
const ec_point y{ base16_literal(POINTY) };
const auto sum = x + y;
BOOST_REQUIRE(sum);
BOOST_REQUIRE_EQUAL(encode_base16(sum.secret()), SUM1);
}

BOOST_AUTO_TEST_CASE(ec_scalar__multiply__valid__expected)
{
const ec_scalar x{ base16_literal(SECRET1A) };
const ec_scalar y{ base16_literal(SECRET1B) };
const auto product = x * y;
BOOST_REQUIRE(product);
BOOST_REQUIRE_EQUAL(encode_base16(product.secret()), PRODUCT1);
}

BOOST_AUTO_TEST_CASE(ec_scalar__negate__positive__expected)
{
const ec_scalar one{ base16_literal(POSITIVE_ONE) };
const auto negation = -one;
BOOST_REQUIRE(one);
BOOST_REQUIRE(negation);
BOOST_REQUIRE_EQUAL(encode_base16(negation.secret()), NEGATIVE_ONE);
}

BOOST_AUTO_TEST_CASE(ec_scalar__add__negative__expected)
{
const ec_scalar one{ base16_literal(POSITIVE_ONE) };
const ec_scalar two{ base16_literal(POSITIVE_TWO) };
BOOST_REQUIRE(one);
BOOST_REQUIRE(two);

const auto sum = -one + two;
BOOST_REQUIRE(sum);
BOOST_REQUIRE_EQUAL(encode_base16(sum.secret()), encode_base16(one.secret()));
}

BOOST_AUTO_TEST_CASE(ec_arithmetic__point__multiply_g__expected)
{
const ec_scalar key = base16_literal(SECRET2);
const auto product = key * ec_point::G;
BOOST_REQUIRE(product);
BOOST_REQUIRE_EQUAL(encode_base16(product.point()), COMPRESSED2);
BOOST_REQUIRE_EQUAL(encode_base16(sum.point()), SUM);
}

BOOST_AUTO_TEST_SUITE_END()
85 changes: 77 additions & 8 deletions test/math/ec_scalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,88 @@

using namespace bc;

BOOST_AUTO_TEST_SUITE(ec_point_tests)
BOOST_AUTO_TEST_SUITE(ec_scalar_tests)

#define POINTX "0245dbb7e2cd3a5de19fde8d556fd567a036f9c377ecf69a9202aa4affce41c623"
#define POINTY "02cfc43e064c50cfd1896766ef70e7da82b16e8cfebd8d5dec618212d0db1e6d12"
#define SUM "03332bf6821c7c0e1080efc131d2b745760a8245c0b91a05f13308ff8600d30525"
#define SECRET1A "b9d22ea0ed7e3d53cc9e1b3d436bb9260fc3211634c821f6bb3cb3a73ee7a0b5"
#define SECRET1B "f9416cd856d81a00366ad7234a7b5e5dbda61812e56effcb4cde0695bc092380"
#define SUM1 "b3139b79445657540308f2608de7178512ba5c426aee818648485bb02aba82f4"
#define PRODUCT1 "aba800424dd618d36a42bf6d6d3156a38a74298b9e4519bbba34cf0d7dce4d4f"

BOOST_AUTO_TEST_CASE(ec_point__sum__valid__expected)
#define POSITIVE_ONE "0000000000000000000000000000000000000000000000000000000000000001"
#define POSITIVE_TWO "0000000000000000000000000000000000000000000000000000000000000002"
#define NEGATIVE_ONE "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140"

#define SECRET2 "8010b1bb119ad37d4b65a1022a314897b1b3614b345974332cb1b9582cf03536"
#define COMPRESSED2 "0309ba8621aefd3b6ba4ca6d11a4746e8df8d35d9b51b383338f627ba7fc732731"

BOOST_AUTO_TEST_CASE(ec_scalar__zero__multiply_g__fail)
{
const auto product = ec_scalar::zero * ec_point::G;
BOOST_REQUIRE(!product);
}

BOOST_AUTO_TEST_CASE(ec_scalar__add__valid__expected)
{
const ec_point x{ base16_literal(POINTX) };
const ec_point y{ base16_literal(POINTY) };
const ec_scalar x{ base16_literal(SECRET1A) };
const ec_scalar y{ base16_literal(SECRET1B) };
const auto sum = x + y;
BOOST_REQUIRE(sum);
BOOST_REQUIRE_EQUAL(encode_base16(sum.point()), SUM);
BOOST_REQUIRE_EQUAL(encode_base16(sum.secret()), SUM1);
}

BOOST_AUTO_TEST_CASE(ec_scalar__multiply__valid__expected)
{
const ec_scalar x{ base16_literal(SECRET1A) };
const ec_scalar y{ base16_literal(SECRET1B) };
const auto product = x * y;
BOOST_REQUIRE(product);
BOOST_REQUIRE_EQUAL(encode_base16(product.secret()), PRODUCT1);
}

BOOST_AUTO_TEST_CASE(ec_scalar__negate__positive__expected)
{
const ec_scalar one{ base16_literal(POSITIVE_ONE) };
const auto negation = -one;
BOOST_REQUIRE(one);
BOOST_REQUIRE(negation);
BOOST_REQUIRE_EQUAL(encode_base16(negation.secret()), NEGATIVE_ONE);
}

BOOST_AUTO_TEST_CASE(ec_scalar__add__negative__expected)
{
const ec_scalar one{ base16_literal(POSITIVE_ONE) };
const ec_scalar two{ base16_literal(POSITIVE_TWO) };
BOOST_REQUIRE(one);
BOOST_REQUIRE(two);

const auto sum = -one + two;
BOOST_REQUIRE(sum);
BOOST_REQUIRE_EQUAL(encode_base16(sum.secret()), encode_base16(one.secret()));
}

BOOST_AUTO_TEST_CASE(ec_arithmetic__point__multiply_g__expected)
{
const ec_scalar key = base16_literal(SECRET2);
const auto product = key * ec_point::G;
BOOST_REQUIRE(product);
BOOST_REQUIRE_EQUAL(encode_base16(product.point()), COMPRESSED2);
}

BOOST_AUTO_TEST_CASE(ec_scalar__init__expected)
{
const ec_scalar one{ base16_literal(POSITIVE_ONE) };
const ec_scalar two{ base16_literal(POSITIVE_TWO) };
BOOST_REQUIRE(one);
BOOST_REQUIRE(two);

const ec_scalar one_uint64(1);
const ec_scalar two_uint64(2);
BOOST_REQUIRE(one_uint64);
BOOST_REQUIRE(two_uint64);
BOOST_REQUIRE_EQUAL(encode_base16(
one.secret()), encode_base16(one_uint64.secret()));
BOOST_REQUIRE_EQUAL(encode_base16(
two.secret()), encode_base16(two_uint64.secret()));
}

BOOST_AUTO_TEST_SUITE_END()