Skip to content

Commit

Permalink
GH-2334 Remove duplicate code and update comments
Browse files Browse the repository at this point in the history
  • Loading branch information
heifner committed Mar 27, 2024
1 parent aea1aa1 commit 2686c85
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 37 deletions.
26 changes: 11 additions & 15 deletions libraries/libfc/include/fc/crypto/bls_signature.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ namespace fc::crypto::blslib {
const std::string bls_signature_prefix = "SIG_BLS_";
};

// Immutable after construction.
// Immutable after construction (although operator= is provided).
// Provides an efficient wrapper around bls12_381::g2.
// Serialization form:
// Non-Montgomery form and little-endian encoding for the field elements.
// Affine form for the group element (the z component is 1 and not included in the serialization).
// Binary serialization encodes x component first followed by y component.
// Cached g2 in Jacobian Montgomery is used for efficient BLS math.
// Keeping the serialized data allows for efficient serialization without the expensive conversion
// from Jacobian Montgomery to Affine Non-Montgomery.
class bls_signature {
public:
bls_signature() = default;
Expand Down Expand Up @@ -50,23 +53,19 @@ namespace fc::crypto::blslib {
template<typename T>
friend T& operator>>(T& ds, bls_signature& sig) {
ds.read(reinterpret_cast<char*>(sig._affine_non_montgomery_le.data()), sig._affine_non_montgomery_le.size()*sizeof(uint8_t));
constexpr bool check = true; // check if invalid
constexpr bool raw = false; // non-montgomery
std::optional<bls12_381::g2> g2 = bls12_381::g2::fromAffineBytesLE(sig._affine_non_montgomery_le, check, raw);
FC_ASSERT(g2, "Invalid bls signature ${k}", ("k", sig._affine_non_montgomery_le));
sig._jacobian_montgomery_le = *g2;
sig._jacobian_montgomery_le = to_jacobian_montgomery_le(sig._affine_non_montgomery_le);
return ds;
}

private:
friend class bls_aggregate_signature;
static bls12_381::g2 to_jacobian_montgomery_le(const std::array<uint8_t, 192>& affine_non_montgomery_le);

std::array<uint8_t, 192> _affine_non_montgomery_le{};
bls12_381::g2 _jacobian_montgomery_le; // cached g2
};

// Serialization form:
// Non-Montgomery form and little-endian encoding for the field elements.
// Affine form for the group element (the z component is 1 and not included in the serialization).
// Binary serialization encodes x component first followed by y component.
// See bls_signature comment above
class bls_aggregate_signature {
public:
bls_aggregate_signature() = default;
Expand All @@ -91,6 +90,7 @@ namespace fc::crypto::blslib {
}

// affine non-montgomery base64url with bls_signature_prefix
// Expensive as conversion from Jacobian Montgomery to Affine Non-Montgomery needed
std::string to_string() const;

const bls12_381::g2& jacobian_montgomery_le() const { return _jacobian_montgomery_le; }
Expand All @@ -112,11 +112,7 @@ namespace fc::crypto::blslib {
friend T& operator>>(T& ds, bls_aggregate_signature& sig) {
std::array<uint8_t, 192> affine_non_montgomery_le;
ds.read(reinterpret_cast<char*>(affine_non_montgomery_le.data()), affine_non_montgomery_le.size()*sizeof(uint8_t));
constexpr bool check = true; // check if invalid
constexpr bool raw = false; // non-montgomery
std::optional<bls12_381::g2> g2 = bls12_381::g2::fromAffineBytesLE(affine_non_montgomery_le, check, raw);
FC_ASSERT(g2, "Invalid bls aggregate signature ${k}", ("k", affine_non_montgomery_le));
sig._jacobian_montgomery_le = *g2;
sig._jacobian_montgomery_le = bls_signature::to_jacobian_montgomery_le(affine_non_montgomery_le);
return ds;
}

Expand Down
44 changes: 22 additions & 22 deletions libraries/libfc/src/crypto/bls_signature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,46 @@

namespace fc::crypto::blslib {

bls_signature::bls_signature(std::span<const uint8_t, 192> affine_non_montgomery_le) {
std::ranges::copy(affine_non_montgomery_le, _affine_non_montgomery_le.begin());
bls12_381::g2 bls_signature::to_jacobian_montgomery_le(const std::array<uint8_t, 192>& affine_non_montgomery_le) {
constexpr bool check = true; // verify
constexpr bool raw = false; // to montgomery
auto g2 = bls12_381::g2::fromAffineBytesLE(affine_non_montgomery_le, check, raw);
FC_ASSERT(g2, "Invalid bls_signature");
_jacobian_montgomery_le = *g2;
return *g2;
}

static std::tuple<bls12_381::g2, std::array<uint8_t, 192>> sig_parse_base64url(const std::string& base64urlstr) {
inline std::array<uint8_t, 192> from_span(std::span<const uint8_t, 192> affine_non_montgomery_le) {
std::array<uint8_t, 192> r;
std::ranges::copy(affine_non_montgomery_le, r.begin());
return r;
}

bls_signature::bls_signature(std::span<const uint8_t, 192> affine_non_montgomery_le)
: _affine_non_montgomery_le(from_span(affine_non_montgomery_le))
, _jacobian_montgomery_le(to_jacobian_montgomery_le(_affine_non_montgomery_le)) {
}

static std::array<uint8_t, 192> sig_parse_base64url(const std::string& base64urlstr) {
try {
auto res = std::mismatch(config::bls_signature_prefix.begin(), config::bls_signature_prefix.end(),
base64urlstr.begin());
auto res = std::mismatch(config::bls_signature_prefix.begin(), config::bls_signature_prefix.end(), base64urlstr.begin());
FC_ASSERT(res.first == config::bls_signature_prefix.end(), "BLS Signature has invalid format : ${str}", ("str", base64urlstr));

auto data_str = base64urlstr.substr(config::bls_signature_prefix.size());

std::array<uint8_t, 192> bytes = fc::crypto::blslib::deserialize_base64url<std::array<uint8_t, 192>>(data_str);

constexpr bool check = true; // check if base64urlstr is invalid
constexpr bool raw = false; // non-montgomery
std::optional<bls12_381::g2> g2 = bls12_381::g2::fromAffineBytesLE(bytes, check, raw);
FC_ASSERT(g2);
return {*g2, bytes};
} FC_RETHROW_EXCEPTIONS( warn, "error parsing bls_signature", ("str", base64urlstr ) )
return fc::crypto::blslib::deserialize_base64url<std::array<uint8_t, 192>>(data_str);
} FC_RETHROW_EXCEPTIONS( warn, "error parsing bls_signature", ("str", base64urlstr ) )
}

bls_signature::bls_signature(const std::string& base64urlstr) {
std::tie(_jacobian_montgomery_le, _affine_non_montgomery_le) = sig_parse_base64url(base64urlstr);
bls_signature::bls_signature(const std::string& base64urlstr)
: _affine_non_montgomery_le(sig_parse_base64url(base64urlstr))
, _jacobian_montgomery_le(to_jacobian_montgomery_le(_affine_non_montgomery_le)) {
}

std::string bls_signature::to_string() const {
std::string data_str = fc::crypto::blslib::serialize_base64url<std::array<uint8_t, 192>>(_affine_non_montgomery_le);
return config::bls_signature_prefix + data_str;
}

bls_aggregate_signature::bls_aggregate_signature(const std::string& base64urlstr) {
std::tie(_jacobian_montgomery_le, std::ignore) = sig_parse_base64url(base64urlstr);
bls_aggregate_signature::bls_aggregate_signature(const std::string& base64urlstr)
: _jacobian_montgomery_le(bls_signature::to_jacobian_montgomery_le(sig_parse_base64url(base64urlstr))) {
}

std::string bls_aggregate_signature::to_string() const {
Expand All @@ -59,15 +61,13 @@ namespace fc {
void to_variant(const crypto::blslib::bls_signature& var, variant& vo) {
vo = var.to_string();
}

void from_variant(const variant& var, crypto::blslib::bls_signature& vo) {
vo = crypto::blslib::bls_signature(var.as_string());
}

void to_variant(const crypto::blslib::bls_aggregate_signature& var, variant& vo) {
vo = var.to_string();
}

void from_variant(const variant& var, crypto::blslib::bls_aggregate_signature& vo) {
vo = crypto::blslib::bls_aggregate_signature(var.as_string());
}
Expand Down

0 comments on commit 2686c85

Please sign in to comment.