react-native-quick-crypto 1.0.11 → 1.0.13
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/android/CMakeLists.txt +7 -0
- package/cpp/cipher/CCMCipher.cpp +4 -1
- package/cpp/cipher/ChaCha20Cipher.cpp +3 -1
- package/cpp/cipher/ChaCha20Poly1305Cipher.cpp +5 -5
- package/cpp/cipher/ChaCha20Poly1305Cipher.hpp +1 -2
- package/cpp/cipher/HybridCipher.cpp +10 -1
- package/cpp/cipher/HybridCipher.hpp +2 -0
- package/cpp/cipher/HybridRsaCipher.cpp +0 -13
- package/cpp/cipher/XChaCha20Poly1305Cipher.cpp +7 -5
- package/cpp/cipher/XChaCha20Poly1305Cipher.hpp +1 -2
- package/cpp/cipher/XSalsa20Cipher.cpp +4 -0
- package/cpp/cipher/XSalsa20Poly1305Cipher.cpp +7 -5
- package/cpp/cipher/XSalsa20Poly1305Cipher.hpp +1 -2
- package/cpp/ecdh/HybridECDH.cpp +20 -133
- package/cpp/keys/HybridKeyObjectHandle.cpp +144 -141
- package/cpp/keys/HybridKeyObjectHandle.hpp +6 -3
- package/cpp/keys/KeyObjectData.hpp +2 -0
- package/cpp/kmac/HybridKmac.cpp +83 -0
- package/cpp/kmac/HybridKmac.hpp +31 -0
- package/cpp/mldsa/HybridMlDsaKeyPair.cpp +11 -20
- package/cpp/mldsa/HybridMlDsaKeyPair.hpp +4 -2
- package/cpp/mlkem/HybridMlKemKeyPair.cpp +319 -0
- package/cpp/mlkem/HybridMlKemKeyPair.hpp +48 -0
- package/cpp/sign/SignUtils.hpp +9 -26
- package/cpp/utils/QuickCryptoUtils.cpp +44 -0
- package/cpp/utils/QuickCryptoUtils.hpp +39 -0
- package/cpp/x509/HybridX509Certificate.cpp +174 -0
- package/cpp/x509/HybridX509Certificate.hpp +51 -0
- package/lib/commonjs/cipher.js +15 -2
- package/lib/commonjs/cipher.js.map +1 -1
- package/lib/commonjs/dhKeyPair.js +3 -3
- package/lib/commonjs/dhKeyPair.js.map +1 -1
- package/lib/commonjs/dsa.js +3 -3
- package/lib/commonjs/dsa.js.map +1 -1
- package/lib/commonjs/ec.js +18 -18
- package/lib/commonjs/ec.js.map +1 -1
- package/lib/commonjs/ed.js +9 -9
- package/lib/commonjs/ed.js.map +1 -1
- package/lib/commonjs/hash.js +17 -12
- package/lib/commonjs/hash.js.map +1 -1
- package/lib/commonjs/hkdf.js.map +1 -1
- package/lib/commonjs/index.js +22 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/keys/classes.js +2 -2
- package/lib/commonjs/keys/classes.js.map +1 -1
- package/lib/commonjs/keys/index.js +24 -0
- package/lib/commonjs/keys/index.js.map +1 -1
- package/lib/commonjs/keys/publicCipher.js +2 -2
- package/lib/commonjs/keys/publicCipher.js.map +1 -1
- package/lib/commonjs/keys/signVerify.js +0 -2
- package/lib/commonjs/keys/signVerify.js.map +1 -1
- package/lib/commonjs/mlkem.js +219 -0
- package/lib/commonjs/mlkem.js.map +1 -0
- package/lib/commonjs/pbkdf2.js +18 -1
- package/lib/commonjs/pbkdf2.js.map +1 -1
- package/lib/commonjs/rsa.js +7 -7
- package/lib/commonjs/rsa.js.map +1 -1
- package/lib/commonjs/specs/kmac.nitro.js +6 -0
- package/lib/commonjs/specs/kmac.nitro.js.map +1 -0
- package/lib/commonjs/specs/mlKemKeyPair.nitro.js +6 -0
- package/lib/commonjs/specs/mlKemKeyPair.nitro.js.map +1 -0
- package/lib/commonjs/specs/x509certificate.nitro.js +6 -0
- package/lib/commonjs/specs/x509certificate.nitro.js.map +1 -0
- package/lib/commonjs/subtle.js +292 -112
- package/lib/commonjs/subtle.js.map +1 -1
- package/lib/commonjs/utils/conversion.js +3 -3
- package/lib/commonjs/utils/conversion.js.map +1 -1
- package/lib/commonjs/utils/hashnames.js +31 -0
- package/lib/commonjs/utils/hashnames.js.map +1 -1
- package/lib/commonjs/utils/types.js.map +1 -1
- package/lib/commonjs/x509certificate.js +189 -0
- package/lib/commonjs/x509certificate.js.map +1 -0
- package/lib/module/cipher.js +16 -3
- package/lib/module/cipher.js.map +1 -1
- package/lib/module/dhKeyPair.js +1 -1
- package/lib/module/dhKeyPair.js.map +1 -1
- package/lib/module/dsa.js +1 -1
- package/lib/module/dsa.js.map +1 -1
- package/lib/module/ec.js +6 -6
- package/lib/module/ec.js.map +1 -1
- package/lib/module/ed.js +1 -1
- package/lib/module/ed.js.map +1 -1
- package/lib/module/hash.js +17 -12
- package/lib/module/hash.js.map +1 -1
- package/lib/module/hkdf.js.map +1 -1
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/keys/classes.js +2 -2
- package/lib/module/keys/classes.js.map +1 -1
- package/lib/module/keys/index.js +25 -1
- package/lib/module/keys/index.js.map +1 -1
- package/lib/module/keys/publicCipher.js +2 -2
- package/lib/module/keys/publicCipher.js.map +1 -1
- package/lib/module/keys/signVerify.js +0 -2
- package/lib/module/keys/signVerify.js.map +1 -1
- package/lib/module/mlkem.js +211 -0
- package/lib/module/mlkem.js.map +1 -0
- package/lib/module/pbkdf2.js +18 -1
- package/lib/module/pbkdf2.js.map +1 -1
- package/lib/module/rsa.js +1 -1
- package/lib/module/rsa.js.map +1 -1
- package/lib/module/specs/kmac.nitro.js +4 -0
- package/lib/module/specs/kmac.nitro.js.map +1 -0
- package/lib/module/specs/mlKemKeyPair.nitro.js +4 -0
- package/lib/module/specs/mlKemKeyPair.nitro.js.map +1 -0
- package/lib/module/specs/x509certificate.nitro.js +4 -0
- package/lib/module/specs/x509certificate.nitro.js.map +1 -0
- package/lib/module/subtle.js +292 -112
- package/lib/module/subtle.js.map +1 -1
- package/lib/module/utils/conversion.js +3 -4
- package/lib/module/utils/conversion.js.map +1 -1
- package/lib/module/utils/hashnames.js +31 -0
- package/lib/module/utils/hashnames.js.map +1 -1
- package/lib/module/utils/types.js.map +1 -1
- package/lib/module/x509certificate.js +184 -0
- package/lib/module/x509certificate.js.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/typescript/cipher.d.ts +3 -0
- package/lib/typescript/cipher.d.ts.map +1 -1
- package/lib/typescript/dhKeyPair.d.ts +1 -1
- package/lib/typescript/dhKeyPair.d.ts.map +1 -1
- package/lib/typescript/dsa.d.ts +1 -1
- package/lib/typescript/dsa.d.ts.map +1 -1
- package/lib/typescript/ec.d.ts +1 -1
- package/lib/typescript/ec.d.ts.map +1 -1
- package/lib/typescript/ed.d.ts +1 -1
- package/lib/typescript/ed.d.ts.map +1 -1
- package/lib/typescript/hash.d.ts.map +1 -1
- package/lib/typescript/hkdf.d.ts +2 -6
- package/lib/typescript/hkdf.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +15 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/keys/classes.d.ts +5 -5
- package/lib/typescript/keys/classes.d.ts.map +1 -1
- package/lib/typescript/keys/index.d.ts +2 -2
- package/lib/typescript/keys/index.d.ts.map +1 -1
- package/lib/typescript/keys/signVerify.d.ts.map +1 -1
- package/lib/typescript/mlkem.d.ts +30 -0
- package/lib/typescript/mlkem.d.ts.map +1 -0
- package/lib/typescript/pbkdf2.d.ts +2 -2
- package/lib/typescript/pbkdf2.d.ts.map +1 -1
- package/lib/typescript/rsa.d.ts +1 -1
- package/lib/typescript/rsa.d.ts.map +1 -1
- package/lib/typescript/specs/keyObjectHandle.nitro.d.ts +1 -0
- package/lib/typescript/specs/keyObjectHandle.nitro.d.ts.map +1 -1
- package/lib/typescript/specs/kmac.nitro.d.ts +10 -0
- package/lib/typescript/specs/kmac.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/mlKemKeyPair.nitro.d.ts +18 -0
- package/lib/typescript/specs/mlKemKeyPair.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/x509certificate.nitro.d.ts +34 -0
- package/lib/typescript/specs/x509certificate.nitro.d.ts.map +1 -0
- package/lib/typescript/subtle.d.ts +10 -0
- package/lib/typescript/subtle.d.ts.map +1 -1
- package/lib/typescript/utils/conversion.d.ts.map +1 -1
- package/lib/typescript/utils/hashnames.d.ts +1 -1
- package/lib/typescript/utils/hashnames.d.ts.map +1 -1
- package/lib/typescript/utils/types.d.ts +13 -7
- package/lib/typescript/utils/types.d.ts.map +1 -1
- package/lib/typescript/x509certificate.d.ts +64 -0
- package/lib/typescript/x509certificate.d.ts.map +1 -0
- package/nitrogen/generated/android/QuickCrypto+autolinking.cmake +3 -0
- package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +30 -0
- package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +30 -0
- package/nitrogen/generated/shared/c++/AsymmetricKeyType.hpp +12 -0
- package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridKeyObjectHandleSpec.hpp +1 -0
- package/nitrogen/generated/shared/c++/HybridKmacSpec.cpp +23 -0
- package/nitrogen/generated/shared/c++/HybridKmacSpec.hpp +66 -0
- package/nitrogen/generated/shared/c++/HybridMlKemKeyPairSpec.cpp +31 -0
- package/nitrogen/generated/shared/c++/HybridMlKemKeyPairSpec.hpp +74 -0
- package/nitrogen/generated/shared/c++/HybridX509CertificateHandleSpec.cpp +46 -0
- package/nitrogen/generated/shared/c++/HybridX509CertificateHandleSpec.hpp +96 -0
- package/package.json +4 -1
- package/src/cipher.ts +17 -3
- package/src/dhKeyPair.ts +1 -1
- package/src/dsa.ts +1 -1
- package/src/ec.ts +9 -9
- package/src/ed.ts +2 -2
- package/src/hash.ts +34 -11
- package/src/hkdf.ts +2 -7
- package/src/index.ts +7 -0
- package/src/keys/classes.ts +10 -9
- package/src/keys/index.ts +37 -2
- package/src/keys/publicCipher.ts +2 -2
- package/src/keys/signVerify.ts +0 -5
- package/src/mlkem.ts +350 -0
- package/src/pbkdf2.ts +34 -5
- package/src/rsa.ts +1 -1
- package/src/specs/keyObjectHandle.nitro.ts +5 -0
- package/src/specs/kmac.nitro.ts +12 -0
- package/src/specs/mlKemKeyPair.nitro.ts +32 -0
- package/src/specs/x509certificate.nitro.ts +38 -0
- package/src/subtle.ts +551 -125
- package/src/utils/conversion.ts +10 -4
- package/src/utils/hashnames.ts +33 -2
- package/src/utils/types.ts +42 -5
- package/src/x509certificate.ts +277 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
#include "HybridMlKemKeyPair.hpp"
|
|
2
|
+
|
|
3
|
+
#include <NitroModules/ArrayBuffer.hpp>
|
|
4
|
+
#include <openssl/bio.h>
|
|
5
|
+
#include <openssl/err.h>
|
|
6
|
+
#include <openssl/pem.h>
|
|
7
|
+
|
|
8
|
+
#include "QuickCryptoUtils.hpp"
|
|
9
|
+
|
|
10
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30500000L
|
|
11
|
+
#define RNQC_HAS_ML_KEM 1
|
|
12
|
+
#else
|
|
13
|
+
#define RNQC_HAS_ML_KEM 0
|
|
14
|
+
#endif
|
|
15
|
+
|
|
16
|
+
namespace margelo::nitro::crypto {
|
|
17
|
+
|
|
18
|
+
void HybridMlKemKeyPair::setVariant(const std::string& variant) {
|
|
19
|
+
#if !RNQC_HAS_ML_KEM
|
|
20
|
+
throw std::runtime_error("ML-KEM requires OpenSSL 3.5+");
|
|
21
|
+
#endif
|
|
22
|
+
if (variant != "ML-KEM-512" && variant != "ML-KEM-768" && variant != "ML-KEM-1024") {
|
|
23
|
+
throw std::runtime_error("Invalid ML-KEM variant: " + variant + ". Must be ML-KEM-512, ML-KEM-768, or ML-KEM-1024");
|
|
24
|
+
}
|
|
25
|
+
variant_ = variant;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
std::shared_ptr<Promise<void>> HybridMlKemKeyPair::generateKeyPair(double publicFormat, double publicType, double privateFormat,
|
|
29
|
+
double privateType) {
|
|
30
|
+
return Promise<void>::async([this, publicFormat, publicType, privateFormat, privateType]() {
|
|
31
|
+
this->generateKeyPairSync(publicFormat, publicType, privateFormat, privateType);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
void HybridMlKemKeyPair::generateKeyPairSync(double publicFormat, double publicType, double privateFormat, double privateType) {
|
|
36
|
+
#if !RNQC_HAS_ML_KEM
|
|
37
|
+
throw std::runtime_error("ML-KEM requires OpenSSL 3.5+");
|
|
38
|
+
#else
|
|
39
|
+
clearOpenSSLErrors();
|
|
40
|
+
|
|
41
|
+
if (variant_.empty()) {
|
|
42
|
+
throw std::runtime_error("ML-KEM variant not set. Call setVariant() first.");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
publicFormat_ = static_cast<int>(publicFormat);
|
|
46
|
+
publicType_ = static_cast<int>(publicType);
|
|
47
|
+
privateFormat_ = static_cast<int>(privateFormat);
|
|
48
|
+
privateType_ = static_cast<int>(privateType);
|
|
49
|
+
|
|
50
|
+
pkey_.reset();
|
|
51
|
+
|
|
52
|
+
EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(nullptr, variant_.c_str(), nullptr);
|
|
53
|
+
if (pctx == nullptr) {
|
|
54
|
+
throw std::runtime_error("Failed to create key context for " + variant_ + ": " + getOpenSSLError());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (EVP_PKEY_keygen_init(pctx) <= 0) {
|
|
58
|
+
EVP_PKEY_CTX_free(pctx);
|
|
59
|
+
throw std::runtime_error("Failed to initialize keygen: " + getOpenSSLError());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
EVP_PKEY* raw = nullptr;
|
|
63
|
+
if (EVP_PKEY_keygen(pctx, &raw) <= 0) {
|
|
64
|
+
EVP_PKEY_CTX_free(pctx);
|
|
65
|
+
throw std::runtime_error("Failed to generate ML-KEM key pair: " + getOpenSSLError());
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
pkey_.reset(raw);
|
|
69
|
+
EVP_PKEY_CTX_free(pctx);
|
|
70
|
+
#endif
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
std::shared_ptr<ArrayBuffer> HybridMlKemKeyPair::getPublicKey() {
|
|
74
|
+
#if !RNQC_HAS_ML_KEM
|
|
75
|
+
throw std::runtime_error("ML-KEM requires OpenSSL 3.5+");
|
|
76
|
+
#else
|
|
77
|
+
checkKeyPair();
|
|
78
|
+
|
|
79
|
+
BIO* bio = BIO_new(BIO_s_mem());
|
|
80
|
+
if (!bio) {
|
|
81
|
+
throw std::runtime_error("Failed to create BIO for public key export");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
int result;
|
|
85
|
+
if (publicFormat_ == 1) {
|
|
86
|
+
result = PEM_write_bio_PUBKEY(bio, pkey_.get());
|
|
87
|
+
} else {
|
|
88
|
+
result = i2d_PUBKEY_bio(bio, pkey_.get());
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (result != 1) {
|
|
92
|
+
BIO_free(bio);
|
|
93
|
+
throw std::runtime_error("Failed to export public key: " + getOpenSSLError());
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
BUF_MEM* bptr;
|
|
97
|
+
BIO_get_mem_ptr(bio, &bptr);
|
|
98
|
+
|
|
99
|
+
uint8_t* data = new uint8_t[bptr->length];
|
|
100
|
+
memcpy(data, bptr->data, bptr->length);
|
|
101
|
+
size_t len = bptr->length;
|
|
102
|
+
|
|
103
|
+
BIO_free(bio);
|
|
104
|
+
|
|
105
|
+
return std::make_shared<NativeArrayBuffer>(data, len, [=]() { delete[] data; });
|
|
106
|
+
#endif
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
std::shared_ptr<ArrayBuffer> HybridMlKemKeyPair::getPrivateKey() {
|
|
110
|
+
#if !RNQC_HAS_ML_KEM
|
|
111
|
+
throw std::runtime_error("ML-KEM requires OpenSSL 3.5+");
|
|
112
|
+
#else
|
|
113
|
+
checkKeyPair();
|
|
114
|
+
|
|
115
|
+
BIO* bio = BIO_new(BIO_s_mem());
|
|
116
|
+
if (!bio) {
|
|
117
|
+
throw std::runtime_error("Failed to create BIO for private key export");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
int result;
|
|
121
|
+
if (privateFormat_ == 1) {
|
|
122
|
+
result = PEM_write_bio_PrivateKey(bio, pkey_.get(), nullptr, nullptr, 0, nullptr, nullptr);
|
|
123
|
+
} else {
|
|
124
|
+
result = i2d_PKCS8PrivateKey_bio(bio, pkey_.get(), nullptr, nullptr, 0, nullptr, nullptr);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (result != 1) {
|
|
128
|
+
BIO_free(bio);
|
|
129
|
+
throw std::runtime_error("Failed to export private key: " + getOpenSSLError());
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
BUF_MEM* bptr;
|
|
133
|
+
BIO_get_mem_ptr(bio, &bptr);
|
|
134
|
+
|
|
135
|
+
uint8_t* data = new uint8_t[bptr->length];
|
|
136
|
+
memcpy(data, bptr->data, bptr->length);
|
|
137
|
+
size_t len = bptr->length;
|
|
138
|
+
|
|
139
|
+
BIO_free(bio);
|
|
140
|
+
|
|
141
|
+
return std::make_shared<NativeArrayBuffer>(data, len, [=]() { delete[] data; });
|
|
142
|
+
#endif
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
void HybridMlKemKeyPair::setPublicKey(const std::shared_ptr<ArrayBuffer>& keyData, double format, double type) {
|
|
146
|
+
#if !RNQC_HAS_ML_KEM
|
|
147
|
+
throw std::runtime_error("ML-KEM requires OpenSSL 3.5+");
|
|
148
|
+
#else
|
|
149
|
+
clearOpenSSLErrors();
|
|
150
|
+
|
|
151
|
+
if (variant_.empty()) {
|
|
152
|
+
throw std::runtime_error("ML-KEM variant not set. Call setVariant() first.");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
publicFormat_ = static_cast<int>(format);
|
|
156
|
+
publicType_ = static_cast<int>(type);
|
|
157
|
+
|
|
158
|
+
BIO* bio = BIO_new_mem_buf(keyData->data(), static_cast<int>(keyData->size()));
|
|
159
|
+
if (!bio) {
|
|
160
|
+
throw std::runtime_error("Failed to create BIO for public key import");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
EVP_PKEY* importedKey = nullptr;
|
|
164
|
+
if (publicFormat_ == 1) {
|
|
165
|
+
importedKey = PEM_read_bio_PUBKEY(bio, nullptr, nullptr, nullptr);
|
|
166
|
+
} else {
|
|
167
|
+
importedKey = d2i_PUBKEY_bio(bio, nullptr);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
BIO_free(bio);
|
|
171
|
+
|
|
172
|
+
if (importedKey == nullptr) {
|
|
173
|
+
throw std::runtime_error("Failed to import public key: " + getOpenSSLError());
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
pkey_.reset(importedKey);
|
|
177
|
+
#endif
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
void HybridMlKemKeyPair::setPrivateKey(const std::shared_ptr<ArrayBuffer>& keyData, double format, double type) {
|
|
181
|
+
#if !RNQC_HAS_ML_KEM
|
|
182
|
+
throw std::runtime_error("ML-KEM requires OpenSSL 3.5+");
|
|
183
|
+
#else
|
|
184
|
+
clearOpenSSLErrors();
|
|
185
|
+
|
|
186
|
+
if (variant_.empty()) {
|
|
187
|
+
throw std::runtime_error("ML-KEM variant not set. Call setVariant() first.");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
privateFormat_ = static_cast<int>(format);
|
|
191
|
+
privateType_ = static_cast<int>(type);
|
|
192
|
+
|
|
193
|
+
BIO* bio = BIO_new_mem_buf(keyData->data(), static_cast<int>(keyData->size()));
|
|
194
|
+
if (!bio) {
|
|
195
|
+
throw std::runtime_error("Failed to create BIO for private key import");
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
EVP_PKEY* importedKey = nullptr;
|
|
199
|
+
if (privateFormat_ == 1) {
|
|
200
|
+
importedKey = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr);
|
|
201
|
+
} else {
|
|
202
|
+
importedKey = d2i_PrivateKey_bio(bio, nullptr);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
BIO_free(bio);
|
|
206
|
+
|
|
207
|
+
if (importedKey == nullptr) {
|
|
208
|
+
throw std::runtime_error("Failed to import private key: " + getOpenSSLError());
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
pkey_.reset(importedKey);
|
|
212
|
+
#endif
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> HybridMlKemKeyPair::encapsulate() {
|
|
216
|
+
return Promise<std::shared_ptr<ArrayBuffer>>::async([this]() { return this->encapsulateSync(); });
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
std::shared_ptr<ArrayBuffer> HybridMlKemKeyPair::encapsulateSync() {
|
|
220
|
+
#if !RNQC_HAS_ML_KEM
|
|
221
|
+
throw std::runtime_error("ML-KEM requires OpenSSL 3.5+");
|
|
222
|
+
#else
|
|
223
|
+
clearOpenSSLErrors();
|
|
224
|
+
checkKeyPair();
|
|
225
|
+
|
|
226
|
+
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey_.get(), nullptr);
|
|
227
|
+
if (ctx == nullptr) {
|
|
228
|
+
throw std::runtime_error("Failed to create encapsulation context: " + getOpenSSLError());
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (EVP_PKEY_encapsulate_init(ctx, nullptr) <= 0) {
|
|
232
|
+
EVP_PKEY_CTX_free(ctx);
|
|
233
|
+
throw std::runtime_error("Failed to initialize encapsulation: " + getOpenSSLError());
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
size_t ct_len = 0;
|
|
237
|
+
size_t sk_len = 0;
|
|
238
|
+
if (EVP_PKEY_encapsulate(ctx, nullptr, &ct_len, nullptr, &sk_len) <= 0) {
|
|
239
|
+
EVP_PKEY_CTX_free(ctx);
|
|
240
|
+
throw std::runtime_error("Failed to determine encapsulation output sizes: " + getOpenSSLError());
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Pack result as: [uint32 ct_len][uint32 sk_len][ciphertext][shared_key]
|
|
244
|
+
size_t header_size = sizeof(uint32_t) * 2;
|
|
245
|
+
size_t total_size = header_size + ct_len + sk_len;
|
|
246
|
+
uint8_t* out = new uint8_t[total_size];
|
|
247
|
+
|
|
248
|
+
uint32_t ct_len_u32 = static_cast<uint32_t>(ct_len);
|
|
249
|
+
uint32_t sk_len_u32 = static_cast<uint32_t>(sk_len);
|
|
250
|
+
memcpy(out, &ct_len_u32, sizeof(uint32_t));
|
|
251
|
+
memcpy(out + sizeof(uint32_t), &sk_len_u32, sizeof(uint32_t));
|
|
252
|
+
|
|
253
|
+
uint8_t* ct_data = out + header_size;
|
|
254
|
+
uint8_t* sk_data = ct_data + ct_len;
|
|
255
|
+
|
|
256
|
+
if (EVP_PKEY_encapsulate(ctx, ct_data, &ct_len, sk_data, &sk_len) <= 0) {
|
|
257
|
+
EVP_PKEY_CTX_free(ctx);
|
|
258
|
+
delete[] out;
|
|
259
|
+
throw std::runtime_error("Failed to encapsulate: " + getOpenSSLError());
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
EVP_PKEY_CTX_free(ctx);
|
|
263
|
+
|
|
264
|
+
return std::make_shared<NativeArrayBuffer>(out, total_size, [=]() { delete[] out; });
|
|
265
|
+
#endif
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> HybridMlKemKeyPair::decapsulate(const std::shared_ptr<ArrayBuffer>& ciphertext) {
|
|
269
|
+
auto nativeCiphertext = ToNativeArrayBuffer(ciphertext);
|
|
270
|
+
return Promise<std::shared_ptr<ArrayBuffer>>::async([this, nativeCiphertext]() { return this->decapsulateSync(nativeCiphertext); });
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
std::shared_ptr<ArrayBuffer> HybridMlKemKeyPair::decapsulateSync(const std::shared_ptr<ArrayBuffer>& ciphertext) {
|
|
274
|
+
#if !RNQC_HAS_ML_KEM
|
|
275
|
+
throw std::runtime_error("ML-KEM requires OpenSSL 3.5+");
|
|
276
|
+
#else
|
|
277
|
+
clearOpenSSLErrors();
|
|
278
|
+
checkKeyPair();
|
|
279
|
+
|
|
280
|
+
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey_.get(), nullptr);
|
|
281
|
+
if (ctx == nullptr) {
|
|
282
|
+
throw std::runtime_error("Failed to create decapsulation context: " + getOpenSSLError());
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (EVP_PKEY_decapsulate_init(ctx, nullptr) <= 0) {
|
|
286
|
+
EVP_PKEY_CTX_free(ctx);
|
|
287
|
+
throw std::runtime_error("Failed to initialize decapsulation: " + getOpenSSLError());
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const uint8_t* ct_data = ciphertext->data();
|
|
291
|
+
size_t ct_size = ciphertext->size();
|
|
292
|
+
|
|
293
|
+
size_t sk_len = 0;
|
|
294
|
+
if (EVP_PKEY_decapsulate(ctx, nullptr, &sk_len, ct_data, ct_size) <= 0) {
|
|
295
|
+
EVP_PKEY_CTX_free(ctx);
|
|
296
|
+
throw std::runtime_error("Failed to determine shared key size: " + getOpenSSLError());
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
uint8_t* sk_data = new uint8_t[sk_len];
|
|
300
|
+
|
|
301
|
+
if (EVP_PKEY_decapsulate(ctx, sk_data, &sk_len, ct_data, ct_size) <= 0) {
|
|
302
|
+
EVP_PKEY_CTX_free(ctx);
|
|
303
|
+
delete[] sk_data;
|
|
304
|
+
throw std::runtime_error("Failed to decapsulate: " + getOpenSSLError());
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
EVP_PKEY_CTX_free(ctx);
|
|
308
|
+
|
|
309
|
+
return std::make_shared<NativeArrayBuffer>(sk_data, sk_len, [=]() { delete[] sk_data; });
|
|
310
|
+
#endif
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
void HybridMlKemKeyPair::checkKeyPair() {
|
|
314
|
+
if (!pkey_) {
|
|
315
|
+
throw std::runtime_error("Key pair not initialized");
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
} // namespace margelo::nitro::crypto
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
#include <openssl/evp.h>
|
|
5
|
+
#include <string>
|
|
6
|
+
|
|
7
|
+
#include "HybridMlKemKeyPairSpec.hpp"
|
|
8
|
+
#include "QuickCryptoUtils.hpp"
|
|
9
|
+
|
|
10
|
+
namespace margelo::nitro::crypto {
|
|
11
|
+
|
|
12
|
+
class HybridMlKemKeyPair : public HybridMlKemKeyPairSpec {
|
|
13
|
+
public:
|
|
14
|
+
HybridMlKemKeyPair() : HybridObject(TAG) {}
|
|
15
|
+
~HybridMlKemKeyPair() override = default;
|
|
16
|
+
|
|
17
|
+
void setVariant(const std::string& variant) override;
|
|
18
|
+
|
|
19
|
+
std::shared_ptr<Promise<void>> generateKeyPair(double publicFormat, double publicType, double privateFormat, double privateType) override;
|
|
20
|
+
void generateKeyPairSync(double publicFormat, double publicType, double privateFormat, double privateType) override;
|
|
21
|
+
|
|
22
|
+
std::shared_ptr<ArrayBuffer> getPublicKey() override;
|
|
23
|
+
std::shared_ptr<ArrayBuffer> getPrivateKey() override;
|
|
24
|
+
|
|
25
|
+
void setPublicKey(const std::shared_ptr<ArrayBuffer>& keyData, double format, double type) override;
|
|
26
|
+
void setPrivateKey(const std::shared_ptr<ArrayBuffer>& keyData, double format, double type) override;
|
|
27
|
+
|
|
28
|
+
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> encapsulate() override;
|
|
29
|
+
std::shared_ptr<ArrayBuffer> encapsulateSync() override;
|
|
30
|
+
|
|
31
|
+
std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> decapsulate(const std::shared_ptr<ArrayBuffer>& ciphertext) override;
|
|
32
|
+
std::shared_ptr<ArrayBuffer> decapsulateSync(const std::shared_ptr<ArrayBuffer>& ciphertext) override;
|
|
33
|
+
|
|
34
|
+
private:
|
|
35
|
+
std::string variant_;
|
|
36
|
+
|
|
37
|
+
using EVP_PKEY_ptr = std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>;
|
|
38
|
+
EVP_PKEY_ptr pkey_{nullptr, EVP_PKEY_free};
|
|
39
|
+
|
|
40
|
+
int publicFormat_ = -1;
|
|
41
|
+
int publicType_ = -1;
|
|
42
|
+
int privateFormat_ = -1;
|
|
43
|
+
int privateType_ = -1;
|
|
44
|
+
|
|
45
|
+
void checkKeyPair();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
} // namespace margelo::nitro::crypto
|
package/cpp/sign/SignUtils.hpp
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
#include <cstring>
|
|
4
4
|
#include <memory>
|
|
5
|
+
#include <openssl/bn.h>
|
|
6
|
+
#include <openssl/core_names.h>
|
|
5
7
|
#include <openssl/dsa.h>
|
|
6
8
|
#include <openssl/ec.h>
|
|
7
9
|
#include <openssl/ecdsa.h>
|
|
8
10
|
#include <openssl/evp.h>
|
|
9
11
|
#include <string>
|
|
10
12
|
|
|
13
|
+
#include "../utils/QuickCryptoUtils.hpp"
|
|
14
|
+
|
|
11
15
|
namespace margelo::nitro::crypto {
|
|
12
16
|
|
|
13
17
|
enum DSASigEnc {
|
|
@@ -15,29 +19,6 @@ enum DSASigEnc {
|
|
|
15
19
|
kSigEncP1363 = 1,
|
|
16
20
|
};
|
|
17
21
|
|
|
18
|
-
inline const EVP_MD* getDigestByName(const std::string& algorithm) {
|
|
19
|
-
if (algorithm == "SHA1" || algorithm == "sha1" || algorithm == "SHA-1" || algorithm == "sha-1") {
|
|
20
|
-
return EVP_sha1();
|
|
21
|
-
} else if (algorithm == "SHA224" || algorithm == "sha224" || algorithm == "SHA-224" || algorithm == "sha-224") {
|
|
22
|
-
return EVP_sha224();
|
|
23
|
-
} else if (algorithm == "SHA256" || algorithm == "sha256" || algorithm == "SHA-256" || algorithm == "sha-256") {
|
|
24
|
-
return EVP_sha256();
|
|
25
|
-
} else if (algorithm == "SHA384" || algorithm == "sha384" || algorithm == "SHA-384" || algorithm == "sha-384") {
|
|
26
|
-
return EVP_sha384();
|
|
27
|
-
} else if (algorithm == "SHA512" || algorithm == "sha512" || algorithm == "SHA-512" || algorithm == "sha-512") {
|
|
28
|
-
return EVP_sha512();
|
|
29
|
-
} else if (algorithm == "SHA3-224" || algorithm == "sha3-224") {
|
|
30
|
-
return EVP_sha3_224();
|
|
31
|
-
} else if (algorithm == "SHA3-256" || algorithm == "sha3-256") {
|
|
32
|
-
return EVP_sha3_256();
|
|
33
|
-
} else if (algorithm == "SHA3-384" || algorithm == "sha3-384") {
|
|
34
|
-
return EVP_sha3_384();
|
|
35
|
-
} else if (algorithm == "SHA3-512" || algorithm == "sha3-512") {
|
|
36
|
-
return EVP_sha3_512();
|
|
37
|
-
}
|
|
38
|
-
throw std::runtime_error("Unsupported hash algorithm: " + algorithm);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
22
|
inline unsigned int getBytesOfRS(EVP_PKEY* pkey) {
|
|
42
23
|
int bits;
|
|
43
24
|
int base_id = EVP_PKEY_base_id(pkey);
|
|
@@ -46,9 +27,11 @@ inline unsigned int getBytesOfRS(EVP_PKEY* pkey) {
|
|
|
46
27
|
const DSA* dsa_key = EVP_PKEY_get0_DSA(pkey);
|
|
47
28
|
bits = BN_num_bits(DSA_get0_q(dsa_key));
|
|
48
29
|
} else if (base_id == EVP_PKEY_EC) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
30
|
+
BIGNUM* order = nullptr;
|
|
31
|
+
if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_ORDER, &order) != 1 || !order)
|
|
32
|
+
return 0;
|
|
33
|
+
bits = BN_num_bits(order);
|
|
34
|
+
BN_free(order);
|
|
52
35
|
} else {
|
|
53
36
|
return 0;
|
|
54
37
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#include "QuickCryptoUtils.hpp"
|
|
2
|
+
#include <openssl/bn.h>
|
|
3
|
+
#include <openssl/core_names.h>
|
|
4
|
+
#include <openssl/evp.h>
|
|
5
|
+
#include <openssl/param_build.h>
|
|
6
|
+
#include <stdexcept>
|
|
7
|
+
|
|
8
|
+
namespace margelo::nitro::crypto {
|
|
9
|
+
|
|
10
|
+
EVP_PKEY* createEcEvpPkey(const char* group_name, const uint8_t* pub_oct, size_t pub_len, const BIGNUM* priv_bn) {
|
|
11
|
+
OSSL_PARAM_BLD* bld = OSSL_PARAM_BLD_new();
|
|
12
|
+
if (!bld)
|
|
13
|
+
throw std::runtime_error("Failed to create OSSL_PARAM_BLD");
|
|
14
|
+
|
|
15
|
+
OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0);
|
|
16
|
+
OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, pub_oct, pub_len);
|
|
17
|
+
if (priv_bn)
|
|
18
|
+
OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv_bn);
|
|
19
|
+
|
|
20
|
+
OSSL_PARAM* params = OSSL_PARAM_BLD_to_param(bld);
|
|
21
|
+
OSSL_PARAM_BLD_free(bld);
|
|
22
|
+
if (!params)
|
|
23
|
+
throw std::runtime_error("Failed to build EC parameters");
|
|
24
|
+
|
|
25
|
+
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr);
|
|
26
|
+
if (!ctx) {
|
|
27
|
+
OSSL_PARAM_free(params);
|
|
28
|
+
throw std::runtime_error("Failed to create EVP_PKEY_CTX for EC");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
int selection = priv_bn ? EVP_PKEY_KEYPAIR : EVP_PKEY_PUBLIC_KEY;
|
|
32
|
+
EVP_PKEY* pkey = nullptr;
|
|
33
|
+
if (EVP_PKEY_fromdata_init(ctx) <= 0 || EVP_PKEY_fromdata(ctx, &pkey, selection, params) <= 0) {
|
|
34
|
+
EVP_PKEY_CTX_free(ctx);
|
|
35
|
+
OSSL_PARAM_free(params);
|
|
36
|
+
throw std::runtime_error("Failed to create EVP_PKEY from EC parameters");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
EVP_PKEY_CTX_free(ctx);
|
|
40
|
+
OSSL_PARAM_free(params);
|
|
41
|
+
return pkey;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
} // namespace margelo::nitro::crypto
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
#include <algorithm>
|
|
4
4
|
#include <cctype>
|
|
5
5
|
#include <limits>
|
|
6
|
+
#include <openssl/bn.h>
|
|
6
7
|
#include <openssl/err.h>
|
|
8
|
+
#include <openssl/evp.h>
|
|
7
9
|
#include <string>
|
|
8
10
|
#include <vector>
|
|
9
11
|
|
|
@@ -72,4 +74,41 @@ inline std::string toLower(std::string s) {
|
|
|
72
74
|
return s;
|
|
73
75
|
}
|
|
74
76
|
|
|
77
|
+
inline const EVP_MD* getDigestByName(const std::string& algorithm) {
|
|
78
|
+
std::string algo = toLower(algorithm);
|
|
79
|
+
|
|
80
|
+
// Strip legacy RSA- prefix (e.g. rsa-sha256 -> sha256) for Node.js compat
|
|
81
|
+
if (algo.size() > 4 && algo.compare(0, 4, "rsa-") == 0) {
|
|
82
|
+
algo = algo.substr(4);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (algo == "sha1" || algo == "sha-1") {
|
|
86
|
+
return EVP_sha1();
|
|
87
|
+
} else if (algo == "sha224" || algo == "sha-224") {
|
|
88
|
+
return EVP_sha224();
|
|
89
|
+
} else if (algo == "sha256" || algo == "sha-256") {
|
|
90
|
+
return EVP_sha256();
|
|
91
|
+
} else if (algo == "sha384" || algo == "sha-384") {
|
|
92
|
+
return EVP_sha384();
|
|
93
|
+
} else if (algo == "sha512" || algo == "sha-512") {
|
|
94
|
+
return EVP_sha512();
|
|
95
|
+
} else if (algo == "sha3-224") {
|
|
96
|
+
return EVP_sha3_224();
|
|
97
|
+
} else if (algo == "sha3-256") {
|
|
98
|
+
return EVP_sha3_256();
|
|
99
|
+
} else if (algo == "sha3-384") {
|
|
100
|
+
return EVP_sha3_384();
|
|
101
|
+
} else if (algo == "sha3-512") {
|
|
102
|
+
return EVP_sha3_512();
|
|
103
|
+
} else if (algo == "ripemd160" || algo == "ripemd-160") {
|
|
104
|
+
return EVP_ripemd160();
|
|
105
|
+
}
|
|
106
|
+
throw std::runtime_error("Unsupported hash algorithm: " + algorithm);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Build an EVP_PKEY from EC curve name + public key octets + optional private key BIGNUM.
|
|
110
|
+
// Uses OSSL_PARAM_BLD + EVP_PKEY_fromdata (OpenSSL 3.x, no deprecated EC_KEY APIs).
|
|
111
|
+
// Caller owns the returned EVP_PKEY*.
|
|
112
|
+
EVP_PKEY* createEcEvpPkey(const char* group_name, const uint8_t* pub_oct, size_t pub_len, const BIGNUM* priv_bn = nullptr);
|
|
113
|
+
|
|
75
114
|
} // namespace margelo::nitro::crypto
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#include "HybridX509Certificate.hpp"
|
|
2
|
+
#include "../keys/HybridKeyObjectHandle.hpp"
|
|
3
|
+
#include "../keys/KeyObjectData.hpp"
|
|
4
|
+
#include "QuickCryptoUtils.hpp"
|
|
5
|
+
#include <ncrypto.h>
|
|
6
|
+
|
|
7
|
+
namespace margelo::nitro::crypto {
|
|
8
|
+
|
|
9
|
+
std::string HybridX509Certificate::bioToString(ncrypto::BIOPointer bio) const {
|
|
10
|
+
if (!bio)
|
|
11
|
+
return "";
|
|
12
|
+
BUF_MEM* mem = bio;
|
|
13
|
+
if (!mem || mem->length == 0)
|
|
14
|
+
return "";
|
|
15
|
+
return std::string(mem->data, mem->length);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
void HybridX509Certificate::init(const std::shared_ptr<ArrayBuffer>& buffer) {
|
|
19
|
+
ncrypto::Buffer<const unsigned char> buf{.data = reinterpret_cast<const unsigned char*>(buffer->data()), .len = buffer->size()};
|
|
20
|
+
auto result = ncrypto::X509Pointer::Parse(buf);
|
|
21
|
+
if (!result) {
|
|
22
|
+
throw std::runtime_error("Failed to parse X509 certificate");
|
|
23
|
+
}
|
|
24
|
+
cert_ = std::move(result.value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
std::string HybridX509Certificate::subject() {
|
|
28
|
+
return bioToString(cert_.view().getSubject());
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
std::string HybridX509Certificate::subjectAltName() {
|
|
32
|
+
return bioToString(cert_.view().getSubjectAltName());
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
std::string HybridX509Certificate::issuer() {
|
|
36
|
+
return bioToString(cert_.view().getIssuer());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
std::string HybridX509Certificate::infoAccess() {
|
|
40
|
+
return bioToString(cert_.view().getInfoAccess());
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
std::string HybridX509Certificate::validFrom() {
|
|
44
|
+
return bioToString(cert_.view().getValidFrom());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
std::string HybridX509Certificate::validTo() {
|
|
48
|
+
return bioToString(cert_.view().getValidTo());
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
double HybridX509Certificate::validFromDate() {
|
|
52
|
+
return static_cast<double>(cert_.view().getValidFromTime()) * 1000.0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
double HybridX509Certificate::validToDate() {
|
|
56
|
+
return static_cast<double>(cert_.view().getValidToTime()) * 1000.0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
std::string HybridX509Certificate::signatureAlgorithm() {
|
|
60
|
+
auto algo = cert_.view().getSignatureAlgorithm();
|
|
61
|
+
if (!algo.has_value())
|
|
62
|
+
return "";
|
|
63
|
+
return std::string(algo.value());
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
std::string HybridX509Certificate::signatureAlgorithmOid() {
|
|
67
|
+
return cert_.view().getSignatureAlgorithmOID().value_or("");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
std::string HybridX509Certificate::serialNumber() {
|
|
71
|
+
auto serial = cert_.view().getSerialNumber();
|
|
72
|
+
if (!serial)
|
|
73
|
+
return "";
|
|
74
|
+
return std::string(static_cast<const char*>(serial.get()), serial.size());
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
std::string HybridX509Certificate::fingerprint() {
|
|
78
|
+
return cert_.view().getFingerprint(ncrypto::Digest::SHA1).value_or("");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
std::string HybridX509Certificate::fingerprint256() {
|
|
82
|
+
return cert_.view().getFingerprint(ncrypto::Digest::SHA256).value_or("");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
std::string HybridX509Certificate::fingerprint512() {
|
|
86
|
+
return cert_.view().getFingerprint(ncrypto::Digest::SHA512).value_or("");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
std::shared_ptr<ArrayBuffer> HybridX509Certificate::raw() {
|
|
90
|
+
auto bio = cert_.view().toDER();
|
|
91
|
+
if (!bio) {
|
|
92
|
+
throw std::runtime_error("Failed to export certificate as DER");
|
|
93
|
+
}
|
|
94
|
+
BUF_MEM* mem = bio;
|
|
95
|
+
return ToNativeArrayBuffer(reinterpret_cast<const uint8_t*>(mem->data), mem->length);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
std::string HybridX509Certificate::pem() {
|
|
99
|
+
return bioToString(cert_.view().toPEM());
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
std::shared_ptr<HybridKeyObjectHandleSpec> HybridX509Certificate::publicKey() {
|
|
103
|
+
auto result = cert_.view().getPublicKey();
|
|
104
|
+
if (!result) {
|
|
105
|
+
throw std::runtime_error("Failed to extract public key from certificate");
|
|
106
|
+
}
|
|
107
|
+
auto handle = std::make_shared<HybridKeyObjectHandle>();
|
|
108
|
+
handle->setKeyObjectData(KeyObjectData::CreateAsymmetric(KeyType::PUBLIC, std::move(result.value)));
|
|
109
|
+
return handle;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
std::vector<std::string> HybridX509Certificate::keyUsage() {
|
|
113
|
+
std::vector<std::string> usages;
|
|
114
|
+
cert_.view().enumUsages([&](const char* usage) { usages.emplace_back(usage); });
|
|
115
|
+
return usages;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
bool HybridX509Certificate::ca() {
|
|
119
|
+
return cert_.view().isCA();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
bool HybridX509Certificate::checkIssued(const std::shared_ptr<HybridX509CertificateHandleSpec>& other) {
|
|
123
|
+
auto otherCert = std::dynamic_pointer_cast<HybridX509Certificate>(other);
|
|
124
|
+
if (!otherCert) {
|
|
125
|
+
throw std::runtime_error("Invalid X509Certificate");
|
|
126
|
+
}
|
|
127
|
+
return cert_.view().isIssuedBy(otherCert->cert_.view());
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
bool HybridX509Certificate::checkPrivateKey(const std::shared_ptr<HybridKeyObjectHandleSpec>& key) {
|
|
131
|
+
auto handle = std::dynamic_pointer_cast<HybridKeyObjectHandle>(key);
|
|
132
|
+
if (!handle) {
|
|
133
|
+
throw std::runtime_error("Invalid key object");
|
|
134
|
+
}
|
|
135
|
+
return cert_.view().checkPrivateKey(handle->getKeyObjectData().GetAsymmetricKey());
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
bool HybridX509Certificate::verify(const std::shared_ptr<HybridKeyObjectHandleSpec>& key) {
|
|
139
|
+
auto handle = std::dynamic_pointer_cast<HybridKeyObjectHandle>(key);
|
|
140
|
+
if (!handle) {
|
|
141
|
+
throw std::runtime_error("Invalid key object");
|
|
142
|
+
}
|
|
143
|
+
return cert_.view().checkPublicKey(handle->getKeyObjectData().GetAsymmetricKey());
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
std::optional<std::string> HybridX509Certificate::checkHost(const std::string& name, double flags) {
|
|
147
|
+
ncrypto::DataPointer peername;
|
|
148
|
+
auto match = cert_.view().checkHost(name, static_cast<int>(flags), &peername);
|
|
149
|
+
if (match == ncrypto::X509View::CheckMatch::MATCH) {
|
|
150
|
+
if (peername) {
|
|
151
|
+
return std::string(static_cast<const char*>(peername.get()), peername.size());
|
|
152
|
+
}
|
|
153
|
+
return name;
|
|
154
|
+
}
|
|
155
|
+
return std::nullopt;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
std::optional<std::string> HybridX509Certificate::checkEmail(const std::string& email, double flags) {
|
|
159
|
+
auto match = cert_.view().checkEmail(email, static_cast<int>(flags));
|
|
160
|
+
if (match == ncrypto::X509View::CheckMatch::MATCH) {
|
|
161
|
+
return email;
|
|
162
|
+
}
|
|
163
|
+
return std::nullopt;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
std::optional<std::string> HybridX509Certificate::checkIP(const std::string& ip) {
|
|
167
|
+
auto match = cert_.view().checkIp(ip, 0);
|
|
168
|
+
if (match == ncrypto::X509View::CheckMatch::MATCH) {
|
|
169
|
+
return ip;
|
|
170
|
+
}
|
|
171
|
+
return std::nullopt;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
} // namespace margelo::nitro::crypto
|