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

fix: addressing Huberts PR comments #124

Merged
merged 32 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
b011c50
fix: addon.cc for PR comments
matthewkeil Mar 8, 2024
dcb01cd
fix: use #pragma once
matthewkeil Mar 8, 2024
99002cc
fix: remove using cout and endl
matthewkeil Mar 8, 2024
4bc0474
fix: update visibility of BlstTsAddon members and remove _ for publics
matthewkeil Mar 8, 2024
254be1a
refactor: lowercase functions namespace and init
matthewkeil Mar 8, 2024
a2a9b71
refactor: remove functions.h
matthewkeil Mar 8, 2024
8a2c561
fix: and ... catch to PublicKey::Deserialize and catch blst error by …
matthewkeil Mar 8, 2024
9919eb1
fix: add is_affine = false case
matthewkeil Mar 8, 2024
3a5f64f
refactor: remove auto type for proto in class init
matthewkeil Mar 12, 2024
3d138e5
fix: change override to final in point wrapers
matthewkeil Mar 12, 2024
13cbfb8
fix: replace hard coded numbers to macros
matthewkeil Mar 12, 2024
4f52d9a
fix: make points in wrappers private
matthewkeil Mar 12, 2024
d412287
fix: add const casting to all point wrapper methods where feasible
matthewkeil Mar 12, 2024
f8c1239
fix: missed swapping hard coded numbers to macros
matthewkeil Mar 12, 2024
962abcc
feat: make gyp file c++17 compliant
matthewkeil Mar 12, 2024
560e699
fix: remove duplicate headers from secret_key.h
matthewkeil Mar 12, 2024
bf0461f
refactor: remove underscore from public members
matthewkeil Mar 12, 2024
5d02255
refactor: convert macro sizes to static const values
matthewkeil Mar 12, 2024
86c4cad
feat: mark main classes as final
matthewkeil Mar 12, 2024
f17928e
feat: create blst_ts namespace
matthewkeil Mar 12, 2024
e5010f8
refactor: remove IS_INFINITY macro
matthewkeil Mar 14, 2024
658cda3
refactor: move wrapper function definitions to .cc
matthewkeil Mar 14, 2024
cba443e
feat: break out info[1] in FromKeygen
matthewkeil Mar 15, 2024
2e41be9
refactor: directly set is_zero_bytes
matthewkeil Mar 15, 2024
2e11c9e
fix: remove erroneous return and add comment about is_external for se…
matthewkeil Mar 15, 2024
2c85cf1
fix: catch by const ref
matthewkeil Mar 15, 2024
5de98fa
fix: remove ostringstream
matthewkeil Mar 15, 2024
91c46cd
fix: remove hungarian notation
matthewkeil Mar 15, 2024
3028b07
feat: return optional<string> from is_valid_length
matthewkeil Mar 15, 2024
5353fc0
refactor: update docstring and move to header
matthewkeil Mar 15, 2024
ed48ba5
feat: add Refs to async functions to prevent GC
matthewkeil Mar 15, 2024
1625ff0
feat: add final to point wrappers
matthewkeil Mar 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions rebuild/binding.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
'-Wpedantic',
],
'cflags_cc': [
'-std=c++17',
'-fexceptions',
'-Werror',
'-Wall',
Expand All @@ -41,6 +42,7 @@
'VCCLCompilerTool': {
'ExceptionHandling': 1,
'EnablePREfast': 'true',
'AdditionalOptions': [ '/std:c++17' ],
},
},
}
Expand All @@ -52,6 +54,7 @@
['OS=="mac"', {
'xcode_settings': {
'OTHER_CFLAGS': ['-fvisibility=hidden'],
'CLANG_CXX_LANGUAGE_STANDARD': 'c++17',
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
'CLANG_CXX_LIBRARY': 'libc++',
'MACOSX_DEPLOYMENT_TARGET': '12',
Expand Down
84 changes: 46 additions & 38 deletions rebuild/src/addon.cc
Original file line number Diff line number Diff line change
@@ -1,61 +1,63 @@
#include "addon.h"

namespace blst_ts {
bool is_zero_bytes(
const uint8_t *data, const size_t start_byte, const size_t byte_length) {
for (size_t i = start_byte; i < byte_length; i++) {
if (data[i] != 0) {
return false;
}
const uint8_t *data,
const size_t starting_index,
const size_t byte_length) noexcept {
if (starting_index < byte_length) {
return std::all_of(
data + starting_index, data + byte_length, [](uint8_t x) {
return x == 0x00;
});
}
return true;
return false;
}

bool is_valid_length(
std::string &error_out,
size_t byte_length,
size_t length1,
size_t length2) {
[[nodiscard]] std::optional<std::string> is_valid_length(
size_t byte_length, size_t length1, size_t length2) noexcept {
if (byte_length == length1 || (length2 != 0 && byte_length == length2)) {
return true;
return std::nullopt;
}
error_out.append(" must be ");
std::string err_msg{" must be "};
if (length1 != 0) {
error_out.append(std::to_string(length1));
err_msg.append(std::to_string(length1));
};
if (length2 != 0) {
if (length1 != 0) {
error_out.append(" or ");
err_msg.append(" or ");
}
error_out.append(std::to_string(length2));
err_msg.append(std::to_string(length2));
};
error_out.append(" bytes long");
return false;
err_msg.append(" bytes long");
return err_msg;
}
} // namespace blst_ts

BlstTsAddon::BlstTsAddon(Napi::Env env, Napi::Object exports)
: _dst{"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"},
_blst_error_strings{
"BLST_SUCCESS",
"BLST_ERROR::BLST_BAD_ENCODING",
"BLST_ERROR::BLST_POINT_NOT_ON_CURVE",
"BLST_ERROR::BLST_POINT_NOT_IN_GROUP",
"BLST_ERROR::BLST_AGGR_TYPE_MISMATCH",
"BLST_ERROR::BLST_VERIFY_FAIL",
"BLST_ERROR::BLST_PK_IS_INFINITY",
"BLST_ERROR::BLST_BAD_SCALAR",
} {
: _blst_error_strings{
"BLST_SUCCESS",
"BLST_ERROR::BLST_BAD_ENCODING",
"BLST_ERROR::BLST_POINT_NOT_ON_CURVE",
"BLST_ERROR::BLST_POINT_NOT_IN_GROUP",
"BLST_ERROR::BLST_AGGR_TYPE_MISMATCH",
"BLST_ERROR::BLST_VERIFY_FAIL",
"BLST_ERROR::BLST_PK_IS_INFINITY",
"BLST_ERROR::BLST_BAD_SCALAR",
},
dst{"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"} {
Napi::Object js_constants = Napi::Object::New(env);
js_constants.Set(
Napi::String::New(env, "DST"), Napi::String::New(env, _dst));
Napi::String::New(env, "DST"), Napi::String::New(env, dst));
DefineAddon(
exports,
{
InstanceValue("BLST_CONSTANTS", js_constants, napi_enumerable),
});
SecretKey::Init(env, exports, this);
PublicKey::Init(env, exports, this);
Signature::Init(env, exports, this);
Functions::Init(env, exports);
blst_ts::SecretKey::Init(env, exports, this);
blst_ts::PublicKey::Init(env, exports, this);
blst_ts::Signature::Init(env, exports, this);
blst_ts_functions::init(env, exports);
env.SetInstanceData(this);

// Check that openssl PRNG is seeded
Expand All @@ -68,6 +70,14 @@ BlstTsAddon::BlstTsAddon(Napi::Env env, Napi::Object exports)
}

std::string BlstTsAddon::GetBlstErrorString(const blst::BLST_ERROR &err) {
size_t err_index = static_cast<size_t>(err);
// size of total array divided by size of one element minus 1 for 0 index
// basis
size_t max_index =
sizeof(_blst_error_strings) / sizeof(_blst_error_strings[0]) - 1;
if (err_index > max_index) {
return "BLST_ERROR::UNKNOWN_ERROR_CODE";
}
return _blst_error_strings[err];
}

Expand All @@ -77,10 +87,8 @@ bool BlstTsAddon::GetRandomBytes(blst::byte *bytes, size_t length) {
// [RandomBytesTraits::DeriveBits](https://github.com/nodejs/node/blob/4166d40d0873b6d8a0c7291872c8d20dc680b1d7/src/crypto/crypto_random.cc#L65)
// [CSPRNG](https://github.com/nodejs/node/blob/4166d40d0873b6d8a0c7291872c8d20dc680b1d7/src/crypto/crypto_util.cc#L63)
do {
if (1 == RAND_status()) {
if (1 == RAND_bytes(bytes, length)) {
return true;
}
if ((1 == RAND_status()) && (1 == RAND_bytes(bytes, length))) {
return true;
}
} while (1 == RAND_poll());

Expand Down
106 changes: 56 additions & 50 deletions rebuild/src/addon.h
Original file line number Diff line number Diff line change
@@ -1,34 +1,26 @@
#ifndef BLST_TS_ADDON_H__
#define BLST_TS_ADDON_H__
#pragma once

#include <openssl/rand.h>

#include <algorithm>
#include <iostream>
#include <memory>
#include <sstream>
#include <optional>
#include <string>
#include <string_view>

#include "blst.hpp"
#include "napi.h"

// TODO: these should come out post PR review
using std::cout;
using std::endl;

namespace blst_ts {
#define BLST_TS_RANDOM_BYTES_LENGTH 8U

#define BLST_TS_FUNCTION_PREAMBLE(info, env, module) \
Napi::Env env = info.Env(); \
Napi::EscapableHandleScope scope(env); \
BlstTsAddon *module = env.GetInstanceData<BlstTsAddon>();

#define BLST_TS_IS_INFINITY \
Napi::Env env = info.Env(); \
Napi::EscapableHandleScope scope(env); \
return scope.Escape(Napi::Boolean::New(env, _point->IsInfinite()));

#define BLST_TS_SERIALIZE_POINT(macro_name) \
#define BLST_TS_SERIALIZE_POINT(snake_case_name) \
Napi::Env env = info.Env(); \
Napi::EscapableHandleScope scope(env); \
bool compressed{true}; \
Expand All @@ -37,12 +29,12 @@ using std::endl;
} \
Napi::Buffer<uint8_t> serialized = Napi::Buffer<uint8_t>::New( \
env, \
compressed ? BLST_TS_##macro_name##_LENGTH_COMPRESSED \
: BLST_TS_##macro_name##_LENGTH_UNCOMPRESSED); \
_point->Serialize(compressed, serialized.Data()); \
compressed ? snake_case_name##_length_compressed \
: snake_case_name##_length_uncompressed); \
point->Serialize(compressed, serialized.Data()); \
return scope.Escape(serialized);

#define BLST_TS_UNWRAP_UINT_8_ARRAY(value_name, arr_name, js_name) \
#define BLST_TS_UNWRAP_UINT_8_ARRAY(value_name, arr_name, js_name) \
if (!value_name.IsTypedArray()) { \
Napi::TypeError::New( \
env, "BLST_ERROR: " js_name " must be a BlstBuffer") \
Expand All @@ -59,79 +51,95 @@ using std::endl;
Napi::Uint8Array arr_name = \
arr_name##_array.As<Napi::TypedArrayOf<uint8_t>>();

#define BLST_TS_CLASS_UNWRAP_UINT_8_ARRAY(value_name, arr_name, js_name) \
#define BLST_TS_CLASS_UNWRAP_UINT_8_ARRAY(value_name, arr_name, js_name) \
if (!value_name.IsTypedArray()) { \
Napi::TypeError::New( \
env, "BLST_ERROR: " js_name " must be a BlstBuffer") \
.ThrowAsJavaScriptException(); \
m_has_error = true; \
has_error = true; \
return; \
} \
Napi::TypedArray arr_name##_array = value_name.As<Napi::TypedArray>(); \
if (arr_name##_array.TypedArrayType() != napi_uint8_array) { \
Napi::TypeError::New( \
env, "BLST_ERROR: " js_name " must be a BlstBuffer") \
.ThrowAsJavaScriptException(); \
m_has_error = true; \
has_error = true; \
return; \
} \
Napi::Uint8Array arr_name = \
arr_name##_array.As<Napi::TypedArrayOf<uint8_t>>();

class BlstTsAddon;

typedef enum { Affine, Jacobian } CoordType;

/**
* Checks a byte array to see if it is all zeros. Can pass start byte for the
* cases where the first byte is the tag (infinity point and
* compress/uncompressed).
* Checks if a specified range of bytes within a byte array consists only of
* zeros.
*
* @param data uint8_t*
* @param start_byte size_t
* @param byte_length size_t
* @param data A pointer to the first element of the byte array to be checked.
* @param starting_index The offset (index) from the beginning of the array
* where the check should start. (0 starts at *data)
* @param byte_length The total length of the data array
*
* @return bool
* @return Returns true if all bytes from start_byte to the end of the array are
* zeros. Returns false if the starting offset is beyond the array length or if
* any byte in the specified range is not zero.
*/
bool is_zero_bytes(
const uint8_t *data, const size_t start_byte, const size_t byte_length);
const uint8_t *data,
const size_t start_byte,
const size_t byte_length) noexcept;

/**
* Checks if a byte array is a valid length. If not, sets the error message and
* returns false. If valid returns true for use in conditional statements.
* Validates that a given byte length matches one of two specified lengths,
* returning an optional error message if the validation fails.
*
* @param[out] error_out &std::string - error message to set if invalid
* @param[in] byte_length size_t - length of the byte array to validate
* @param[in] length1 size_t - first valid length
* @param[in] length2 size_t - second valid length (optional)
* @param byte_length The length to be validated against length1 and length2.
* @param length1 The first valid length that byte_length can be. A value of 0
* is considered as not set and thus not compared.
* @param length2 The second valid length that byte_length can be. A value of 0
* is considered as not set and thus not compared.
*
* @return bool
* @return An std::optional<std::string> that contains an error message if
* byte_length does not match either length1 or (if length2 is not 0) length2.
* If byte_length is valid, std::nullopt is returned. The error message, if
* returned, specifies the valid lengths byte_length must match.
*
* @note If both length1 and length2 are provided (non-zero), and byte_length
* does not match, the error message indicates that the valid byte_length must
* be either length1 or length2. If only one length is provided (the other being
* 0), the error message will only reference the provided length. This function
* is marked with [[nodiscard]] to ensure that the caller handles the potential
* error message, promoting safer and more intentional error checking.
*/
bool is_valid_length(
std::string &error_out,
size_t byte_length,
size_t length1,
size_t length2 = 0);
[[nodiscard]] std::optional<std::string> is_valid_length(
size_t byte_length, size_t length1, size_t length2 = 0) noexcept;
} // namespace blst_ts

class BlstTsAddon;
/**
* Circular dependency if these are moved up to the top of the file.
*/
#include "functions.h"
#include "public_key.h"
#include "secret_key.h"
#include "signature.h"
namespace blst_ts_functions {
void init(const Napi::Env &env, Napi::Object &exports);
}

/**
* BlstTsAddon is the main entry point for the library. It is responsible
* for initialization and holding global values.
*/
class BlstTsAddon : public Napi::Addon<BlstTsAddon> {
public:
std::string _dst;
private:
std::string _blst_error_strings[8];
Napi::FunctionReference _secret_key_ctr;
Napi::FunctionReference _public_key_ctr;
Napi::FunctionReference _signature_ctr;

public:
std::string dst;
Napi::FunctionReference secret_key_ctr;
Napi::FunctionReference public_key_ctr;
Napi::FunctionReference signature_ctr;

/**
* BlstTsAddon::BlstTsAddon constructor used by Node.js to create an
Expand Down Expand Up @@ -173,5 +181,3 @@ class BlstTsAddon : public Napi::Addon<BlstTsAddon> {
*/
bool GetRandomBytes(blst::byte *ikm, size_t length);
};

#endif /* BLST_TS_ADDON_H__ */
Loading