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
package/cpp/ecdh/HybridECDH.cpp
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#include "QuickCryptoUtils.hpp"
|
|
3
3
|
#include <NitroModules/ArrayBuffer.hpp>
|
|
4
4
|
#include <openssl/bn.h>
|
|
5
|
+
#include <openssl/core_names.h>
|
|
5
6
|
#include <openssl/ec.h>
|
|
6
7
|
#include <openssl/err.h>
|
|
7
8
|
#include <openssl/evp.h>
|
|
@@ -12,15 +13,9 @@ namespace margelo::nitro::crypto {
|
|
|
12
13
|
|
|
13
14
|
// Smart pointer type aliases for RAII
|
|
14
15
|
using EVP_PKEY_CTX_ptr = std::unique_ptr<EVP_PKEY_CTX, decltype(&EVP_PKEY_CTX_free)>;
|
|
15
|
-
using EC_KEY_ptr = std::unique_ptr<EC_KEY, decltype(&EC_KEY_free)>;
|
|
16
16
|
using EC_POINT_ptr = std::unique_ptr<EC_POINT, decltype(&EC_POINT_free)>;
|
|
17
17
|
using BN_ptr = std::unique_ptr<BIGNUM, decltype(&BN_free)>;
|
|
18
18
|
|
|
19
|
-
// Suppress deprecation warnings for EC_KEY_* functions
|
|
20
|
-
// These APIs work but are deprecated in OpenSSL 3.x
|
|
21
|
-
#pragma clang diagnostic push
|
|
22
|
-
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
|
23
|
-
|
|
24
19
|
void HybridECDH::init(const std::string& curveName) {
|
|
25
20
|
int nid = getCurveNid(curveName);
|
|
26
21
|
if (nid == NID_undef) {
|
|
@@ -70,41 +65,8 @@ std::shared_ptr<ArrayBuffer> HybridECDH::computeSecret(const std::shared_ptr<Arr
|
|
|
70
65
|
throw std::runtime_error("ECDH: private key not set");
|
|
71
66
|
}
|
|
72
67
|
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
if (!point) {
|
|
76
|
-
throw std::runtime_error("ECDH: failed to create EC point");
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (EC_POINT_oct2point(_group.get(), point.get(), otherPublicKey->data(), otherPublicKey->size(), nullptr) != 1) {
|
|
80
|
-
throw std::runtime_error("ECDH: failed to decode peer public key");
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Create EC_KEY for the peer
|
|
84
|
-
EC_KEY_ptr ecKey(EC_KEY_new(), EC_KEY_free);
|
|
85
|
-
if (!ecKey) {
|
|
86
|
-
throw std::runtime_error("ECDH: failed to create EC_KEY");
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (EC_KEY_set_group(ecKey.get(), _group.get()) != 1) {
|
|
90
|
-
throw std::runtime_error("ECDH: failed to set EC group");
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
|
|
94
|
-
throw std::runtime_error("ECDH: failed to set peer public key");
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Create EVP_PKEY for the peer
|
|
98
|
-
EVP_PKEY_ptr peerPkey(EVP_PKEY_new(), EVP_PKEY_free);
|
|
99
|
-
if (!peerPkey) {
|
|
100
|
-
throw std::runtime_error("ECDH: failed to create peer EVP_PKEY");
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// EVP_PKEY_assign_EC_KEY takes ownership of ecKey on success
|
|
104
|
-
if (EVP_PKEY_assign_EC_KEY(peerPkey.get(), ecKey.get()) != 1) {
|
|
105
|
-
throw std::runtime_error("ECDH: failed to assign EC_KEY to EVP_PKEY");
|
|
106
|
-
}
|
|
107
|
-
ecKey.release(); // EVP_PKEY now owns the EC_KEY
|
|
68
|
+
// Build peer EVP_PKEY from raw public key octets
|
|
69
|
+
EVP_PKEY_ptr peerPkey(createEcEvpPkey(_curveName.c_str(), otherPublicKey->data(), otherPublicKey->size()), EVP_PKEY_free);
|
|
108
70
|
|
|
109
71
|
// Derive shared secret using EVP API
|
|
110
72
|
EVP_PKEY_CTX_ptr ctx(EVP_PKEY_CTX_new(_pkey.get(), nullptr), EVP_PKEY_CTX_free);
|
|
@@ -142,19 +104,15 @@ std::shared_ptr<ArrayBuffer> HybridECDH::getPrivateKey() {
|
|
|
142
104
|
throw std::runtime_error("ECDH: no key set");
|
|
143
105
|
}
|
|
144
106
|
|
|
145
|
-
|
|
146
|
-
if (!
|
|
147
|
-
throw std::runtime_error("ECDH: key is not an EC key");
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const BIGNUM* priv = EC_KEY_get0_private_key(ec);
|
|
151
|
-
if (!priv) {
|
|
107
|
+
BIGNUM* priv = nullptr;
|
|
108
|
+
if (EVP_PKEY_get_bn_param(_pkey.get(), OSSL_PKEY_PARAM_PRIV_KEY, &priv) != 1 || !priv) {
|
|
152
109
|
throw std::runtime_error("ECDH: no private key available");
|
|
153
110
|
}
|
|
154
111
|
|
|
155
112
|
int len = BN_num_bytes(priv);
|
|
156
113
|
std::vector<uint8_t> buf(len);
|
|
157
114
|
BN_bn2bin(priv, buf.data());
|
|
115
|
+
BN_free(priv);
|
|
158
116
|
|
|
159
117
|
return ToNativeArrayBuffer(buf);
|
|
160
118
|
}
|
|
@@ -162,23 +120,12 @@ std::shared_ptr<ArrayBuffer> HybridECDH::getPrivateKey() {
|
|
|
162
120
|
void HybridECDH::setPrivateKey(const std::shared_ptr<ArrayBuffer>& privateKey) {
|
|
163
121
|
ensureInitialized();
|
|
164
122
|
|
|
165
|
-
// Create new EC_KEY
|
|
166
|
-
EC_KEY_ptr ecKey(EC_KEY_new(), EC_KEY_free);
|
|
167
|
-
if (!ecKey) {
|
|
168
|
-
throw std::runtime_error("ECDH: failed to create EC_KEY");
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if (EC_KEY_set_group(ecKey.get(), _group.get()) != 1) {
|
|
172
|
-
throw std::runtime_error("ECDH: failed to set EC group");
|
|
173
|
-
}
|
|
174
|
-
|
|
175
123
|
// Convert private key bytes to BIGNUM
|
|
176
124
|
BN_ptr privBn(BN_bin2bn(privateKey->data(), static_cast<int>(privateKey->size()), nullptr), BN_free);
|
|
177
125
|
if (!privBn) {
|
|
178
126
|
throw std::runtime_error("ECDH: failed to convert private key");
|
|
179
127
|
}
|
|
180
128
|
|
|
181
|
-
// Calculate public key from private key
|
|
182
129
|
EC_POINT_ptr pubPoint(EC_POINT_new(_group.get()), EC_POINT_free);
|
|
183
130
|
if (!pubPoint) {
|
|
184
131
|
throw std::runtime_error("ECDH: failed to create EC point");
|
|
@@ -188,28 +135,17 @@ void HybridECDH::setPrivateKey(const std::shared_ptr<ArrayBuffer>& privateKey) {
|
|
|
188
135
|
throw std::runtime_error("ECDH: failed to compute public key from private key");
|
|
189
136
|
}
|
|
190
137
|
|
|
191
|
-
|
|
192
|
-
if (
|
|
193
|
-
throw std::runtime_error("ECDH: failed to
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (EC_KEY_set_public_key(ecKey.get(), pubPoint.get()) != 1) {
|
|
197
|
-
throw std::runtime_error("ECDH: failed to set public key");
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Create new EVP_PKEY
|
|
201
|
-
EVP_PKEY_ptr pkey(EVP_PKEY_new(), EVP_PKEY_free);
|
|
202
|
-
if (!pkey) {
|
|
203
|
-
throw std::runtime_error("ECDH: failed to create EVP_PKEY");
|
|
138
|
+
size_t pubLen = EC_POINT_point2oct(_group.get(), pubPoint.get(), POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
|
|
139
|
+
if (pubLen == 0) {
|
|
140
|
+
throw std::runtime_error("ECDH: failed to get public key length");
|
|
204
141
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
throw std::runtime_error("ECDH: failed to assign EC_KEY to EVP_PKEY");
|
|
142
|
+
std::vector<uint8_t> pubOct(pubLen);
|
|
143
|
+
if (EC_POINT_point2oct(_group.get(), pubPoint.get(), POINT_CONVERSION_UNCOMPRESSED, pubOct.data(), pubLen, nullptr) == 0) {
|
|
144
|
+
throw std::runtime_error("ECDH: failed to serialize public key");
|
|
209
145
|
}
|
|
210
|
-
ecKey.release(); // EVP_PKEY now owns the EC_KEY
|
|
211
146
|
|
|
212
|
-
|
|
147
|
+
// Build EVP_PKEY via OSSL_PARAM_BLD
|
|
148
|
+
_pkey.reset(createEcEvpPkey(_curveName.c_str(), pubOct.data(), pubOct.size(), privBn.get()));
|
|
213
149
|
}
|
|
214
150
|
|
|
215
151
|
std::shared_ptr<ArrayBuffer> HybridECDH::getPublicKey() {
|
|
@@ -217,26 +153,14 @@ std::shared_ptr<ArrayBuffer> HybridECDH::getPublicKey() {
|
|
|
217
153
|
throw std::runtime_error("ECDH: no key set");
|
|
218
154
|
}
|
|
219
155
|
|
|
220
|
-
|
|
221
|
-
if (
|
|
222
|
-
throw std::runtime_error("ECDH: key is not an EC key");
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const EC_POINT* point = EC_KEY_get0_public_key(ec);
|
|
226
|
-
const EC_GROUP* group = EC_KEY_get0_group(ec);
|
|
227
|
-
if (!point || !group) {
|
|
228
|
-
throw std::runtime_error("ECDH: incomplete key");
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Get uncompressed public key size
|
|
232
|
-
size_t len = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr);
|
|
233
|
-
if (len == 0) {
|
|
156
|
+
size_t len = 0;
|
|
157
|
+
if (EVP_PKEY_get_octet_string_param(_pkey.get(), OSSL_PKEY_PARAM_PUB_KEY, nullptr, 0, &len) != 1 || len == 0) {
|
|
234
158
|
throw std::runtime_error("ECDH: failed to get public key length");
|
|
235
159
|
}
|
|
236
160
|
|
|
237
161
|
std::vector<uint8_t> buf(len);
|
|
238
|
-
if (
|
|
239
|
-
throw std::runtime_error("ECDH: failed to
|
|
162
|
+
if (EVP_PKEY_get_octet_string_param(_pkey.get(), OSSL_PKEY_PARAM_PUB_KEY, buf.data(), buf.size(), &len) != 1) {
|
|
163
|
+
throw std::runtime_error("ECDH: failed to get public key");
|
|
240
164
|
}
|
|
241
165
|
|
|
242
166
|
return ToNativeArrayBuffer(buf);
|
|
@@ -245,43 +169,43 @@ std::shared_ptr<ArrayBuffer> HybridECDH::getPublicKey() {
|
|
|
245
169
|
void HybridECDH::setPublicKey(const std::shared_ptr<ArrayBuffer>& publicKey) {
|
|
246
170
|
ensureInitialized();
|
|
247
171
|
|
|
248
|
-
//
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
throw std::runtime_error("ECDH: failed to create EC point");
|
|
252
|
-
}
|
|
172
|
+
// Build EVP_PKEY directly from public key octets
|
|
173
|
+
_pkey.reset(createEcEvpPkey(_curveName.c_str(), publicKey->data(), publicKey->size()));
|
|
174
|
+
}
|
|
253
175
|
|
|
254
|
-
|
|
255
|
-
|
|
176
|
+
std::shared_ptr<ArrayBuffer> HybridECDH::convertKey(const std::shared_ptr<ArrayBuffer>& key, const std::string& curve, double format) {
|
|
177
|
+
int nid = getCurveNid(curve);
|
|
178
|
+
if (nid == NID_undef) {
|
|
179
|
+
throw std::runtime_error("ECDH: unknown curve: " + curve);
|
|
256
180
|
}
|
|
257
181
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
throw std::runtime_error("ECDH: failed to create EC_KEY");
|
|
182
|
+
EC_GROUP_ptr group(EC_GROUP_new_by_curve_name(nid), EC_GROUP_free);
|
|
183
|
+
if (!group) {
|
|
184
|
+
throw std::runtime_error("ECDH: failed to create EC group for curve: " + curve);
|
|
262
185
|
}
|
|
263
186
|
|
|
264
|
-
|
|
265
|
-
|
|
187
|
+
EC_POINT_ptr point(EC_POINT_new(group.get()), EC_POINT_free);
|
|
188
|
+
if (!point) {
|
|
189
|
+
throw std::runtime_error("ECDH: failed to create EC point");
|
|
266
190
|
}
|
|
267
191
|
|
|
268
|
-
if (
|
|
269
|
-
throw std::runtime_error("ECDH: failed to
|
|
192
|
+
if (EC_POINT_oct2point(group.get(), point.get(), key->data(), key->size(), nullptr) != 1) {
|
|
193
|
+
throw std::runtime_error("ECDH: failed to decode public key");
|
|
270
194
|
}
|
|
271
195
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
196
|
+
auto form = static_cast<point_conversion_form_t>(static_cast<int>(format));
|
|
197
|
+
|
|
198
|
+
size_t len = EC_POINT_point2oct(group.get(), point.get(), form, nullptr, 0, nullptr);
|
|
199
|
+
if (len == 0) {
|
|
200
|
+
throw std::runtime_error("ECDH: failed to get converted key length");
|
|
276
201
|
}
|
|
277
202
|
|
|
278
|
-
|
|
279
|
-
if (
|
|
280
|
-
throw std::runtime_error("ECDH: failed to
|
|
203
|
+
std::vector<uint8_t> buf(len);
|
|
204
|
+
if (EC_POINT_point2oct(group.get(), point.get(), form, buf.data(), len, nullptr) == 0) {
|
|
205
|
+
throw std::runtime_error("ECDH: failed to convert key");
|
|
281
206
|
}
|
|
282
|
-
ecKey.release(); // EVP_PKEY now owns the EC_KEY
|
|
283
207
|
|
|
284
|
-
|
|
208
|
+
return ToNativeArrayBuffer(buf);
|
|
285
209
|
}
|
|
286
210
|
|
|
287
211
|
void HybridECDH::ensureInitialized() const {
|
|
@@ -301,6 +225,4 @@ int HybridECDH::getCurveNid(const std::string& name) {
|
|
|
301
225
|
return nid;
|
|
302
226
|
}
|
|
303
227
|
|
|
304
|
-
#pragma clang diagnostic pop
|
|
305
|
-
|
|
306
228
|
} // namespace margelo::nitro::crypto
|
package/cpp/ecdh/HybridECDH.hpp
CHANGED
|
@@ -28,6 +28,7 @@ class HybridECDH : public HybridECDHSpec {
|
|
|
28
28
|
void setPrivateKey(const std::shared_ptr<ArrayBuffer>& privateKey) override;
|
|
29
29
|
std::shared_ptr<ArrayBuffer> getPublicKey() override;
|
|
30
30
|
void setPublicKey(const std::shared_ptr<ArrayBuffer>& publicKey) override;
|
|
31
|
+
std::shared_ptr<ArrayBuffer> convertKey(const std::shared_ptr<ArrayBuffer>& key, const std::string& curve, double format) override;
|
|
31
32
|
|
|
32
33
|
private:
|
|
33
34
|
EVP_PKEY_ptr _pkey;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include "HybridKeyObjectHandle.hpp"
|
|
6
6
|
#include "QuickCryptoUtils.hpp"
|
|
7
7
|
#include <openssl/bn.h>
|
|
8
|
+
#include <openssl/core_names.h>
|
|
8
9
|
#include <openssl/crypto.h>
|
|
9
10
|
#include <openssl/ec.h>
|
|
10
11
|
#include <openssl/evp.h>
|
|
@@ -91,9 +92,9 @@ std::shared_ptr<ArrayBuffer> HybridKeyObjectHandle::exportKey(std::optional<KFor
|
|
|
91
92
|
const std::optional<std::shared_ptr<ArrayBuffer>>& passphrase) {
|
|
92
93
|
auto keyType = data_.GetKeyType();
|
|
93
94
|
|
|
94
|
-
//
|
|
95
|
+
// Copy to avoid JSI ArrayBuffer GC issues. See #645.
|
|
95
96
|
if (keyType == KeyType::SECRET) {
|
|
96
|
-
return data_.GetSymmetricKey();
|
|
97
|
+
return ToNativeArrayBuffer(data_.GetSymmetricKey());
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
// Handle asymmetric keys (public/private)
|
|
@@ -125,6 +126,42 @@ std::shared_ptr<ArrayBuffer> HybridKeyObjectHandle::exportKey(std::optional<KFor
|
|
|
125
126
|
}
|
|
126
127
|
}
|
|
127
128
|
|
|
129
|
+
// For EC keys, handle raw format (uncompressed point)
|
|
130
|
+
if (!format.has_value() && !type.has_value() && keyId == EVP_PKEY_EC && keyType == KeyType::PUBLIC) {
|
|
131
|
+
size_t len = 0;
|
|
132
|
+
if (EVP_PKEY_get_octet_string_param(pkey.get(), OSSL_PKEY_PARAM_PUB_KEY, nullptr, 0, &len) != 1 || len == 0)
|
|
133
|
+
throw std::runtime_error("Failed to get EC public key size");
|
|
134
|
+
std::vector<uint8_t> buf(len);
|
|
135
|
+
if (EVP_PKEY_get_octet_string_param(pkey.get(), OSSL_PKEY_PARAM_PUB_KEY, buf.data(), buf.size(), &len) != 1)
|
|
136
|
+
throw std::runtime_error("Failed to get EC public key");
|
|
137
|
+
return ToNativeArrayBuffer(std::string(reinterpret_cast<const char*>(buf.data()), len));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30500000L
|
|
141
|
+
if (!format.has_value() && !type.has_value()) {
|
|
142
|
+
const char* typeName = EVP_PKEY_get0_type_name(pkey.get());
|
|
143
|
+
if (typeName != nullptr) {
|
|
144
|
+
std::string name(typeName);
|
|
145
|
+
bool isPqcKey = (name.starts_with("ML-KEM-") || name.starts_with("ML-DSA-"));
|
|
146
|
+
if (isPqcKey) {
|
|
147
|
+
if (keyType == KeyType::PUBLIC) {
|
|
148
|
+
auto rawData = pkey.rawPublicKey();
|
|
149
|
+
if (!rawData) {
|
|
150
|
+
throw std::runtime_error("Failed to get raw PQC public key");
|
|
151
|
+
}
|
|
152
|
+
return ToNativeArrayBuffer(std::string(reinterpret_cast<const char*>(rawData.get()), rawData.size()));
|
|
153
|
+
} else {
|
|
154
|
+
auto rawData = pkey.rawSeed();
|
|
155
|
+
if (!rawData) {
|
|
156
|
+
throw std::runtime_error("Failed to get raw PQC seed");
|
|
157
|
+
}
|
|
158
|
+
return ToNativeArrayBuffer(std::string(reinterpret_cast<const char*>(rawData.get()), rawData.size()));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
#endif
|
|
164
|
+
|
|
128
165
|
// Set default format and type if not provided
|
|
129
166
|
auto exportFormat = format.value_or(KFormatType::DER);
|
|
130
167
|
auto exportType = type.value_or(keyType == KeyType::PUBLIC ? KeyEncoding::SPKI : KeyEncoding::PKCS8);
|
|
@@ -239,54 +276,50 @@ JWK HybridKeyObjectHandle::exportJwk(const JWK& key, bool handleRsaPss) {
|
|
|
239
276
|
|
|
240
277
|
// Export EC keys
|
|
241
278
|
if (keyId == EVP_PKEY_EC) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const EC_GROUP* group = EC_KEY_get0_group(ec);
|
|
247
|
-
if (!group)
|
|
248
|
-
throw std::runtime_error("Failed to get EC group");
|
|
279
|
+
char curve_name_buf[64];
|
|
280
|
+
size_t name_len = 0;
|
|
281
|
+
if (EVP_PKEY_get_utf8_string_param(pkey.get(), OSSL_PKEY_PARAM_GROUP_NAME, curve_name_buf, sizeof(curve_name_buf), &name_len) != 1)
|
|
282
|
+
throw std::runtime_error("Failed to get EC group name");
|
|
249
283
|
|
|
250
|
-
|
|
251
|
-
const char* curve_name = OBJ_nid2sn(nid);
|
|
252
|
-
if (!curve_name)
|
|
253
|
-
throw std::runtime_error("Unknown curve");
|
|
284
|
+
std::string curve_name(curve_name_buf, name_len);
|
|
254
285
|
|
|
255
|
-
|
|
256
|
-
|
|
286
|
+
int bits = EVP_PKEY_bits(pkey.get());
|
|
287
|
+
if (bits <= 0)
|
|
288
|
+
throw std::runtime_error("Failed to get EC key size");
|
|
289
|
+
size_t field_size = (static_cast<size_t>(bits) + 7) / 8;
|
|
257
290
|
|
|
258
291
|
result.kty = JWKkty::EC;
|
|
259
292
|
|
|
260
293
|
// Map OpenSSL curve names to JWK curve names
|
|
261
|
-
if (
|
|
294
|
+
if (curve_name == "prime256v1") {
|
|
262
295
|
result.crv = "P-256";
|
|
263
|
-
} else if (
|
|
296
|
+
} else if (curve_name == "secp384r1") {
|
|
264
297
|
result.crv = "P-384";
|
|
265
|
-
} else if (
|
|
298
|
+
} else if (curve_name == "secp521r1") {
|
|
266
299
|
result.crv = "P-521";
|
|
267
300
|
} else {
|
|
268
301
|
result.crv = curve_name;
|
|
269
302
|
}
|
|
270
303
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
if (EC_POINT_get_affine_coordinates(group, pub_key, x_bn, y_bn, nullptr) == 1) {
|
|
277
|
-
result.x = bn_to_base64url(x_bn, field_size);
|
|
278
|
-
result.y = bn_to_base64url(y_bn, field_size);
|
|
279
|
-
}
|
|
280
|
-
|
|
304
|
+
BIGNUM* x_bn = nullptr;
|
|
305
|
+
BIGNUM* y_bn = nullptr;
|
|
306
|
+
if (EVP_PKEY_get_bn_param(pkey.get(), OSSL_PKEY_PARAM_EC_PUB_X, &x_bn) != 1 ||
|
|
307
|
+
EVP_PKEY_get_bn_param(pkey.get(), OSSL_PKEY_PARAM_EC_PUB_Y, &y_bn) != 1) {
|
|
281
308
|
BN_free(x_bn);
|
|
282
309
|
BN_free(y_bn);
|
|
310
|
+
throw std::runtime_error("Failed to get EC public key coordinates");
|
|
283
311
|
}
|
|
312
|
+
result.x = bn_to_base64url(x_bn, field_size);
|
|
313
|
+
result.y = bn_to_base64url(y_bn, field_size);
|
|
314
|
+
BN_free(x_bn);
|
|
315
|
+
BN_free(y_bn);
|
|
284
316
|
|
|
285
317
|
// Export private key if this is a private key
|
|
286
318
|
if (keyType == KeyType::PRIVATE) {
|
|
287
|
-
|
|
288
|
-
if (
|
|
289
|
-
result.d = bn_to_base64url(
|
|
319
|
+
BIGNUM* priv_bn = nullptr;
|
|
320
|
+
if (EVP_PKEY_get_bn_param(pkey.get(), OSSL_PKEY_PARAM_PRIV_KEY, &priv_bn) == 1 && priv_bn) {
|
|
321
|
+
result.d = bn_to_base64url(priv_bn, field_size);
|
|
322
|
+
BN_free(priv_bn);
|
|
290
323
|
}
|
|
291
324
|
}
|
|
292
325
|
|
|
@@ -370,8 +403,25 @@ AsymmetricKeyType HybridKeyObjectHandle::getAsymmetricKeyType() {
|
|
|
370
403
|
return AsymmetricKeyType::ML_DSA_87;
|
|
371
404
|
#endif
|
|
372
405
|
default:
|
|
373
|
-
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30500000L
|
|
410
|
+
// EVP_PKEY_id returns -1 for provider-only key types (e.g. ML-KEM)
|
|
411
|
+
// Fall back to string-based type name comparison
|
|
412
|
+
const char* typeName = EVP_PKEY_get0_type_name(pkey.get());
|
|
413
|
+
if (typeName != nullptr) {
|
|
414
|
+
std::string name(typeName);
|
|
415
|
+
if (name == "ML-KEM-512")
|
|
416
|
+
return AsymmetricKeyType::ML_KEM_512;
|
|
417
|
+
if (name == "ML-KEM-768")
|
|
418
|
+
return AsymmetricKeyType::ML_KEM_768;
|
|
419
|
+
if (name == "ML-KEM-1024")
|
|
420
|
+
return AsymmetricKeyType::ML_KEM_1024;
|
|
374
421
|
}
|
|
422
|
+
#endif
|
|
423
|
+
|
|
424
|
+
throw std::runtime_error("Unsupported asymmetric key type");
|
|
375
425
|
}
|
|
376
426
|
|
|
377
427
|
bool HybridKeyObjectHandle::init(KeyType keyType, const std::variant<std::shared_ptr<ArrayBuffer>, std::string>& key,
|
|
@@ -555,81 +605,54 @@ std::optional<KeyType> HybridKeyObjectHandle::initJwk(const JWK& keyData, std::o
|
|
|
555
605
|
|
|
556
606
|
std::string crv = keyData.crv.value();
|
|
557
607
|
|
|
558
|
-
// Map JWK curve names to OpenSSL
|
|
559
|
-
|
|
608
|
+
// Map JWK curve names to OpenSSL group names and field sizes
|
|
609
|
+
const char* group_name;
|
|
610
|
+
size_t field_size;
|
|
560
611
|
if (crv == "P-256") {
|
|
561
|
-
|
|
612
|
+
group_name = "prime256v1";
|
|
613
|
+
field_size = 32;
|
|
562
614
|
} else if (crv == "P-384") {
|
|
563
|
-
|
|
615
|
+
group_name = "secp384r1";
|
|
616
|
+
field_size = 48;
|
|
564
617
|
} else if (crv == "P-521") {
|
|
565
|
-
|
|
618
|
+
group_name = "secp521r1";
|
|
619
|
+
field_size = 66;
|
|
566
620
|
} else {
|
|
567
621
|
throw std::runtime_error("Unsupported EC curve: " + crv);
|
|
568
622
|
}
|
|
569
623
|
|
|
570
|
-
// Create EC_KEY
|
|
571
|
-
EC_KEY* ec = EC_KEY_new_by_curve_name(nid);
|
|
572
|
-
if (!ec)
|
|
573
|
-
throw std::runtime_error("Failed to create EC key");
|
|
574
|
-
|
|
575
|
-
const EC_GROUP* group = EC_KEY_get0_group(ec);
|
|
576
|
-
|
|
577
624
|
// Decode public key coordinates
|
|
578
625
|
BIGNUM* x_bn = base64url_to_bn(keyData.x.value());
|
|
579
626
|
BIGNUM* y_bn = base64url_to_bn(keyData.y.value());
|
|
580
|
-
|
|
581
627
|
if (!x_bn || !y_bn) {
|
|
582
|
-
EC_KEY_free(ec);
|
|
583
|
-
throw std::runtime_error("Failed to decode EC public key coordinates");
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// Set public key
|
|
587
|
-
EC_POINT* pub_key = EC_POINT_new(group);
|
|
588
|
-
if (!pub_key || EC_POINT_set_affine_coordinates(group, pub_key, x_bn, y_bn, nullptr) != 1) {
|
|
589
628
|
BN_free(x_bn);
|
|
590
629
|
BN_free(y_bn);
|
|
591
|
-
|
|
592
|
-
EC_POINT_free(pub_key);
|
|
593
|
-
EC_KEY_free(ec);
|
|
594
|
-
throw std::runtime_error("Failed to set EC public key");
|
|
630
|
+
throw std::runtime_error("Failed to decode EC public key coordinates");
|
|
595
631
|
}
|
|
596
632
|
|
|
633
|
+
// Build uncompressed point: 0x04 || x_padded || y_padded
|
|
634
|
+
std::vector<uint8_t> pub_oct(1 + 2 * field_size, 0);
|
|
635
|
+
pub_oct[0] = 0x04;
|
|
636
|
+
BN_bn2binpad(x_bn, pub_oct.data() + 1, static_cast<int>(field_size));
|
|
637
|
+
BN_bn2binpad(y_bn, pub_oct.data() + 1 + field_size, static_cast<int>(field_size));
|
|
597
638
|
BN_free(x_bn);
|
|
598
639
|
BN_free(y_bn);
|
|
599
640
|
|
|
600
|
-
|
|
601
|
-
EC_POINT_free(pub_key);
|
|
602
|
-
EC_KEY_free(ec);
|
|
603
|
-
throw std::runtime_error("Failed to set EC public key on EC_KEY");
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
EC_POINT_free(pub_key);
|
|
607
|
-
|
|
608
|
-
// Set private key if present
|
|
641
|
+
BIGNUM* d_bn = nullptr;
|
|
609
642
|
if (isPrivate) {
|
|
610
|
-
|
|
611
|
-
if (!d_bn)
|
|
612
|
-
EC_KEY_free(ec);
|
|
643
|
+
d_bn = base64url_to_bn(keyData.d.value());
|
|
644
|
+
if (!d_bn)
|
|
613
645
|
throw std::runtime_error("Failed to decode EC private key");
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
if (EC_KEY_set_private_key(ec, d_bn) != 1) {
|
|
617
|
-
BN_free(d_bn);
|
|
618
|
-
EC_KEY_free(ec);
|
|
619
|
-
throw std::runtime_error("Failed to set EC private key");
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
BN_free(d_bn);
|
|
623
646
|
}
|
|
624
647
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
throw std::runtime_error("Failed to create EVP_PKEY from EC_KEY");
|
|
648
|
+
EVP_PKEY* pkey = nullptr;
|
|
649
|
+
try {
|
|
650
|
+
pkey = createEcEvpPkey(group_name, pub_oct.data(), pub_oct.size(), d_bn);
|
|
651
|
+
} catch (...) {
|
|
652
|
+
BN_free(d_bn);
|
|
653
|
+
throw;
|
|
632
654
|
}
|
|
655
|
+
BN_free(d_bn);
|
|
633
656
|
|
|
634
657
|
KeyType type = isPrivate ? KeyType::PRIVATE : KeyType::PUBLIC;
|
|
635
658
|
data_ = KeyObjectData::CreateAsymmetric(type, ncrypto::EVPKeyPointer(pkey));
|
|
@@ -714,20 +737,11 @@ KeyDetail HybridKeyObjectHandle::keyDetail() {
|
|
|
714
737
|
}
|
|
715
738
|
|
|
716
739
|
if (keyType == EVP_PKEY_EC) {
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
if (
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
int nid = EC_GROUP_get_curve_name(group);
|
|
723
|
-
const char* curve_name = OBJ_nid2sn(nid);
|
|
724
|
-
if (curve_name) {
|
|
725
|
-
std::string namedCurve(curve_name);
|
|
726
|
-
EC_KEY_free(ec_key);
|
|
727
|
-
return KeyDetail(std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, namedCurve);
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
EC_KEY_free(ec_key);
|
|
740
|
+
char curve_name[64];
|
|
741
|
+
size_t name_len = 0;
|
|
742
|
+
if (EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME, curve_name, sizeof(curve_name), &name_len) == 1) {
|
|
743
|
+
return KeyDetail(std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt,
|
|
744
|
+
std::string(curve_name, name_len));
|
|
731
745
|
}
|
|
732
746
|
}
|
|
733
747
|
|
|
@@ -793,48 +807,56 @@ bool HybridKeyObjectHandle::initECRaw(const std::string& namedCurve, const std::
|
|
|
793
807
|
throw std::runtime_error("Unknown curve: " + namedCurve);
|
|
794
808
|
}
|
|
795
809
|
|
|
796
|
-
//
|
|
797
|
-
|
|
798
|
-
if (!
|
|
799
|
-
throw std::runtime_error("Failed to
|
|
810
|
+
// Get the OpenSSL group name for this curve
|
|
811
|
+
const char* group_name = OBJ_nid2sn(nid);
|
|
812
|
+
if (!group_name) {
|
|
813
|
+
throw std::runtime_error("Failed to get curve name for NID");
|
|
800
814
|
}
|
|
801
815
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
}
|
|
816
|
+
EVP_PKEY* pkey = createEcEvpPkey(group_name, keyData->data(), keyData->size());
|
|
817
|
+
this->data_ = KeyObjectData::CreateAsymmetric(KeyType::PUBLIC, ncrypto::EVPKeyPointer(pkey));
|
|
818
|
+
return true;
|
|
819
|
+
}
|
|
807
820
|
|
|
808
|
-
|
|
809
|
-
|
|
821
|
+
bool HybridKeyObjectHandle::initPqcRaw(const std::string& algorithmName, const std::shared_ptr<ArrayBuffer>& keyData, bool isPublic) {
|
|
822
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30500000L
|
|
823
|
+
data_ = KeyObjectData();
|
|
810
824
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
825
|
+
int nid = 0;
|
|
826
|
+
if (algorithmName == "ML-KEM-512")
|
|
827
|
+
nid = EVP_PKEY_ML_KEM_512;
|
|
828
|
+
else if (algorithmName == "ML-KEM-768")
|
|
829
|
+
nid = EVP_PKEY_ML_KEM_768;
|
|
830
|
+
else if (algorithmName == "ML-KEM-1024")
|
|
831
|
+
nid = EVP_PKEY_ML_KEM_1024;
|
|
832
|
+
else if (algorithmName == "ML-DSA-44")
|
|
833
|
+
nid = EVP_PKEY_ML_DSA_44;
|
|
834
|
+
else if (algorithmName == "ML-DSA-65")
|
|
835
|
+
nid = EVP_PKEY_ML_DSA_65;
|
|
836
|
+
else if (algorithmName == "ML-DSA-87")
|
|
837
|
+
nid = EVP_PKEY_ML_DSA_87;
|
|
838
|
+
else
|
|
839
|
+
throw std::runtime_error("Unknown PQC algorithm: " + algorithmName);
|
|
814
840
|
|
|
815
|
-
|
|
816
|
-
ncrypto::ECKeyPointer ec = ncrypto::ECKeyPointer::New(group.get());
|
|
817
|
-
if (!ec) {
|
|
818
|
-
throw std::runtime_error("Failed to create EC_KEY");
|
|
819
|
-
}
|
|
841
|
+
ncrypto::Buffer<const unsigned char> buffer{.data = reinterpret_cast<const unsigned char*>(keyData->data()), .len = keyData->size()};
|
|
820
842
|
|
|
821
|
-
|
|
822
|
-
|
|
843
|
+
ncrypto::EVPKeyPointer pkey;
|
|
844
|
+
if (isPublic) {
|
|
845
|
+
pkey = ncrypto::EVPKeyPointer::NewRawPublic(nid, buffer);
|
|
846
|
+
} else {
|
|
847
|
+
pkey = ncrypto::EVPKeyPointer::NewRawSeed(nid, buffer);
|
|
823
848
|
}
|
|
824
849
|
|
|
825
|
-
// Create EVP_PKEY from EC_KEY
|
|
826
|
-
ncrypto::EVPKeyPointer pkey = ncrypto::EVPKeyPointer::New();
|
|
827
850
|
if (!pkey) {
|
|
828
|
-
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
if (!pkey.set(ec)) {
|
|
832
|
-
throw std::runtime_error("Failed to assign EC_KEY to EVP_PKEY");
|
|
851
|
+
return false;
|
|
833
852
|
}
|
|
834
853
|
|
|
835
|
-
|
|
836
|
-
this->data_ = KeyObjectData::CreateAsymmetric(
|
|
854
|
+
auto keyType = isPublic ? KeyType::PUBLIC : KeyType::PRIVATE;
|
|
855
|
+
this->data_ = KeyObjectData::CreateAsymmetric(keyType, std::move(pkey));
|
|
837
856
|
return true;
|
|
857
|
+
#else
|
|
858
|
+
throw std::runtime_error("PQC raw key import requires OpenSSL 3.5+");
|
|
859
|
+
#endif
|
|
838
860
|
}
|
|
839
861
|
|
|
840
862
|
bool HybridKeyObjectHandle::keyEquals(const std::shared_ptr<HybridKeyObjectHandleSpec>& other) {
|