react-native-quick-crypto 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/QuickCrypto.podspec +19 -52
- package/android/CMakeLists.txt +4 -2
- package/android/build.gradle +1 -1
- package/cpp/cipher/HybridCipher.cpp +20 -3
- package/cpp/cipher/HybridRsaCipher.cpp +20 -1
- package/cpp/ed25519/HybridEdKeyPair.cpp +8 -2
- package/cpp/keys/HybridKeyObjectHandle.cpp +8 -0
- package/cpp/keys/KeyObjectData.hpp +1 -1
- package/cpp/mldsa/HybridMlDsaKeyPair.cpp +264 -0
- package/cpp/mldsa/HybridMlDsaKeyPair.hpp +47 -0
- package/cpp/sign/HybridSignHandle.cpp +97 -22
- package/cpp/sign/HybridVerifyHandle.cpp +90 -21
- package/deps/ncrypto/.bazelignore +4 -0
- package/deps/ncrypto/.bazelrc +2 -0
- package/deps/ncrypto/.bazelversion +1 -0
- package/deps/ncrypto/.clang-format +111 -0
- package/deps/ncrypto/.github/workflows/bazel.yml +58 -0
- package/deps/ncrypto/.github/workflows/linter.yml +38 -0
- package/deps/ncrypto/.github/workflows/macos.yml +43 -0
- package/deps/ncrypto/.github/workflows/ubuntu.yml +46 -0
- package/deps/ncrypto/.github/workflows/visual-studio.yml +49 -0
- package/deps/ncrypto/.python-version +1 -0
- package/deps/ncrypto/BUILD.bazel +36 -0
- package/deps/ncrypto/CMakeLists.txt +55 -0
- package/deps/ncrypto/LICENSE +21 -0
- package/deps/ncrypto/MODULE.bazel +1 -0
- package/deps/ncrypto/MODULE.bazel.lock +280 -0
- package/deps/ncrypto/README.md +18 -0
- package/deps/ncrypto/WORKSPACE +15 -0
- package/deps/ncrypto/cmake/CPM.cmake +1225 -0
- package/deps/ncrypto/cmake/ncrypto-flags.cmake +16 -0
- package/deps/ncrypto/include/dh-primes.h +67 -0
- package/deps/ncrypto/{ncrypto.h → include/ncrypto.h} +361 -89
- package/deps/ncrypto/patches/0001-Expose-libdecrepit-so-NodeJS-can-use-it-for-ncrypto.patch +28 -0
- package/deps/ncrypto/pyproject.toml +38 -0
- package/deps/ncrypto/src/CMakeLists.txt +15 -0
- package/deps/ncrypto/src/engine.cpp +93 -0
- package/deps/ncrypto/{ncrypto.cc → src/ncrypto.cpp} +1168 -234
- package/deps/ncrypto/tests/BUILD.bazel +9 -0
- package/deps/ncrypto/tests/CMakeLists.txt +7 -0
- package/deps/ncrypto/tests/basic.cpp +86 -0
- package/deps/ncrypto/tools/run-clang-format.sh +42 -0
- package/lib/commonjs/ed.js +68 -0
- package/lib/commonjs/ed.js.map +1 -1
- package/lib/commonjs/keys/classes.js +6 -0
- package/lib/commonjs/keys/classes.js.map +1 -1
- package/lib/commonjs/mldsa.js +69 -0
- package/lib/commonjs/mldsa.js.map +1 -0
- package/lib/commonjs/specs/mlDsaKeyPair.nitro.js +6 -0
- package/lib/commonjs/specs/mlDsaKeyPair.nitro.js.map +1 -0
- package/lib/commonjs/subtle.js +483 -13
- package/lib/commonjs/subtle.js.map +1 -1
- package/lib/commonjs/utils/types.js.map +1 -1
- package/lib/module/ed.js +66 -0
- package/lib/module/ed.js.map +1 -1
- package/lib/module/keys/classes.js +6 -0
- package/lib/module/keys/classes.js.map +1 -1
- package/lib/module/mldsa.js +63 -0
- package/lib/module/mldsa.js.map +1 -0
- package/lib/module/specs/mlDsaKeyPair.nitro.js +4 -0
- package/lib/module/specs/mlDsaKeyPair.nitro.js.map +1 -0
- package/lib/module/subtle.js +484 -14
- package/lib/module/subtle.js.map +1 -1
- package/lib/module/utils/types.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/typescript/ed.d.ts +4 -1
- package/lib/typescript/ed.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/keys/classes.d.ts +2 -0
- package/lib/typescript/keys/classes.d.ts.map +1 -1
- package/lib/typescript/mldsa.d.ts +18 -0
- package/lib/typescript/mldsa.d.ts.map +1 -0
- package/lib/typescript/specs/mlDsaKeyPair.nitro.d.ts +16 -0
- package/lib/typescript/specs/mlDsaKeyPair.nitro.d.ts.map +1 -0
- package/lib/typescript/subtle.d.ts +4 -1
- package/lib/typescript/subtle.d.ts.map +1 -1
- package/lib/typescript/utils/types.d.ts +14 -6
- package/lib/typescript/utils/types.d.ts.map +1 -1
- package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +1 -0
- package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +10 -0
- package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +10 -0
- package/nitrogen/generated/shared/c++/AsymmetricKeyType.hpp +12 -0
- package/nitrogen/generated/shared/c++/HybridMlDsaKeyPairSpec.cpp +29 -0
- package/nitrogen/generated/shared/c++/HybridMlDsaKeyPairSpec.hpp +73 -0
- package/package.json +7 -3
- package/src/ed.ts +102 -0
- package/src/keys/classes.ts +9 -0
- package/src/mldsa.ts +125 -0
- package/src/specs/mlDsaKeyPair.nitro.ts +29 -0
- package/src/subtle.ts +667 -17
- package/src/utils/types.ts +27 -6
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
#include <openssl/evp.h>
|
|
10
10
|
#include <openssl/rsa.h>
|
|
11
11
|
|
|
12
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30500000L
|
|
13
|
+
#define RNQC_HAS_ML_DSA 1
|
|
14
|
+
#else
|
|
15
|
+
#define RNQC_HAS_ML_DSA 0
|
|
16
|
+
#endif
|
|
17
|
+
|
|
12
18
|
namespace margelo::nitro::crypto {
|
|
13
19
|
|
|
14
20
|
using margelo::nitro::NativeArrayBuffer;
|
|
@@ -22,17 +28,28 @@ HybridSignHandle::~HybridSignHandle() {
|
|
|
22
28
|
|
|
23
29
|
void HybridSignHandle::init(const std::string& algorithm) {
|
|
24
30
|
algorithm_name = algorithm;
|
|
25
|
-
md = getDigestByName(algorithm);
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
if (!
|
|
29
|
-
|
|
30
|
-
}
|
|
32
|
+
// For ML-DSA and other pure signature schemes, algorithm may be empty/null
|
|
33
|
+
if (!algorithm.empty()) {
|
|
34
|
+
md = getDigestByName(algorithm);
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
md_ctx = EVP_MD_CTX_new();
|
|
37
|
+
if (!md_ctx) {
|
|
38
|
+
throw std::runtime_error("Failed to create message digest context");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (EVP_DigestInit_ex(md_ctx, md, nullptr) <= 0) {
|
|
42
|
+
EVP_MD_CTX_free(md_ctx);
|
|
43
|
+
md_ctx = nullptr;
|
|
44
|
+
throw std::runtime_error("Failed to initialize message digest");
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
// No digest for pure signature schemes like ML-DSA
|
|
48
|
+
md = nullptr;
|
|
49
|
+
md_ctx = EVP_MD_CTX_new();
|
|
50
|
+
if (!md_ctx) {
|
|
51
|
+
throw std::runtime_error("Failed to create message digest context");
|
|
52
|
+
}
|
|
36
53
|
}
|
|
37
54
|
}
|
|
38
55
|
|
|
@@ -43,22 +60,60 @@ void HybridSignHandle::update(const std::shared_ptr<ArrayBuffer>& data) {
|
|
|
43
60
|
|
|
44
61
|
auto native_data = ToNativeArrayBuffer(data);
|
|
45
62
|
|
|
46
|
-
// Accumulate raw data for potential one-shot signing (Ed25519/Ed448)
|
|
63
|
+
// Accumulate raw data for potential one-shot signing (Ed25519/Ed448/ML-DSA)
|
|
47
64
|
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(native_data->data());
|
|
48
65
|
data_buffer.insert(data_buffer.end(), ptr, ptr + native_data->size());
|
|
49
66
|
|
|
50
|
-
if
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
67
|
+
// Only update digest if we have one (not needed for pure signature schemes)
|
|
68
|
+
if (md != nullptr) {
|
|
69
|
+
if (EVP_DigestUpdate(md_ctx, native_data->data(), native_data->size()) <= 0) {
|
|
70
|
+
unsigned long err = ERR_get_error();
|
|
71
|
+
char err_buf[256];
|
|
72
|
+
ERR_error_string_n(err, err_buf, sizeof(err_buf));
|
|
73
|
+
throw std::runtime_error("Failed to update digest: " + std::string(err_buf));
|
|
74
|
+
}
|
|
55
75
|
}
|
|
56
76
|
}
|
|
57
77
|
|
|
58
|
-
// Check if key type requires one-shot signing (Ed25519, Ed448)
|
|
78
|
+
// Check if key type requires one-shot signing (Ed25519, Ed448, ML-DSA)
|
|
59
79
|
static bool isOneShotVariant(EVP_PKEY* pkey) {
|
|
60
80
|
int type = EVP_PKEY_id(pkey);
|
|
81
|
+
#if RNQC_HAS_ML_DSA
|
|
82
|
+
return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448 || type == EVP_PKEY_ML_DSA_44 || type == EVP_PKEY_ML_DSA_65 ||
|
|
83
|
+
type == EVP_PKEY_ML_DSA_87;
|
|
84
|
+
#else
|
|
61
85
|
return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448;
|
|
86
|
+
#endif
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Get the algorithm name for creating PKEY_CTX (for ML-DSA variants)
|
|
90
|
+
static const char* getAlgorithmName(EVP_PKEY* pkey) {
|
|
91
|
+
int type = EVP_PKEY_id(pkey);
|
|
92
|
+
#if RNQC_HAS_ML_DSA
|
|
93
|
+
switch (type) {
|
|
94
|
+
case EVP_PKEY_ML_DSA_44:
|
|
95
|
+
return "ML-DSA-44";
|
|
96
|
+
case EVP_PKEY_ML_DSA_65:
|
|
97
|
+
return "ML-DSA-65";
|
|
98
|
+
case EVP_PKEY_ML_DSA_87:
|
|
99
|
+
return "ML-DSA-87";
|
|
100
|
+
case EVP_PKEY_ED25519:
|
|
101
|
+
return "ED25519";
|
|
102
|
+
case EVP_PKEY_ED448:
|
|
103
|
+
return "ED448";
|
|
104
|
+
default:
|
|
105
|
+
return nullptr;
|
|
106
|
+
}
|
|
107
|
+
#else
|
|
108
|
+
switch (type) {
|
|
109
|
+
case EVP_PKEY_ED25519:
|
|
110
|
+
return "ED25519";
|
|
111
|
+
case EVP_PKEY_ED448:
|
|
112
|
+
return "ED448";
|
|
113
|
+
default:
|
|
114
|
+
return nullptr;
|
|
115
|
+
}
|
|
116
|
+
#endif
|
|
62
117
|
}
|
|
63
118
|
|
|
64
119
|
std::shared_ptr<ArrayBuffer> HybridSignHandle::sign(const std::shared_ptr<HybridKeyObjectHandleSpec>& keyHandle,
|
|
@@ -78,18 +133,35 @@ std::shared_ptr<ArrayBuffer> HybridSignHandle::sign(const std::shared_ptr<Hybrid
|
|
|
78
133
|
size_t sig_len = 0;
|
|
79
134
|
std::unique_ptr<uint8_t[]> sig_buf;
|
|
80
135
|
|
|
81
|
-
|
|
82
|
-
|
|
136
|
+
int pkey_type = EVP_PKEY_id(pkey);
|
|
137
|
+
bool is_one_shot = isOneShotVariant(pkey);
|
|
138
|
+
|
|
139
|
+
// Ed25519/Ed448/ML-DSA require one-shot signing with EVP_DigestSign
|
|
140
|
+
// Also use one-shot path if no digest was specified (md == nullptr)
|
|
141
|
+
if (is_one_shot || md == nullptr) {
|
|
83
142
|
// Create a new context for one-shot signing
|
|
84
143
|
EVP_MD_CTX* sign_ctx = EVP_MD_CTX_new();
|
|
85
144
|
if (!sign_ctx) {
|
|
86
145
|
throw std::runtime_error("Failed to create signing context");
|
|
87
146
|
}
|
|
88
147
|
|
|
89
|
-
//
|
|
90
|
-
|
|
148
|
+
// Get algorithm name and create PKEY_CTX for ML-DSA
|
|
149
|
+
const char* alg_name = getAlgorithmName(pkey);
|
|
150
|
+
EVP_PKEY_CTX* pkey_ctx = nullptr;
|
|
151
|
+
if (alg_name != nullptr) {
|
|
152
|
+
pkey_ctx = EVP_PKEY_CTX_new_from_name(nullptr, alg_name, nullptr);
|
|
153
|
+
if (!pkey_ctx) {
|
|
154
|
+
EVP_MD_CTX_free(sign_ctx);
|
|
155
|
+
throw std::runtime_error(std::string("Failed to create signing context for ") + alg_name);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Initialize for one-shot signing (pass nullptr for md - these algorithms have built-in hash)
|
|
160
|
+
if (EVP_DigestSignInit(sign_ctx, pkey_ctx ? &pkey_ctx : nullptr, nullptr, nullptr, pkey) <= 0) {
|
|
91
161
|
EVP_MD_CTX_free(sign_ctx);
|
|
92
|
-
|
|
162
|
+
if (pkey_ctx)
|
|
163
|
+
EVP_PKEY_CTX_free(pkey_ctx);
|
|
164
|
+
throw std::runtime_error("Failed to initialize one-shot signing");
|
|
93
165
|
}
|
|
94
166
|
|
|
95
167
|
// Get the accumulated data from the digest context
|
|
@@ -130,7 +202,10 @@ std::shared_ptr<ArrayBuffer> HybridSignHandle::sign(const std::shared_ptr<Hybrid
|
|
|
130
202
|
|
|
131
203
|
if (EVP_PKEY_sign_init(pkey_ctx) <= 0) {
|
|
132
204
|
EVP_PKEY_CTX_free(pkey_ctx);
|
|
133
|
-
|
|
205
|
+
char err_buf[512];
|
|
206
|
+
snprintf(err_buf, sizeof(err_buf), "Failed to initialize signing for key type %d (expected one-shot: %s, RNQC_HAS_ML_DSA=%d)",
|
|
207
|
+
pkey_type, is_one_shot ? "true" : "false", RNQC_HAS_ML_DSA);
|
|
208
|
+
throw std::runtime_error(std::string(err_buf) + ": " + getOpenSSLError());
|
|
134
209
|
}
|
|
135
210
|
|
|
136
211
|
if (padding.has_value()) {
|
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
#include <openssl/evp.h>
|
|
10
10
|
#include <openssl/rsa.h>
|
|
11
11
|
|
|
12
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30500000L
|
|
13
|
+
#define RNQC_HAS_ML_DSA 1
|
|
14
|
+
#else
|
|
15
|
+
#define RNQC_HAS_ML_DSA 0
|
|
16
|
+
#endif
|
|
17
|
+
|
|
12
18
|
namespace margelo::nitro::crypto {
|
|
13
19
|
|
|
14
20
|
using margelo::nitro::NativeArrayBuffer;
|
|
@@ -22,17 +28,28 @@ HybridVerifyHandle::~HybridVerifyHandle() {
|
|
|
22
28
|
|
|
23
29
|
void HybridVerifyHandle::init(const std::string& algorithm) {
|
|
24
30
|
algorithm_name = algorithm;
|
|
25
|
-
md = getDigestByName(algorithm);
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
if (!
|
|
29
|
-
|
|
30
|
-
}
|
|
32
|
+
// For ML-DSA and other pure signature schemes, algorithm may be empty/null
|
|
33
|
+
if (!algorithm.empty()) {
|
|
34
|
+
md = getDigestByName(algorithm);
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
md_ctx = EVP_MD_CTX_new();
|
|
37
|
+
if (!md_ctx) {
|
|
38
|
+
throw std::runtime_error("Failed to create message digest context");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (EVP_DigestInit_ex(md_ctx, md, nullptr) <= 0) {
|
|
42
|
+
EVP_MD_CTX_free(md_ctx);
|
|
43
|
+
md_ctx = nullptr;
|
|
44
|
+
throw std::runtime_error("Failed to initialize message digest");
|
|
45
|
+
}
|
|
46
|
+
} else {
|
|
47
|
+
// No digest for pure signature schemes like ML-DSA
|
|
48
|
+
md = nullptr;
|
|
49
|
+
md_ctx = EVP_MD_CTX_new();
|
|
50
|
+
if (!md_ctx) {
|
|
51
|
+
throw std::runtime_error("Failed to create message digest context");
|
|
52
|
+
}
|
|
36
53
|
}
|
|
37
54
|
}
|
|
38
55
|
|
|
@@ -43,22 +60,60 @@ void HybridVerifyHandle::update(const std::shared_ptr<ArrayBuffer>& data) {
|
|
|
43
60
|
|
|
44
61
|
auto native_data = ToNativeArrayBuffer(data);
|
|
45
62
|
|
|
46
|
-
// Accumulate raw data for potential one-shot verification (Ed25519/Ed448)
|
|
63
|
+
// Accumulate raw data for potential one-shot verification (Ed25519/Ed448/ML-DSA)
|
|
47
64
|
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(native_data->data());
|
|
48
65
|
data_buffer.insert(data_buffer.end(), ptr, ptr + native_data->size());
|
|
49
66
|
|
|
50
|
-
if
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
67
|
+
// Only update digest if we have one (not needed for pure signature schemes)
|
|
68
|
+
if (md != nullptr) {
|
|
69
|
+
if (EVP_DigestUpdate(md_ctx, native_data->data(), native_data->size()) <= 0) {
|
|
70
|
+
unsigned long err = ERR_get_error();
|
|
71
|
+
char err_buf[256];
|
|
72
|
+
ERR_error_string_n(err, err_buf, sizeof(err_buf));
|
|
73
|
+
throw std::runtime_error("Failed to update digest: " + std::string(err_buf));
|
|
74
|
+
}
|
|
55
75
|
}
|
|
56
76
|
}
|
|
57
77
|
|
|
58
|
-
// Check if key type requires one-shot verification (Ed25519, Ed448)
|
|
78
|
+
// Check if key type requires one-shot verification (Ed25519, Ed448, ML-DSA)
|
|
59
79
|
static bool isOneShotVariant(EVP_PKEY* pkey) {
|
|
60
80
|
int type = EVP_PKEY_id(pkey);
|
|
81
|
+
#if RNQC_HAS_ML_DSA
|
|
82
|
+
return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448 || type == EVP_PKEY_ML_DSA_44 || type == EVP_PKEY_ML_DSA_65 ||
|
|
83
|
+
type == EVP_PKEY_ML_DSA_87;
|
|
84
|
+
#else
|
|
61
85
|
return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448;
|
|
86
|
+
#endif
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Get the algorithm name for creating PKEY_CTX (for ML-DSA variants)
|
|
90
|
+
static const char* getAlgorithmName(EVP_PKEY* pkey) {
|
|
91
|
+
int type = EVP_PKEY_id(pkey);
|
|
92
|
+
#if RNQC_HAS_ML_DSA
|
|
93
|
+
switch (type) {
|
|
94
|
+
case EVP_PKEY_ML_DSA_44:
|
|
95
|
+
return "ML-DSA-44";
|
|
96
|
+
case EVP_PKEY_ML_DSA_65:
|
|
97
|
+
return "ML-DSA-65";
|
|
98
|
+
case EVP_PKEY_ML_DSA_87:
|
|
99
|
+
return "ML-DSA-87";
|
|
100
|
+
case EVP_PKEY_ED25519:
|
|
101
|
+
return "ED25519";
|
|
102
|
+
case EVP_PKEY_ED448:
|
|
103
|
+
return "ED448";
|
|
104
|
+
default:
|
|
105
|
+
return nullptr;
|
|
106
|
+
}
|
|
107
|
+
#else
|
|
108
|
+
switch (type) {
|
|
109
|
+
case EVP_PKEY_ED25519:
|
|
110
|
+
return "ED25519";
|
|
111
|
+
case EVP_PKEY_ED448:
|
|
112
|
+
return "ED448";
|
|
113
|
+
default:
|
|
114
|
+
return nullptr;
|
|
115
|
+
}
|
|
116
|
+
#endif
|
|
62
117
|
}
|
|
63
118
|
|
|
64
119
|
bool HybridVerifyHandle::verify(const std::shared_ptr<HybridKeyObjectHandleSpec>& keyHandle, const std::shared_ptr<ArrayBuffer>& signature,
|
|
@@ -78,17 +133,31 @@ bool HybridVerifyHandle::verify(const std::shared_ptr<HybridKeyObjectHandleSpec>
|
|
|
78
133
|
const unsigned char* sig_data = native_sig->data();
|
|
79
134
|
size_t sig_len = native_sig->size();
|
|
80
135
|
|
|
81
|
-
// Ed25519/Ed448 require one-shot verification with EVP_DigestVerify
|
|
82
|
-
if (
|
|
136
|
+
// Ed25519/Ed448/ML-DSA require one-shot verification with EVP_DigestVerify
|
|
137
|
+
// Also use one-shot path if no digest was specified (md == nullptr)
|
|
138
|
+
if (isOneShotVariant(pkey) || md == nullptr) {
|
|
83
139
|
EVP_MD_CTX* verify_ctx = EVP_MD_CTX_new();
|
|
84
140
|
if (!verify_ctx) {
|
|
85
141
|
throw std::runtime_error("Failed to create verification context");
|
|
86
142
|
}
|
|
87
143
|
|
|
88
|
-
//
|
|
89
|
-
|
|
144
|
+
// Get algorithm name and create PKEY_CTX for ML-DSA
|
|
145
|
+
const char* alg_name = getAlgorithmName(pkey);
|
|
146
|
+
EVP_PKEY_CTX* pkey_ctx = nullptr;
|
|
147
|
+
if (alg_name != nullptr) {
|
|
148
|
+
pkey_ctx = EVP_PKEY_CTX_new_from_name(nullptr, alg_name, nullptr);
|
|
149
|
+
if (!pkey_ctx) {
|
|
150
|
+
EVP_MD_CTX_free(verify_ctx);
|
|
151
|
+
throw std::runtime_error(std::string("Failed to create verification context for ") + alg_name);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Initialize for one-shot verification (pass nullptr for md - these algorithms have built-in hash)
|
|
156
|
+
if (EVP_DigestVerifyInit(verify_ctx, pkey_ctx ? &pkey_ctx : nullptr, nullptr, nullptr, pkey) <= 0) {
|
|
90
157
|
EVP_MD_CTX_free(verify_ctx);
|
|
91
|
-
|
|
158
|
+
if (pkey_ctx)
|
|
159
|
+
EVP_PKEY_CTX_free(pkey_ctx);
|
|
160
|
+
throw std::runtime_error("Failed to initialize one-shot verification");
|
|
92
161
|
}
|
|
93
162
|
|
|
94
163
|
int result = EVP_DigestVerify(verify_ctx, sig_data, sig_len, data_buffer.data(), data_buffer.size());
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
8.0.0
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
Language: Cpp
|
|
3
|
+
# BasedOnStyle: Google
|
|
4
|
+
AccessModifierOffset: -1
|
|
5
|
+
AlignAfterOpenBracket: Align
|
|
6
|
+
AlignConsecutiveAssignments: false
|
|
7
|
+
AlignConsecutiveDeclarations: false
|
|
8
|
+
AlignEscapedNewlines: Right
|
|
9
|
+
AlignOperands: true
|
|
10
|
+
AlignTrailingComments: true
|
|
11
|
+
AllowAllParametersOfDeclarationOnNextLine: true
|
|
12
|
+
AllowShortBlocksOnASingleLine: false
|
|
13
|
+
AllowShortCaseLabelsOnASingleLine: false
|
|
14
|
+
AllowShortFunctionsOnASingleLine: Inline
|
|
15
|
+
AllowShortIfStatementsOnASingleLine: true
|
|
16
|
+
AllowShortLoopsOnASingleLine: true
|
|
17
|
+
AlwaysBreakAfterDefinitionReturnType: None
|
|
18
|
+
AlwaysBreakAfterReturnType: None
|
|
19
|
+
AlwaysBreakBeforeMultilineStrings: false
|
|
20
|
+
AlwaysBreakTemplateDeclarations: true
|
|
21
|
+
BinPackArguments: false
|
|
22
|
+
BinPackParameters: false
|
|
23
|
+
BraceWrapping:
|
|
24
|
+
AfterClass: false
|
|
25
|
+
AfterControlStatement: false
|
|
26
|
+
AfterEnum: false
|
|
27
|
+
AfterFunction: false
|
|
28
|
+
AfterNamespace: false
|
|
29
|
+
AfterObjCDeclaration: false
|
|
30
|
+
AfterStruct: false
|
|
31
|
+
AfterUnion: false
|
|
32
|
+
AfterExternBlock: false
|
|
33
|
+
BeforeCatch: false
|
|
34
|
+
BeforeElse: false
|
|
35
|
+
IndentBraces: false
|
|
36
|
+
SplitEmptyFunction: true
|
|
37
|
+
SplitEmptyRecord: true
|
|
38
|
+
SplitEmptyNamespace: true
|
|
39
|
+
BreakBeforeBinaryOperators: None
|
|
40
|
+
BreakBeforeBraces: Attach
|
|
41
|
+
BreakBeforeInheritanceComma: false
|
|
42
|
+
BreakBeforeTernaryOperators: true
|
|
43
|
+
BreakConstructorInitializersBeforeComma: false
|
|
44
|
+
BreakConstructorInitializers: BeforeColon
|
|
45
|
+
BreakAfterJavaFieldAnnotations: false
|
|
46
|
+
BreakStringLiterals: true
|
|
47
|
+
ColumnLimit: 80
|
|
48
|
+
CommentPragmas: '^ IWYU pragma:'
|
|
49
|
+
CompactNamespaces: false
|
|
50
|
+
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
|
51
|
+
ConstructorInitializerIndentWidth: 4
|
|
52
|
+
ContinuationIndentWidth: 4
|
|
53
|
+
Cpp11BracedListStyle: true
|
|
54
|
+
DerivePointerAlignment: false
|
|
55
|
+
DisableFormat: false
|
|
56
|
+
ExperimentalAutoDetectBinPacking: false
|
|
57
|
+
FixNamespaceComments: true
|
|
58
|
+
ForEachMacros:
|
|
59
|
+
- foreach
|
|
60
|
+
- Q_FOREACH
|
|
61
|
+
- BOOST_FOREACH
|
|
62
|
+
IncludeBlocks: Preserve
|
|
63
|
+
IncludeCategories:
|
|
64
|
+
- Regex: '^<ext/.*\.h>'
|
|
65
|
+
Priority: 2
|
|
66
|
+
- Regex: '^<.*\.h>'
|
|
67
|
+
Priority: 1
|
|
68
|
+
- Regex: '^<.*'
|
|
69
|
+
Priority: 2
|
|
70
|
+
- Regex: '.*'
|
|
71
|
+
Priority: 3
|
|
72
|
+
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
|
73
|
+
IndentCaseLabels: true
|
|
74
|
+
IndentPPDirectives: None
|
|
75
|
+
IndentWidth: 2
|
|
76
|
+
IndentWrappedFunctionNames: false
|
|
77
|
+
JavaScriptQuotes: Leave
|
|
78
|
+
JavaScriptWrapImports: true
|
|
79
|
+
KeepEmptyLinesAtTheStartOfBlocks: false
|
|
80
|
+
MacroBlockBegin: ''
|
|
81
|
+
MacroBlockEnd: ''
|
|
82
|
+
MaxEmptyLinesToKeep: 1
|
|
83
|
+
NamespaceIndentation: None
|
|
84
|
+
ObjCBlockIndentWidth: 2
|
|
85
|
+
ObjCSpaceAfterProperty: false
|
|
86
|
+
ObjCSpaceBeforeProtocolList: false
|
|
87
|
+
PenaltyBreakAssignment: 2
|
|
88
|
+
PenaltyBreakBeforeFirstCallParameter: 1
|
|
89
|
+
PenaltyBreakComment: 300
|
|
90
|
+
PenaltyBreakFirstLessLess: 120
|
|
91
|
+
PenaltyBreakString: 1000
|
|
92
|
+
PenaltyExcessCharacter: 1000000
|
|
93
|
+
PenaltyReturnTypeOnItsOwnLine: 200
|
|
94
|
+
PointerAlignment: Left
|
|
95
|
+
ReflowComments: true
|
|
96
|
+
SortIncludes: true
|
|
97
|
+
SortUsingDeclarations: true
|
|
98
|
+
SpaceAfterCStyleCast: false
|
|
99
|
+
SpaceAfterTemplateKeyword: true
|
|
100
|
+
SpaceBeforeAssignmentOperators: true
|
|
101
|
+
SpaceBeforeParens: ControlStatements
|
|
102
|
+
SpaceInEmptyParentheses: false
|
|
103
|
+
SpacesBeforeTrailingComments: 2
|
|
104
|
+
SpacesInAngles: false
|
|
105
|
+
SpacesInContainerLiterals: true
|
|
106
|
+
SpacesInCStyleCastParentheses: false
|
|
107
|
+
SpacesInParentheses: false
|
|
108
|
+
SpacesInSquareBrackets: false
|
|
109
|
+
Standard: Auto
|
|
110
|
+
TabWidth: 8
|
|
111
|
+
UseTab: Never
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
name: Bazel
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, reopened, ready_for_review]
|
|
6
|
+
paths-ignore:
|
|
7
|
+
- '**.md'
|
|
8
|
+
- 'docs/**'
|
|
9
|
+
push:
|
|
10
|
+
branches:
|
|
11
|
+
- main
|
|
12
|
+
paths-ignore:
|
|
13
|
+
- '**.md'
|
|
14
|
+
- 'docs/**'
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
actions: write
|
|
19
|
+
|
|
20
|
+
concurrency:
|
|
21
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
22
|
+
cancel-in-progress: true
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
macos:
|
|
26
|
+
runs-on: macos-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
29
|
+
- uses: bazel-contrib/setup-bazel@bbf8fe8b219f642c7f8bc673215f28eb1d9dec51 # v0.10.0
|
|
30
|
+
with:
|
|
31
|
+
bazelisk-cache: true
|
|
32
|
+
disk-cache: ${{ github.workflow }}
|
|
33
|
+
repository-cache: true
|
|
34
|
+
- name: Build & Test
|
|
35
|
+
run: bazel test //...
|
|
36
|
+
ubuntu:
|
|
37
|
+
strategy:
|
|
38
|
+
fail-fast: false
|
|
39
|
+
matrix:
|
|
40
|
+
shared: [ON, OFF]
|
|
41
|
+
include:
|
|
42
|
+
- cc: gcc-14
|
|
43
|
+
cxx: g++-14
|
|
44
|
+
- cc: clang-18
|
|
45
|
+
cxx: clang++-18
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
|
49
|
+
- uses: bazel-contrib/setup-bazel@bbf8fe8b219f642c7f8bc673215f28eb1d9dec51 # v0.10.0
|
|
50
|
+
with:
|
|
51
|
+
bazelisk-cache: true
|
|
52
|
+
disk-cache: ${{ github.workflow }}
|
|
53
|
+
repository-cache: true
|
|
54
|
+
- name: Build & Test
|
|
55
|
+
run: bazel test //...
|
|
56
|
+
env:
|
|
57
|
+
CC: ${{matrix.cc}}
|
|
58
|
+
CXX: ${{matrix.cxx}}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: Linter
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, reopened, ready_for_review]
|
|
6
|
+
paths-ignore:
|
|
7
|
+
- '**.md'
|
|
8
|
+
- 'docs/**'
|
|
9
|
+
push:
|
|
10
|
+
branches:
|
|
11
|
+
- main
|
|
12
|
+
paths-ignore:
|
|
13
|
+
- '**.md'
|
|
14
|
+
- 'docs/**'
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
concurrency:
|
|
20
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
21
|
+
cancel-in-progress: true
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
lint:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
|
28
|
+
|
|
29
|
+
- name: Run clang-format
|
|
30
|
+
uses: jidicula/clang-format-action@c74383674bf5f7c69f60ce562019c1c94bc1421a # v4.13.0
|
|
31
|
+
with:
|
|
32
|
+
clang-format-version: '17'
|
|
33
|
+
fallback-style: 'Google'
|
|
34
|
+
|
|
35
|
+
- uses: chartboost/ruff-action@e18ae971ccee1b2d7bbef113930f00c670b78da4 # v1.0.0
|
|
36
|
+
name: Lint with Ruff
|
|
37
|
+
with:
|
|
38
|
+
version: 0.5.1
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: macOS
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, reopened, ready_for_review]
|
|
6
|
+
paths-ignore:
|
|
7
|
+
- '**.md'
|
|
8
|
+
- 'docs/**'
|
|
9
|
+
push:
|
|
10
|
+
branches:
|
|
11
|
+
- main
|
|
12
|
+
paths-ignore:
|
|
13
|
+
- '**.md'
|
|
14
|
+
- 'docs/**'
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
concurrency:
|
|
20
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
21
|
+
cancel-in-progress: true
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
ubuntu-build:
|
|
25
|
+
strategy:
|
|
26
|
+
fail-fast: false
|
|
27
|
+
matrix:
|
|
28
|
+
runs-on: [macos-14, macos-15]
|
|
29
|
+
runs-on: ${{matrix.runs-on}}
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
|
32
|
+
- name: ccache
|
|
33
|
+
uses: hendrikmuhs/ccache-action@v1.2
|
|
34
|
+
with:
|
|
35
|
+
key: ${{github.job}}-${{matrix.os}}
|
|
36
|
+
- name: Prepare
|
|
37
|
+
run: cmake -B build
|
|
38
|
+
- name: Build
|
|
39
|
+
# m1 machines have 3 CPU
|
|
40
|
+
# Ref: https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners
|
|
41
|
+
run: cmake --build build -j=3
|
|
42
|
+
- name: Test
|
|
43
|
+
run: ctest --output-on-failure --test-dir build
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Ubuntu
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, reopened, ready_for_review]
|
|
6
|
+
paths-ignore:
|
|
7
|
+
- '**.md'
|
|
8
|
+
- 'docs/**'
|
|
9
|
+
push:
|
|
10
|
+
branches:
|
|
11
|
+
- main
|
|
12
|
+
paths-ignore:
|
|
13
|
+
- '**.md'
|
|
14
|
+
- 'docs/**'
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
concurrency:
|
|
20
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
21
|
+
cancel-in-progress: true
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
build:
|
|
25
|
+
strategy:
|
|
26
|
+
matrix:
|
|
27
|
+
runs-on: [ubuntu-latest]
|
|
28
|
+
shared: [ON, OFF]
|
|
29
|
+
cxx: [g++-14]
|
|
30
|
+
runs-on: ${{matrix.runs-on}}
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
|
33
|
+
- name: ccache
|
|
34
|
+
uses: hendrikmuhs/ccache-action@v1.2
|
|
35
|
+
with:
|
|
36
|
+
key: ${{github.job}}-${{matrix.os}}-{{matrix.shared}}
|
|
37
|
+
- name: Setup Ninja
|
|
38
|
+
run: sudo apt-get install ninja-build
|
|
39
|
+
- name: Prepare
|
|
40
|
+
run: cmake -DBUILD_SHARED_LIBS=${{matrix.shared}} -G Ninja -B build
|
|
41
|
+
env:
|
|
42
|
+
CXX: ${{matrix.cxx}}
|
|
43
|
+
- name: Build
|
|
44
|
+
run: cmake --build build -j=4
|
|
45
|
+
- name: Test
|
|
46
|
+
run: ctest --output-on-failure --test-dir build
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Windows
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, reopened, ready_for_review]
|
|
6
|
+
paths-ignore:
|
|
7
|
+
- '**.md'
|
|
8
|
+
- 'docs/**'
|
|
9
|
+
push:
|
|
10
|
+
branches:
|
|
11
|
+
- main
|
|
12
|
+
paths-ignore:
|
|
13
|
+
- '**.md'
|
|
14
|
+
- 'docs/**'
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
concurrency:
|
|
20
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
21
|
+
cancel-in-progress: true
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
build:
|
|
25
|
+
runs-on: windows-2025
|
|
26
|
+
strategy:
|
|
27
|
+
fail-fast: false
|
|
28
|
+
matrix:
|
|
29
|
+
include:
|
|
30
|
+
- {gen: Visual Studio 17 2022, arch: x64, config: Release}
|
|
31
|
+
- {gen: Visual Studio 17 2022, arch: x64, config: Debug}
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
|
|
34
|
+
- name: ccache
|
|
35
|
+
uses: hendrikmuhs/ccache-action@v1.2
|
|
36
|
+
with:
|
|
37
|
+
key: ${{github.job}}-${{matrix.os}}-${{matrix.config}}
|
|
38
|
+
- name: Install Dependencies
|
|
39
|
+
run: |
|
|
40
|
+
choco install nasm
|
|
41
|
+
echo "C:\Program Files\NASM" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
|
42
|
+
- name: Configure
|
|
43
|
+
run: |
|
|
44
|
+
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -B build
|
|
45
|
+
- name: Build
|
|
46
|
+
run: cmake --build build --config "${{matrix.config}}" --verbose
|
|
47
|
+
- name: Run tests
|
|
48
|
+
working-directory: build
|
|
49
|
+
run: ctest -C "${{matrix.config}}" --output-on-failure
|