react-native-quick-crypto 1.0.10 → 1.0.12
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 +16 -0
- package/cpp/argon2/HybridArgon2.cpp +103 -0
- package/cpp/argon2/HybridArgon2.hpp +32 -0
- package/cpp/certificate/HybridCertificate.cpp +42 -0
- package/cpp/certificate/HybridCertificate.hpp +16 -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 +68 -1
- package/cpp/cipher/HybridCipher.hpp +6 -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/dh/HybridDhKeyPair.cpp +179 -0
- package/cpp/dh/HybridDhKeyPair.hpp +37 -0
- package/cpp/dsa/HybridDsaKeyPair.cpp +128 -0
- package/cpp/dsa/HybridDsaKeyPair.hpp +32 -0
- package/cpp/ecdh/HybridECDH.cpp +42 -120
- package/cpp/ecdh/HybridECDH.hpp +1 -0
- package/cpp/keys/HybridKeyObjectHandle.cpp +150 -128
- 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/prime/HybridPrime.cpp +81 -0
- package/cpp/prime/HybridPrime.hpp +20 -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/argon2.js +39 -0
- package/lib/commonjs/argon2.js.map +1 -0
- package/lib/commonjs/certificate.js +35 -0
- package/lib/commonjs/certificate.js.map +1 -0
- package/lib/commonjs/cipher.js +23 -2
- package/lib/commonjs/cipher.js.map +1 -1
- package/lib/commonjs/dhKeyPair.js +109 -0
- package/lib/commonjs/dhKeyPair.js.map +1 -0
- package/lib/commonjs/dsa.js +92 -0
- package/lib/commonjs/dsa.js.map +1 -0
- package/lib/commonjs/ec.js +18 -18
- package/lib/commonjs/ec.js.map +1 -1
- package/lib/commonjs/ecdh.js +37 -0
- package/lib/commonjs/ecdh.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 +57 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/keys/classes.js +11 -9
- package/lib/commonjs/keys/classes.js.map +1 -1
- package/lib/commonjs/keys/generateKeyPair.js +11 -0
- package/lib/commonjs/keys/generateKeyPair.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/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/prime.js +84 -0
- package/lib/commonjs/prime.js.map +1 -0
- package/lib/commonjs/rsa.js +7 -7
- package/lib/commonjs/rsa.js.map +1 -1
- package/lib/commonjs/specs/argon2.nitro.js +6 -0
- package/lib/commonjs/specs/argon2.nitro.js.map +1 -0
- package/lib/commonjs/specs/certificate.nitro.js +6 -0
- package/lib/commonjs/specs/certificate.nitro.js.map +1 -0
- package/lib/commonjs/specs/dhKeyPair.nitro.js +6 -0
- package/lib/commonjs/specs/dhKeyPair.nitro.js.map +1 -0
- package/lib/commonjs/specs/dsaKeyPair.nitro.js +6 -0
- package/lib/commonjs/specs/dsaKeyPair.nitro.js.map +1 -0
- 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/prime.nitro.js +6 -0
- package/lib/commonjs/specs/prime.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 +385 -114
- 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/argon2.js +34 -0
- package/lib/module/argon2.js.map +1 -0
- package/lib/module/certificate.js +30 -0
- package/lib/module/certificate.js.map +1 -0
- package/lib/module/cipher.js +23 -3
- package/lib/module/cipher.js.map +1 -1
- package/lib/module/dhKeyPair.js +102 -0
- package/lib/module/dhKeyPair.js.map +1 -0
- package/lib/module/dsa.js +85 -0
- package/lib/module/dsa.js.map +1 -0
- package/lib/module/ec.js +6 -6
- package/lib/module/ec.js.map +1 -1
- package/lib/module/ecdh.js +37 -0
- package/lib/module/ecdh.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 +15 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/keys/classes.js +11 -9
- package/lib/module/keys/classes.js.map +1 -1
- package/lib/module/keys/generateKeyPair.js +11 -0
- package/lib/module/keys/generateKeyPair.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/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/prime.js +77 -0
- package/lib/module/prime.js.map +1 -0
- package/lib/module/rsa.js +1 -1
- package/lib/module/rsa.js.map +1 -1
- package/lib/module/specs/argon2.nitro.js +4 -0
- package/lib/module/specs/argon2.nitro.js.map +1 -0
- package/lib/module/specs/certificate.nitro.js +4 -0
- package/lib/module/specs/certificate.nitro.js.map +1 -0
- package/lib/module/specs/dhKeyPair.nitro.js +4 -0
- package/lib/module/specs/dhKeyPair.nitro.js.map +1 -0
- package/lib/module/specs/dsaKeyPair.nitro.js +4 -0
- package/lib/module/specs/dsaKeyPair.nitro.js.map +1 -0
- 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/prime.nitro.js +4 -0
- package/lib/module/specs/prime.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 +386 -116
- 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/argon2.d.ts +16 -0
- package/lib/typescript/argon2.d.ts.map +1 -0
- package/lib/typescript/certificate.d.ts +8 -0
- package/lib/typescript/certificate.d.ts.map +1 -0
- package/lib/typescript/cipher.d.ts +15 -0
- package/lib/typescript/cipher.d.ts.map +1 -1
- package/lib/typescript/dhKeyPair.d.ts +19 -0
- package/lib/typescript/dhKeyPair.d.ts.map +1 -0
- package/lib/typescript/dsa.d.ts +19 -0
- package/lib/typescript/dsa.d.ts.map +1 -0
- package/lib/typescript/ec.d.ts +1 -1
- package/lib/typescript/ec.d.ts.map +1 -1
- package/lib/typescript/ecdh.d.ts +3 -0
- package/lib/typescript/ecdh.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 +32 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/keys/classes.d.ts +7 -5
- package/lib/typescript/keys/classes.d.ts.map +1 -1
- package/lib/typescript/keys/generateKeyPair.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/prime.d.ts +19 -0
- package/lib/typescript/prime.d.ts.map +1 -0
- package/lib/typescript/rsa.d.ts +1 -1
- package/lib/typescript/rsa.d.ts.map +1 -1
- package/lib/typescript/specs/argon2.nitro.d.ts +9 -0
- package/lib/typescript/specs/argon2.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/certificate.nitro.d.ts +10 -0
- package/lib/typescript/specs/certificate.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/cipher.nitro.d.ts +9 -0
- package/lib/typescript/specs/cipher.nitro.d.ts.map +1 -1
- package/lib/typescript/specs/dhKeyPair.nitro.d.ts +14 -0
- package/lib/typescript/specs/dhKeyPair.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/dsaKeyPair.nitro.d.ts +13 -0
- package/lib/typescript/specs/dsaKeyPair.nitro.d.ts.map +1 -0
- package/lib/typescript/specs/ecdh.nitro.d.ts +1 -0
- package/lib/typescript/specs/ecdh.nitro.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/prime.nitro.d.ts +11 -0
- package/lib/typescript/specs/prime.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 +12 -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 +25 -9
- 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 +8 -0
- package/nitrogen/generated/android/QuickCryptoOnLoad.cpp +80 -0
- package/nitrogen/generated/ios/QuickCryptoAutolinking.mm +80 -0
- package/nitrogen/generated/shared/c++/AsymmetricKeyType.hpp +12 -0
- package/nitrogen/generated/shared/c++/CipherInfo.hpp +104 -0
- package/nitrogen/generated/shared/c++/HybridArgon2Spec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridArgon2Spec.hpp +66 -0
- package/nitrogen/generated/shared/c++/HybridCertificateSpec.cpp +23 -0
- package/nitrogen/generated/shared/c++/HybridCertificateSpec.hpp +64 -0
- package/nitrogen/generated/shared/c++/HybridCipherSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridCipherSpec.hpp +4 -0
- package/nitrogen/generated/shared/c++/HybridDhKeyPairSpec.cpp +27 -0
- package/nitrogen/generated/shared/c++/HybridDhKeyPairSpec.hpp +69 -0
- package/nitrogen/generated/shared/c++/HybridDsaKeyPairSpec.cpp +26 -0
- package/nitrogen/generated/shared/c++/HybridDsaKeyPairSpec.hpp +68 -0
- package/nitrogen/generated/shared/c++/HybridECDHSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridECDHSpec.hpp +1 -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++/HybridPrimeSpec.cpp +24 -0
- package/nitrogen/generated/shared/c++/HybridPrimeSpec.hpp +67 -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/argon2.ts +83 -0
- package/src/certificate.ts +41 -0
- package/src/cipher.ts +41 -3
- package/src/dhKeyPair.ts +156 -0
- package/src/dsa.ts +129 -0
- package/src/ec.ts +9 -9
- package/src/ecdh.ts +59 -0
- package/src/ed.ts +2 -2
- package/src/hash.ts +34 -11
- package/src/hkdf.ts +2 -7
- package/src/index.ts +16 -0
- package/src/keys/classes.ts +26 -14
- package/src/keys/generateKeyPair.ts +14 -0
- package/src/keys/index.ts +37 -2
- package/src/keys/signVerify.ts +0 -5
- package/src/mlkem.ts +350 -0
- package/src/pbkdf2.ts +34 -5
- package/src/prime.ts +134 -0
- package/src/rsa.ts +1 -1
- package/src/specs/argon2.nitro.ts +29 -0
- package/src/specs/certificate.nitro.ts +8 -0
- package/src/specs/cipher.nitro.ts +14 -0
- package/src/specs/dhKeyPair.nitro.ts +14 -0
- package/src/specs/dsaKeyPair.nitro.ts +13 -0
- package/src/specs/ecdh.nitro.ts +1 -0
- 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/prime.nitro.ts +18 -0
- package/src/specs/x509certificate.nitro.ts +38 -0
- package/src/subtle.ts +821 -136
- package/src/utils/conversion.ts +10 -4
- package/src/utils/hashnames.ts +33 -2
- package/src/utils/types.ts +64 -8
- package/src/x509certificate.ts +277 -0
|
@@ -31,6 +31,8 @@ class HybridKeyObjectHandle : public HybridKeyObjectHandleSpec {
|
|
|
31
31
|
|
|
32
32
|
bool initECRaw(const std::string& namedCurve, const std::shared_ptr<ArrayBuffer>& keyData) override;
|
|
33
33
|
|
|
34
|
+
bool initPqcRaw(const std::string& algorithmName, const std::shared_ptr<ArrayBuffer>& keyData, bool isPublic) override;
|
|
35
|
+
|
|
34
36
|
std::optional<KeyType> initJwk(const JWK& keyData, std::optional<NamedCurve> namedCurve) override;
|
|
35
37
|
|
|
36
38
|
KeyDetail keyDetail() override;
|
|
@@ -39,13 +41,14 @@ class HybridKeyObjectHandle : public HybridKeyObjectHandleSpec {
|
|
|
39
41
|
|
|
40
42
|
double getSymmetricKeySize() override;
|
|
41
43
|
|
|
42
|
-
KeyObjectData& getKeyObjectData() {
|
|
43
|
-
return data_;
|
|
44
|
-
}
|
|
45
44
|
const KeyObjectData& getKeyObjectData() const {
|
|
46
45
|
return data_;
|
|
47
46
|
}
|
|
48
47
|
|
|
48
|
+
void setKeyObjectData(KeyObjectData data) {
|
|
49
|
+
data_ = std::move(data);
|
|
50
|
+
}
|
|
51
|
+
|
|
49
52
|
private:
|
|
50
53
|
KeyObjectData data_;
|
|
51
54
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#include <NitroModules/ArrayBuffer.hpp>
|
|
2
|
+
#include <memory>
|
|
3
|
+
#include <openssl/core_names.h>
|
|
4
|
+
#include <openssl/err.h>
|
|
5
|
+
#include <openssl/evp.h>
|
|
6
|
+
#include <string>
|
|
7
|
+
#include <vector>
|
|
8
|
+
|
|
9
|
+
#include "HybridKmac.hpp"
|
|
10
|
+
|
|
11
|
+
namespace margelo::nitro::crypto {
|
|
12
|
+
|
|
13
|
+
void HybridKmac::createKmac(const std::string& algorithm, const std::shared_ptr<ArrayBuffer>& key, double outputLength,
|
|
14
|
+
const std::optional<std::shared_ptr<ArrayBuffer>>& customization) {
|
|
15
|
+
outputLen = static_cast<size_t>(outputLength);
|
|
16
|
+
if (outputLen == 0) {
|
|
17
|
+
throw std::runtime_error("KMAC output length must be greater than 0");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
std::unique_ptr<EVP_MAC, decltype(&EVP_MAC_free)> mac(EVP_MAC_fetch(nullptr, algorithm.c_str(), nullptr), EVP_MAC_free);
|
|
21
|
+
if (!mac) {
|
|
22
|
+
throw std::runtime_error("Failed to fetch " + algorithm + " implementation: " + std::to_string(ERR_get_error()));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
ctx.reset(EVP_MAC_CTX_new(mac.get()));
|
|
26
|
+
if (!ctx) {
|
|
27
|
+
throw std::runtime_error("Failed to create KMAC context: " + std::to_string(ERR_get_error()));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
OSSL_PARAM params[3];
|
|
31
|
+
size_t paramCount = 0;
|
|
32
|
+
|
|
33
|
+
params[paramCount++] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, &outputLen);
|
|
34
|
+
|
|
35
|
+
std::vector<uint8_t> custData;
|
|
36
|
+
if (customization.has_value() && customization.value()->size() > 0) {
|
|
37
|
+
const auto& custBuf = customization.value();
|
|
38
|
+
custData.assign(reinterpret_cast<const uint8_t*>(custBuf->data()), reinterpret_cast<const uint8_t*>(custBuf->data()) + custBuf->size());
|
|
39
|
+
params[paramCount++] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM, custData.data(), custData.size());
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
params[paramCount] = OSSL_PARAM_construct_end();
|
|
43
|
+
|
|
44
|
+
const uint8_t* keyData = reinterpret_cast<const uint8_t*>(key->data());
|
|
45
|
+
size_t keySize = key->size();
|
|
46
|
+
|
|
47
|
+
if (keySize == 0) {
|
|
48
|
+
throw std::runtime_error("KMAC key must not be empty");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (EVP_MAC_init(ctx.get(), keyData, keySize, params) != 1) {
|
|
52
|
+
throw std::runtime_error("Failed to initialize KMAC: " + std::to_string(ERR_get_error()));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
void HybridKmac::update(const std::shared_ptr<ArrayBuffer>& data) {
|
|
57
|
+
if (!ctx) {
|
|
58
|
+
throw std::runtime_error("KMAC context not initialized");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (EVP_MAC_update(ctx.get(), reinterpret_cast<const uint8_t*>(data->data()), data->size()) != 1) {
|
|
62
|
+
throw std::runtime_error("Failed to update KMAC: " + std::to_string(ERR_get_error()));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
std::shared_ptr<ArrayBuffer> HybridKmac::digest() {
|
|
67
|
+
if (!ctx) {
|
|
68
|
+
throw std::runtime_error("KMAC context not initialized");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
uint8_t* buffer = new uint8_t[outputLen];
|
|
72
|
+
|
|
73
|
+
if (EVP_MAC_final(ctx.get(), buffer, nullptr, outputLen) != 1) {
|
|
74
|
+
delete[] buffer;
|
|
75
|
+
throw std::runtime_error("Failed to finalize KMAC digest: " + std::to_string(ERR_get_error()));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
ctx.reset();
|
|
79
|
+
|
|
80
|
+
return std::make_shared<NativeArrayBuffer>(buffer, outputLen, [=]() { delete[] buffer; });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
} // namespace margelo::nitro::crypto
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <NitroModules/ArrayBuffer.hpp>
|
|
4
|
+
#include <memory>
|
|
5
|
+
#include <openssl/evp.h>
|
|
6
|
+
#include <string>
|
|
7
|
+
|
|
8
|
+
#include "HybridKmacSpec.hpp"
|
|
9
|
+
|
|
10
|
+
namespace margelo::nitro::crypto {
|
|
11
|
+
|
|
12
|
+
using namespace facebook;
|
|
13
|
+
|
|
14
|
+
using EVP_MAC_CTX_ptr = std::unique_ptr<EVP_MAC_CTX, decltype(&EVP_MAC_CTX_free)>;
|
|
15
|
+
|
|
16
|
+
class HybridKmac : public HybridKmacSpec {
|
|
17
|
+
public:
|
|
18
|
+
HybridKmac() : HybridObject(TAG) {}
|
|
19
|
+
|
|
20
|
+
public:
|
|
21
|
+
void createKmac(const std::string& algorithm, const std::shared_ptr<ArrayBuffer>& key, double outputLength,
|
|
22
|
+
const std::optional<std::shared_ptr<ArrayBuffer>>& customization) override;
|
|
23
|
+
void update(const std::shared_ptr<ArrayBuffer>& data) override;
|
|
24
|
+
std::shared_ptr<ArrayBuffer> digest() override;
|
|
25
|
+
|
|
26
|
+
private:
|
|
27
|
+
EVP_MAC_CTX_ptr ctx{nullptr, EVP_MAC_CTX_free};
|
|
28
|
+
size_t outputLen = 0;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
} // namespace margelo::nitro::crypto
|
|
@@ -15,13 +15,6 @@
|
|
|
15
15
|
|
|
16
16
|
namespace margelo::nitro::crypto {
|
|
17
17
|
|
|
18
|
-
HybridMlDsaKeyPair::~HybridMlDsaKeyPair() {
|
|
19
|
-
if (pkey_ != nullptr) {
|
|
20
|
-
EVP_PKEY_free(pkey_);
|
|
21
|
-
pkey_ = nullptr;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
18
|
int HybridMlDsaKeyPair::getEvpPkeyType() const {
|
|
26
19
|
#if RNQC_HAS_ML_DSA
|
|
27
20
|
if (variant_ == "ML-DSA-44")
|
|
@@ -66,10 +59,7 @@ void HybridMlDsaKeyPair::generateKeyPairSync(double publicFormat, double publicT
|
|
|
66
59
|
privateFormat_ = static_cast<int>(privateFormat);
|
|
67
60
|
privateType_ = static_cast<int>(privateType);
|
|
68
61
|
|
|
69
|
-
|
|
70
|
-
EVP_PKEY_free(pkey_);
|
|
71
|
-
pkey_ = nullptr;
|
|
72
|
-
}
|
|
62
|
+
pkey_.reset();
|
|
73
63
|
|
|
74
64
|
EVP_PKEY_CTX* pctx = EVP_PKEY_CTX_new_from_name(nullptr, variant_.c_str(), nullptr);
|
|
75
65
|
if (pctx == nullptr) {
|
|
@@ -81,10 +71,12 @@ void HybridMlDsaKeyPair::generateKeyPairSync(double publicFormat, double publicT
|
|
|
81
71
|
throw std::runtime_error("Failed to initialize keygen: " + getOpenSSLError());
|
|
82
72
|
}
|
|
83
73
|
|
|
84
|
-
|
|
74
|
+
EVP_PKEY* raw = nullptr;
|
|
75
|
+
if (EVP_PKEY_keygen(pctx, &raw) <= 0) {
|
|
85
76
|
EVP_PKEY_CTX_free(pctx);
|
|
86
77
|
throw std::runtime_error("Failed to generate ML-DSA key pair: " + getOpenSSLError());
|
|
87
78
|
}
|
|
79
|
+
pkey_.reset(raw);
|
|
88
80
|
|
|
89
81
|
EVP_PKEY_CTX_free(pctx);
|
|
90
82
|
#endif
|
|
@@ -103,9 +95,9 @@ std::shared_ptr<ArrayBuffer> HybridMlDsaKeyPair::getPublicKey() {
|
|
|
103
95
|
|
|
104
96
|
int result;
|
|
105
97
|
if (publicFormat_ == 1) {
|
|
106
|
-
result = PEM_write_bio_PUBKEY(bio, pkey_);
|
|
98
|
+
result = PEM_write_bio_PUBKEY(bio, pkey_.get());
|
|
107
99
|
} else {
|
|
108
|
-
result = i2d_PUBKEY_bio(bio, pkey_);
|
|
100
|
+
result = i2d_PUBKEY_bio(bio, pkey_.get());
|
|
109
101
|
}
|
|
110
102
|
|
|
111
103
|
if (result != 1) {
|
|
@@ -139,10 +131,9 @@ std::shared_ptr<ArrayBuffer> HybridMlDsaKeyPair::getPrivateKey() {
|
|
|
139
131
|
|
|
140
132
|
int result;
|
|
141
133
|
if (privateFormat_ == 1) {
|
|
142
|
-
result = PEM_write_bio_PrivateKey(bio, pkey_, nullptr, nullptr, 0, nullptr, nullptr);
|
|
134
|
+
result = PEM_write_bio_PrivateKey(bio, pkey_.get(), nullptr, nullptr, 0, nullptr, nullptr);
|
|
143
135
|
} else {
|
|
144
|
-
|
|
145
|
-
result = i2d_PKCS8PrivateKey_bio(bio, pkey_, nullptr, nullptr, 0, nullptr, nullptr);
|
|
136
|
+
result = i2d_PKCS8PrivateKey_bio(bio, pkey_.get(), nullptr, nullptr, 0, nullptr, nullptr);
|
|
146
137
|
}
|
|
147
138
|
|
|
148
139
|
if (result != 1) {
|
|
@@ -186,7 +177,7 @@ std::shared_ptr<ArrayBuffer> HybridMlDsaKeyPair::signSync(const std::shared_ptr<
|
|
|
186
177
|
throw std::runtime_error("Failed to create signing context for " + variant_);
|
|
187
178
|
}
|
|
188
179
|
|
|
189
|
-
if (EVP_DigestSignInit(md_ctx, &pkey_ctx, nullptr, nullptr, pkey_) <= 0) {
|
|
180
|
+
if (EVP_DigestSignInit(md_ctx, &pkey_ctx, nullptr, nullptr, pkey_.get()) <= 0) {
|
|
190
181
|
EVP_MD_CTX_free(md_ctx);
|
|
191
182
|
EVP_PKEY_CTX_free(pkey_ctx);
|
|
192
183
|
throw std::runtime_error("Failed to initialize signing: " + getOpenSSLError());
|
|
@@ -237,7 +228,7 @@ bool HybridMlDsaKeyPair::verifySync(const std::shared_ptr<ArrayBuffer>& signatur
|
|
|
237
228
|
throw std::runtime_error("Failed to create verify context for " + variant_);
|
|
238
229
|
}
|
|
239
230
|
|
|
240
|
-
if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, nullptr, nullptr, pkey_) <= 0) {
|
|
231
|
+
if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, nullptr, nullptr, pkey_.get()) <= 0) {
|
|
241
232
|
EVP_MD_CTX_free(md_ctx);
|
|
242
233
|
EVP_PKEY_CTX_free(pkey_ctx);
|
|
243
234
|
throw std::runtime_error("Failed to initialize verification: " + getOpenSSLError());
|
|
@@ -256,7 +247,7 @@ bool HybridMlDsaKeyPair::verifySync(const std::shared_ptr<ArrayBuffer>& signatur
|
|
|
256
247
|
}
|
|
257
248
|
|
|
258
249
|
void HybridMlDsaKeyPair::checkKeyPair() {
|
|
259
|
-
if (pkey_
|
|
250
|
+
if (!pkey_) {
|
|
260
251
|
throw std::runtime_error("Key pair not initialized");
|
|
261
252
|
}
|
|
262
253
|
}
|
|
@@ -11,7 +11,7 @@ namespace margelo::nitro::crypto {
|
|
|
11
11
|
class HybridMlDsaKeyPair : public HybridMlDsaKeyPairSpec {
|
|
12
12
|
public:
|
|
13
13
|
HybridMlDsaKeyPair() : HybridObject(TAG) {}
|
|
14
|
-
~HybridMlDsaKeyPair();
|
|
14
|
+
~HybridMlDsaKeyPair() override = default;
|
|
15
15
|
|
|
16
16
|
std::shared_ptr<Promise<void>> generateKeyPair(double publicFormat, double publicType, double privateFormat, double privateType) override;
|
|
17
17
|
|
|
@@ -32,8 +32,10 @@ class HybridMlDsaKeyPair : public HybridMlDsaKeyPairSpec {
|
|
|
32
32
|
void setVariant(const std::string& variant) override;
|
|
33
33
|
|
|
34
34
|
private:
|
|
35
|
+
using EVP_PKEY_ptr = std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>;
|
|
36
|
+
|
|
35
37
|
std::string variant_;
|
|
36
|
-
|
|
38
|
+
EVP_PKEY_ptr pkey_{nullptr, EVP_PKEY_free};
|
|
37
39
|
|
|
38
40
|
int publicFormat_ = -1;
|
|
39
41
|
int publicType_ = -1;
|
|
@@ -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
|