From 7a5988cea6fa34be4deb6d460e8eec234ee7fa55 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Sun, 27 Jul 2025 16:01:22 +0200 Subject: [PATCH 1/2] crypto: add ML-DSA KeyObject support (keygen, import, export) Note: import in JWK format is not supported yet --- deps/ncrypto/ncrypto.cc | 37 +++++- deps/ncrypto/ncrypto.h | 4 + doc/api/crypto.md | 32 ++++- lib/internal/crypto/keygen.js | 34 +++--- node.gyp | 2 + src/crypto/crypto_keys.cc | 28 ++++- src/crypto/crypto_ml_dsa.cc | 73 ++++++++++++ src/crypto/crypto_ml_dsa.h | 21 ++++ src/env_properties.h | 13 ++- src/node_crypto.h | 1 + test/fixtures/keys/Makefile | 48 ++++++++ test/fixtures/keys/ml_dsa_44_private.pem | 57 +++++++++ .../keys/ml_dsa_44_private_priv_only.pem | 56 +++++++++ .../keys/ml_dsa_44_private_seed_only.pem | 4 + test/fixtures/keys/ml_dsa_44_public.pem | 30 +++++ test/fixtures/keys/ml_dsa_65_private.pem | 88 ++++++++++++++ .../keys/ml_dsa_65_private_priv_only.pem | 87 ++++++++++++++ .../keys/ml_dsa_65_private_seed_only.pem | 4 + test/fixtures/keys/ml_dsa_65_public.pem | 44 +++++++ test/fixtures/keys/ml_dsa_87_private.pem | 106 +++++++++++++++++ .../keys/ml_dsa_87_private_priv_only.pem | 105 +++++++++++++++++ .../keys/ml_dsa_87_private_seed_only.pem | 4 + test/fixtures/keys/ml_dsa_87_public.pem | 57 +++++++++ test/parallel/test-crypto-pqc-key-objects.js | 110 ++++++++++++++++++ .../parallel/test-crypto-pqc-keygen-ml-dsa.js | 66 +++++++++++ 25 files changed, 1087 insertions(+), 24 deletions(-) create mode 100644 src/crypto/crypto_ml_dsa.cc create mode 100644 src/crypto/crypto_ml_dsa.h create mode 100644 test/fixtures/keys/ml_dsa_44_private.pem create mode 100644 test/fixtures/keys/ml_dsa_44_private_priv_only.pem create mode 100644 test/fixtures/keys/ml_dsa_44_private_seed_only.pem create mode 100644 test/fixtures/keys/ml_dsa_44_public.pem create mode 100644 test/fixtures/keys/ml_dsa_65_private.pem create mode 100644 test/fixtures/keys/ml_dsa_65_private_priv_only.pem create mode 100644 test/fixtures/keys/ml_dsa_65_private_seed_only.pem create mode 100644 test/fixtures/keys/ml_dsa_65_public.pem create mode 100644 test/fixtures/keys/ml_dsa_87_private.pem create mode 100644 test/fixtures/keys/ml_dsa_87_private_priv_only.pem create mode 100644 test/fixtures/keys/ml_dsa_87_private_seed_only.pem create mode 100644 test/fixtures/keys/ml_dsa_87_public.pem create mode 100644 test/parallel/test-crypto-pqc-key-objects.js create mode 100644 test/parallel/test-crypto-pqc-keygen-ml-dsa.js diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc index cb6b6ab4a613..3d388fa7f2eb 100644 --- a/deps/ncrypto/ncrypto.cc +++ b/deps/ncrypto/ncrypto.cc @@ -1942,7 +1942,16 @@ EVP_PKEY* EVPKeyPointer::release() { int EVPKeyPointer::id(const EVP_PKEY* key) { if (key == nullptr) return 0; - return EVP_PKEY_id(key); + int type = EVP_PKEY_id(key); +#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5 + // https://github.com/openssl/openssl/issues/27738#issuecomment-3013215870 + if (type == -1) { + if (EVP_PKEY_is_a(key, "ML-DSA-44")) return EVP_PKEY_ML_DSA_44; + if (EVP_PKEY_is_a(key, "ML-DSA-65")) return EVP_PKEY_ML_DSA_65; + if (EVP_PKEY_is_a(key, "ML-DSA-87")) return EVP_PKEY_ML_DSA_87; + } +#endif + return type; } int EVPKeyPointer::base_id(const EVP_PKEY* key) { @@ -1998,6 +2007,32 @@ DataPointer EVPKeyPointer::rawPublicKey() const { return {}; } +#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5 +DataPointer EVPKeyPointer::rawSeed() const { + if (!pkey_) return {}; + switch (id()) { + case EVP_PKEY_ML_DSA_44: + case EVP_PKEY_ML_DSA_65: + case EVP_PKEY_ML_DSA_87: + break; + default: + unreachable(); + } + + size_t seed_len = 32; + if (auto data = DataPointer::Alloc(seed_len)) { + const Buffer buf = data; + size_t len = data.size(); + // TODO(@panva): use OSSL_PKEY_PARAM_ML_DSA_SEED instead of "seed" + if (EVP_PKEY_get_octet_string_param( + get(), "seed", buf.data, len, &seed_len) != 1) + return {}; + return data; + } + return {}; +} +#endif + DataPointer EVPKeyPointer::rawPrivateKey() const { if (!pkey_) return {}; if (auto data = DataPointer::Alloc(rawPrivateKeySize())) { diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h index 28e836f0bdb9..fabec90e67be 100644 --- a/deps/ncrypto/ncrypto.h +++ b/deps/ncrypto/ncrypto.h @@ -910,6 +910,10 @@ class EVPKeyPointer final { DataPointer rawPrivateKey() const; BIOPointer derPublicKey() const; +#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5 + DataPointer rawSeed() const; +#endif + Result writePrivateKey( const PrivateKeyEncodingConfig& config) const; Result writePublicKey( diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 748fdc881788..0b30f468026a 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -1916,6 +1916,9 @@ This can be called many times with new data as it is streamed. * `type`: {string} Must be `'rsa'`, `'rsa-pss'`, `'dsa'`, `'ec'`, `'ed25519'`, - `'ed448'`, `'x25519'`, `'x448'`, or `'dh'`. + `'ed448'`, `'x25519'`, `'x448'`, `'dh'`, `'ml-dsa-44'`[^openssl35], + `'ml-dsa-65'`[^openssl35], or `'ml-dsa-87'`[^openssl35]. * `options`: {Object} * `modulusLength`: {number} Key size in bits (RSA, DSA). * `publicExponent`: {number} Public exponent (RSA). **Default:** `0x10001`. @@ -3816,7 +3842,7 @@ changes: * `privateKey`: {string | Buffer | KeyObject} Generates a new asymmetric key pair of the given `type`. RSA, RSA-PSS, DSA, EC, -Ed25519, Ed448, X25519, X448, and DH are currently supported. +Ed25519, Ed448, X25519, X448, DH, and ML-DSA[^openssl35] are currently supported. If a `publicKeyEncoding` or `privateKeyEncoding` was specified, this function behaves as if [`keyObject.export()`][] had been called on its result. Otherwise, @@ -6150,6 +6176,8 @@ See the [list of SSL OP Flags][] for details. +[^openssl35]: Requires OpenSSL >= 3.5 + [AEAD algorithms]: https://en.wikipedia.org/wiki/Authenticated_encryption [CCM mode]: #ccm-mode [CVE-2021-44532]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44532 diff --git a/lib/internal/crypto/keygen.js b/lib/internal/crypto/keygen.js index 3d1ba4a88341..71b7ee8ce1ff 100644 --- a/lib/internal/crypto/keygen.js +++ b/lib/internal/crypto/keygen.js @@ -19,6 +19,9 @@ const { kKeyVariantRSA_SSA_PKCS1_v1_5, EVP_PKEY_ED25519, EVP_PKEY_ED448, + EVP_PKEY_ML_DSA_44, + EVP_PKEY_ML_DSA_65, + EVP_PKEY_ML_DSA_87, EVP_PKEY_X25519, EVP_PKEY_X448, OPENSSL_EC_NAMED_CURVE, @@ -162,6 +165,16 @@ function parseKeyEncoding(keyType, options = kEmptyObject) { ]; } +const ids = { + 'ed25519': EVP_PKEY_ED25519, + 'ed448': EVP_PKEY_ED448, + 'x25519': EVP_PKEY_X25519, + 'x448': EVP_PKEY_X448, + 'ml-dsa-44': EVP_PKEY_ML_DSA_44, + 'ml-dsa-65': EVP_PKEY_ML_DSA_65, + 'ml-dsa-87': EVP_PKEY_ML_DSA_87, +}; + function createJob(mode, type, options) { validateString(type, 'type'); @@ -278,23 +291,14 @@ function createJob(mode, type, options) { case 'ed448': case 'x25519': case 'x448': + case 'ml-dsa-44': + case 'ml-dsa-65': + case 'ml-dsa-87': { - let id; - switch (type) { - case 'ed25519': - id = EVP_PKEY_ED25519; - break; - case 'ed448': - id = EVP_PKEY_ED448; - break; - case 'x25519': - id = EVP_PKEY_X25519; - break; - case 'x448': - id = EVP_PKEY_X448; - break; + if (ids[type] === undefined) { + throw new ERR_INVALID_ARG_VALUE('type', type, 'must be a supported key type'); } - return new NidKeyPairGenJob(mode, id, ...encoding); + return new NidKeyPairGenJob(mode, ids[type], ...encoding); } case 'dh': { diff --git a/node.gyp b/node.gyp index 4437a34f9cf6..cc0a10c973b9 100644 --- a/node.gyp +++ b/node.gyp @@ -336,6 +336,7 @@ 'src/crypto/crypto_cipher.cc', 'src/crypto/crypto_context.cc', 'src/crypto/crypto_ec.cc', + 'src/crypto/crypto_ml_dsa.cc', 'src/crypto/crypto_hmac.cc', 'src/crypto/crypto_random.cc', 'src/crypto/crypto_rsa.cc', @@ -367,6 +368,7 @@ 'src/crypto/crypto_clienthello.h', 'src/crypto/crypto_context.h', 'src/crypto/crypto_ec.h', + 'src/crypto/crypto_ml_dsa.h', 'src/crypto/crypto_hkdf.h', 'src/crypto/crypto_pbkdf2.h', 'src/crypto/crypto_sig.h', diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc index 458282b1cdfa..804806dc0dd0 100644 --- a/src/crypto/crypto_keys.cc +++ b/src/crypto/crypto_keys.cc @@ -1,12 +1,13 @@ #include "crypto/crypto_keys.h" +#include "async_wrap-inl.h" +#include "base_object-inl.h" #include "crypto/crypto_common.h" +#include "crypto/crypto_dh.h" #include "crypto/crypto_dsa.h" #include "crypto/crypto_ec.h" -#include "crypto/crypto_dh.h" +#include "crypto/crypto_ml_dsa.h" #include "crypto/crypto_rsa.h" #include "crypto/crypto_util.h" -#include "async_wrap-inl.h" -#include "base_object-inl.h" #include "env-inl.h" #include "memory_tracker-inl.h" #include "node.h" @@ -176,6 +177,14 @@ bool ExportJWKAsymmetricKey(Environment* env, // Fall through case EVP_PKEY_X448: return ExportJWKEdKey(env, key, target); +#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5 + case EVP_PKEY_ML_DSA_44: + // Fall through + case EVP_PKEY_ML_DSA_65: + // Fall through + case EVP_PKEY_ML_DSA_87: + return ExportJwkMlDsaKey(env, key, target); +#endif } THROW_ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE(env); return false; @@ -903,6 +912,14 @@ Local KeyObjectHandle::GetAsymmetricKeyType() const { return env()->crypto_x25519_string(); case EVP_PKEY_X448: return env()->crypto_x448_string(); +#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5 + case EVP_PKEY_ML_DSA_44: + return env()->crypto_ml_dsa_44_string(); + case EVP_PKEY_ML_DSA_65: + return env()->crypto_ml_dsa_65_string(); + case EVP_PKEY_ML_DSA_87: + return env()->crypto_ml_dsa_87_string(); +#endif default: return Undefined(env()->isolate()); } @@ -1178,6 +1195,11 @@ void Initialize(Environment* env, Local target) { NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatJWK); NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED25519); NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED448); +#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5 + NODE_DEFINE_CONSTANT(target, EVP_PKEY_ML_DSA_44); + NODE_DEFINE_CONSTANT(target, EVP_PKEY_ML_DSA_65); + NODE_DEFINE_CONSTANT(target, EVP_PKEY_ML_DSA_87); +#endif NODE_DEFINE_CONSTANT(target, EVP_PKEY_X25519); NODE_DEFINE_CONSTANT(target, EVP_PKEY_X448); NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS1); diff --git a/src/crypto/crypto_ml_dsa.cc b/src/crypto/crypto_ml_dsa.cc new file mode 100644 index 000000000000..74d0e9fe467f --- /dev/null +++ b/src/crypto/crypto_ml_dsa.cc @@ -0,0 +1,73 @@ +#include "crypto/crypto_ml_dsa.h" +#include "crypto/crypto_util.h" +#include "env-inl.h" +#include "string_bytes.h" +#include "v8.h" + +namespace node { + +using ncrypto::DataPointer; +using v8::Local; +using v8::Object; +using v8::String; +using v8::Value; + +namespace crypto { + +#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5 +bool ExportJwkMlDsaKey(Environment* env, + const KeyObjectData& key, + Local target) { + Mutex::ScopedLock lock(key.mutex()); + const auto& pkey = key.GetAsymmetricKey(); + + const char* alg = ([&] { + switch (pkey.id()) { + case EVP_PKEY_ML_DSA_44: + return "ML-DSA-44"; + case EVP_PKEY_ML_DSA_65: + return "ML-DSA-65"; + case EVP_PKEY_ML_DSA_87: + return "ML-DSA-87"; + default: + UNREACHABLE(); + } + })(); + + static constexpr auto trySetKey = [](Environment* env, + DataPointer data, + Local target, + Local key) { + Local encoded; + if (!data) return false; + const ncrypto::Buffer out = data; + return StringBytes::Encode(env->isolate(), out.data, out.len, BASE64URL) + .ToLocal(&encoded) && + target->Set(env->context(), key, encoded).IsJust(); + }; + + if (key.GetKeyType() == kKeyTypePrivate) { + auto seed = pkey.rawSeed(); + if (!seed) { + THROW_ERR_CRYPTO_OPERATION_FAILED(env, + "key does not have an available seed"); + return false; + } + if (!trySetKey(env, pkey.rawSeed(), target, env->jwk_priv_string())) { + return false; + } + } + + return !( + target->Set(env->context(), env->jwk_kty_string(), env->jwk_akp_string()) + .IsNothing() || + target + ->Set(env->context(), + env->jwk_alg_string(), + OneByteString(env->isolate(), alg)) + .IsNothing() || + !trySetKey(env, pkey.rawPublicKey(), target, env->jwk_pub_string())); +} +#endif +} // namespace crypto +} // namespace node diff --git a/src/crypto/crypto_ml_dsa.h b/src/crypto/crypto_ml_dsa.h new file mode 100644 index 000000000000..6ecdedaee126 --- /dev/null +++ b/src/crypto/crypto_ml_dsa.h @@ -0,0 +1,21 @@ +#ifndef SRC_CRYPTO_CRYPTO_ML_DSA_H_ +#define SRC_CRYPTO_CRYPTO_ML_DSA_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "crypto/crypto_keys.h" +#include "env.h" +#include "v8.h" + +namespace node { +namespace crypto { +#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5 +bool ExportJwkMlDsaKey(Environment* env, + const KeyObjectData& key, + v8::Local target); +#endif +} // namespace crypto +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS +#endif // SRC_CRYPTO_CRYPTO_ML_DSA_H_ diff --git a/src/env_properties.h b/src/env_properties.h index 230eb9986198..643aebf03b3e 100644 --- a/src/env_properties.h +++ b/src/env_properties.h @@ -115,6 +115,9 @@ V(crypto_ec_string, "ec") \ V(crypto_ed25519_string, "ed25519") \ V(crypto_ed448_string, "ed448") \ + V(crypto_ml_dsa_44_string, "ml-dsa-44") \ + V(crypto_ml_dsa_65_string, "ml-dsa-65") \ + V(crypto_ml_dsa_87_string, "ml-dsa-87") \ V(crypto_x25519_string, "x25519") \ V(crypto_x448_string, "x448") \ V(crypto_rsa_string, "rsa") \ @@ -220,6 +223,8 @@ V(issuer_string, "issuer") \ V(issuercert_string, "issuerCertificate") \ V(iterator_string, "Iterator") \ + V(jwk_akp_string, "AKP") \ + V(jwk_alg_string, "alg") \ V(jwk_crv_string, "crv") \ V(jwk_d_string, "d") \ V(jwk_dp_string, "dp") \ @@ -229,13 +234,15 @@ V(jwk_ec_string, "EC") \ V(jwk_g_string, "g") \ V(jwk_k_string, "k") \ - V(jwk_p_string, "p") \ - V(jwk_q_string, "q") \ - V(jwk_qi_string, "qi") \ V(jwk_kty_string, "kty") \ V(jwk_n_string, "n") \ V(jwk_oct_string, "oct") \ V(jwk_okp_string, "OKP") \ + V(jwk_p_string, "p") \ + V(jwk_priv_string, "priv") \ + V(jwk_pub_string, "pub") \ + V(jwk_q_string, "q") \ + V(jwk_qi_string, "qi") \ V(jwk_rsa_string, "RSA") \ V(jwk_x_string, "x") \ V(jwk_y_string, "y") \ diff --git a/src/node_crypto.h b/src/node_crypto.h index 04d445998542..d34ff52daff8 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -40,6 +40,7 @@ #include "crypto/crypto_hmac.h" #include "crypto/crypto_keygen.h" #include "crypto/crypto_keys.h" +#include "crypto/crypto_ml_dsa.h" #include "crypto/crypto_pbkdf2.h" #include "crypto/crypto_random.h" #include "crypto/crypto_rsa.h" diff --git a/test/fixtures/keys/Makefile b/test/fixtures/keys/Makefile index ffb84ec353b1..7ab719704831 100644 --- a/test/fixtures/keys/Makefile +++ b/test/fixtures/keys/Makefile @@ -98,6 +98,18 @@ all: \ incorrect_san_correct_subject-key.pem \ irrelevant_san_correct_subject-cert.pem \ irrelevant_san_correct_subject-key.pem \ + ml_dsa_44_private.pem \ + ml_dsa_44_private_seed_only.pem \ + ml_dsa_44_private_priv_only.pem \ + ml_dsa_44_public.pem \ + ml_dsa_65_private.pem \ + ml_dsa_65_private_seed_only.pem \ + ml_dsa_65_private_priv_only.pem \ + ml_dsa_65_public.pem \ + ml_dsa_87_private.pem \ + ml_dsa_87_private_seed_only.pem \ + ml_dsa_87_private_priv_only.pem \ + ml_dsa_87_public.pem \ # # Create Certificate Authority: ca1 @@ -855,6 +867,42 @@ ed448_private.pem: ed448_public.pem: ed448_private.pem openssl pkey -in ed448_private.pem -pubout -out ed448_public.pem +ml_dsa_44_private.pem: + openssl genpkey -algorithm ml-dsa-44 -out ml_dsa_44_private.pem + +ml_dsa_44_private_seed_only.pem: ml_dsa_44_private.pem + openssl pkey -in ml_dsa_44_private.pem -provparam ml-dsa.output_formats=seed-only -out ml_dsa_44_private_seed_only.pem + +ml_dsa_44_private_priv_only.pem: ml_dsa_44_private.pem + openssl pkey -in ml_dsa_44_private.pem -provparam ml-dsa.output_formats=priv-only -out ml_dsa_44_private_priv_only.pem + +ml_dsa_44_public.pem: ml_dsa_44_private.pem + openssl pkey -in ml_dsa_44_private.pem -pubout -out ml_dsa_44_public.pem + +ml_dsa_65_private.pem: + openssl genpkey -algorithm ml-dsa-65 -out ml_dsa_65_private.pem + +ml_dsa_65_private_seed_only.pem: ml_dsa_65_private.pem + openssl pkey -in ml_dsa_65_private.pem -provparam ml-dsa.output_formats=seed-only -out ml_dsa_65_private_seed_only.pem + +ml_dsa_65_private_priv_only.pem: ml_dsa_65_private.pem + openssl pkey -in ml_dsa_65_private.pem -provparam ml-dsa.output_formats=priv-only -out ml_dsa_65_private_priv_only.pem + +ml_dsa_65_public.pem: ml_dsa_65_private.pem + openssl pkey -in ml_dsa_65_private.pem -pubout -out ml_dsa_65_public.pem + +ml_dsa_87_private.pem: + openssl genpkey -algorithm ml-dsa-87 -out ml_dsa_87_private.pem + +ml_dsa_87_private_seed_only.pem: ml_dsa_87_private.pem + openssl pkey -in ml_dsa_87_private.pem -provparam ml-dsa.output_formats=seed-only -out ml_dsa_87_private_seed_only.pem + +ml_dsa_87_private_priv_only.pem: ml_dsa_87_private.pem + openssl pkey -in ml_dsa_87_private.pem -provparam ml-dsa.output_formats=priv-only -out ml_dsa_87_private_priv_only.pem + +ml_dsa_87_public.pem: ml_dsa_87_private.pem + openssl pkey -in ml_dsa_87_private.pem -pubout -out ml_dsa_87_public.pem + x448_private.pem: openssl genpkey -algorithm x448 -out x448_private.pem diff --git a/test/fixtures/keys/ml_dsa_44_private.pem b/test/fixtures/keys/ml_dsa_44_private.pem new file mode 100644 index 000000000000..e856bb9ddb8b --- /dev/null +++ b/test/fixtures/keys/ml_dsa_44_private.pem @@ -0,0 +1,57 @@ +-----BEGIN PRIVATE KEY----- +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 +-----END PRIVATE KEY----- diff --git a/test/fixtures/keys/ml_dsa_44_private_priv_only.pem b/test/fixtures/keys/ml_dsa_44_private_priv_only.pem new file mode 100644 index 000000000000..9c7d0d492bbc --- /dev/null +++ b/test/fixtures/keys/ml_dsa_44_private_priv_only.pem @@ -0,0 +1,56 @@ +-----BEGIN PRIVATE KEY----- +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 +-----END PRIVATE KEY----- diff --git a/test/fixtures/keys/ml_dsa_44_private_seed_only.pem b/test/fixtures/keys/ml_dsa_44_private_seed_only.pem new file mode 100644 index 000000000000..96a404dc712e --- /dev/null +++ b/test/fixtures/keys/ml_dsa_44_private_seed_only.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MDQCAQAwCwYJYIZIAWUDBAMRBCKAINu9wITD4mVi5UkAmONcotXzI+sWrxh9G7Qd +t8zISNbm +-----END PRIVATE KEY----- diff --git a/test/fixtures/keys/ml_dsa_44_public.pem b/test/fixtures/keys/ml_dsa_44_public.pem new file mode 100644 index 000000000000..890e65ccedb6 --- /dev/null +++ b/test/fixtures/keys/ml_dsa_44_public.pem @@ -0,0 +1,30 @@ +-----BEGIN PUBLIC KEY----- +MIIFMjALBglghkgBZQMEAxEDggUhAH2Jg9Ucf45KFvShuwbP+c8mBIlhGbNebWAc +TXSqvTYq3GZ72QcMMGhm49FLMSTXOA8n6diBQGWTzt6xQklHaVxz6xkR8CFTM8Is +H7tle1dNsaIXluJq5D04QNyUSUpjXbMemBrt+zGniZCJOgJVHsaOOiXxq5EV2afy +MmcYi/y9nT638Mft9o+1hSObAWnae3A1nzZCY3UMFuKbk3uUcO4dehh2/gzDgCqX +3jB7o4eyGB7iwlOpVYvdI9ZvEbtHcXZnkNXmNbw5zu3zUCn8zi4aVDZ4+wQWduBk +6hXPkjeRwwkgrEhiknE2GAcIklU3UhhtRjaiIjdhYBOM9SY+iRVQfziFJ5eLCm29 +5vJAdAcLVD25AtBVaJBkVBBrem2tT3PyDKQeRrN4PTxURCPwvaNclVtzUtj8x/1Z +OE6X9DdStZMyCv9yKnpC38ql5lQzbDqL7Eu0sPU3ZnVlDRkZoVxSkZHseVY6TCMe +zsARrGCQnOBYWrlna1bW5LxxoIEqbJWu92XAOFc4e2quOyzL9CktmC6fgzJ+0hKI +TxxoO+NdfHiy5/PMqbccLcLdXQRY/ASlHz68rbjdRCEUMt+IcG5ASzfcA6oYJ92d +375LEb5oDf+GUPGI3g/h9zhYeVif0XeusB0pfmBWrfvyReFD3HZZDVG8T7w4uVS/ +dPT3t1ZcBGYU+aLXbV0F+FN3VH6lihIdpDdENpaPMG39zjJgThU38l9HmGv+dPPG +Zyb75Ynn5/kwg8nOlpXGazasAThfDfPiDd2//ET6vkblfPpivjPNx4uBJUAe2eOH +mTJn1MBa6MxBuFqtiujMEP3nRuHVnlFTApaE6RgxTrZS0JQ6ADeJv7Eti28Jv962 +tvZ6FHCvP49dMsvoRDRNmJbodaSC/hqFmY97mDvqxClW7M2moHRNAyf7kHB1HTZw +Ryp+uPnEOsYoV88Wnh8fTsZFljCm8y7SqbmAyv1+xFb5vGE45f6E7K9klk9rrIzS +ZKN9g4UVfjlyyih6ORSaQstmxhS1xhtugoJVL4GUNncl4lnhlTSn3zr9XEOUf0ZV +NjKS4mdW4oMvYYeJbv1wBy340H4X+9Y3jLheJxAVlfmDgIw02gwdoXBqr/13Bl3J +i1h6jloHOTG+pZG9s2LP6MjrJJshcegtD+1K1fJAojeM27k6mTXTY5Vi/0CVJlN7 +5OgqTWtFzdTN7C42aThLGqoEVTy3CAx/o7lYclosprsXvvMjQjhUisYbHHsNPBEP +QxHJD/4iAPKlNoHK3h7bwEuVQORJs9StsqWHuqEt6ID/gl+JzgBH747G9RxyaHJY +IsIy9QbQixYDhPtL59TPp1ThOlmxxh6DSjCTBz9mtx0Auw5g30jsOT+go+V+0Fao +QmOrQBmVhD7t4VLLKeyuVCXjxHQZ/y6xK7eLnMl1ustTwANhZ/BLh2kcn9oIImwx +p86vBNeZv0eCzL2QLhkdGzfYwU5Zv8eGUDKhcCpCHZZZDdUExK2szsjbIFOn4QP9 +tIeRCGE+vi6l6/zrY9yqfDJCQfXN1zRqKObGx00ArdFTTh6MQhT/7MIgCS7Zu+N3 +jrCNTOp2liyKj2oEgoqKLALyWKMMqSUBrzPjd4QbvClK9H/ddSkTe1qkwF0zh2f7 +706nFinrdHRXYdRB7j9061PIUjHImqYRr7ivd094GlriepXApEJ3VrxKPUuhUAe3 +i1PwCyjkN0Tsm1FJF4H8k5Fgz8Wx3XiQoDEb+iINT0oT8sWG+Io= +-----END PUBLIC KEY----- diff --git a/test/fixtures/keys/ml_dsa_65_private.pem b/test/fixtures/keys/ml_dsa_65_private.pem new file mode 100644 index 000000000000..afdf08bec4d9 --- /dev/null +++ b/test/fixtures/keys/ml_dsa_65_private.pem @@ -0,0 +1,88 @@ +-----BEGIN PRIVATE KEY----- +MIIP/gIBADALBglghkgBZQMEAxIEgg/qMIIP5gQg1X9VEr/iXMRwBvnSytEmHrtA ++DpD6FWAUqMrDNlJVBgEgg/AhxPP5LvG83t2fJyfA1TUssJK/ydrzryrCHGZuKFx +mnkukumHBVlGTVKbFcS36vPb0qdJz+7yT4VUEfr2Olvm9/GsrxE8cgRyZu1okCxv +Cb4cNi1BHERK3N3M5g9mbXqUbBqPl5Ug9960/kN2+hJa2+sldDzhmiyw5QWHV6Fv +Hrg4cxggNDEYAQYiADY2YVd2RmJ0FFJTRYd1NBhyJyFUABQjBUFlZGeFEScDJYIG +UoIDQGaEhigFgSYBNBdIRiNDgVcjMQNDIWYHaDcHB3MTV4cXNnR4AHExFVAiJwhi +RQRRYoF4gld2ACAEN1AwEyd2NmcVBINygiFUZjSBAjUlA3QRI2SBdzFBNwgRRDRE +OIRQgoMWhWY3ZDMnQoMzhIaFIxIFBggIGEhkhjEAYABoUkQjEXYFNAFXNjB2UAcI +ZoaGY2cQGFgjcGRTFSdVEiATYDJyhDFYM3UFcwiCgzOHFiM2FEdXgTcEggQhCIhU +NVaIRkIFJHgYGEiGNlBYEgYHUWUDZTQUQRQCcFYVh3ERVRcHAHNEMkJgA2RDaCZW +RXgEYkBzRzSGFQQkSIVCWIRBUgYWgDVzEncDMGgmEIhGcDEBM4BDEmdkAIATQyAh +RHBxJWKGJlRiMEF2ZldRaCchcGE2ETgwUxFTZGd3YxNlcVUBRICDgShhciZGN1Zx +BxGAR4FFRUAAYHBUIlYzA3ByBwAxNjVCcUBgU1EQBTZGIkFBAiMFN1dEMBcRQ1QC +MHM1VSd4SHATEjhWZyYkg4ZIRFSCIjBCYzAmeAUFUSIENFgXOFYCYIZ2VSEDcQNx +JlJkVQFoAUR4QmIVM1RRgThRR3Uyg0UyQ0dVNFA1F3AQV2gTF2U2EkNDNUIFhjET +BYOGSIQjcmJXcnUBEYZmdFhyEYZUNyOIc3RlIAJnKHQ0ETRmF2c0Q4dXMVRVKGFz +Z0CAVRcFN2YGEyhWYRESRIJIEXQIY2YEEQEzFBd1ZIYGNCY2ViJUKAgBd3QBMVJx +OAgihAJzOCYwgYBFBQiCSIaDE4VCIkNEF1gGcxZiR4OFV1hUZxJQNkgTFIRGgGFH +R1eEEidYgSUVF2NUQIE4Q2MxYTJQUwBQM1UUJVZSQYQoOHKFYGaBOHCGZHhBOAZE +ARMxR2gSEYhTVIAXMoRRJiVIgBAlFFhEZlBXEmA3dmVTUFBRcRQDYWZkMCA2VWdx +NxhoFmcnMTBTUnMBJENVZGhIdGBzhAgzgxRmE2IyJkSAVEIlEyRTNYKFUiJhCGeH +hgRxMTVgYoAjCHcmN1NSgVUhUhRUI0ggCINQKFIhUxOFCGIwRghQYQVSNxEUgDBl +cVASNXQ3V0ZWVkAig4YnVFSIcyiIYCFIaBcRUgFBcQMDJCEAVEZndyZYU2EUKAhG +ckADBhYzgFEGhgElAmh3djQIh4ZxFYQBZXQBJUeHBgQEYzdwdBJoczcSZ2ByAUGC +YHdRIkZiR0h0hUJic0N4MGZWhRZ2MAVBOHI1VBFnhGNIUxUTRENVdjZReHBQGIIH +dDgEGBVYdXFYQQMABhKFQzhQNAElAIQFA0ABARgAFwMEFzU1h1EliEElEDUyUFaI +AnUVVhg2NmZRNARmURAnRFcgMQNzg1NRclcUgEUAIyhxYSRFd0RHQDU2h1QoIAQA +AWMHE2IjYHN2gGBVQmZGdVUhZDOCYYVGQyeEB4BShTgFN3ExYlhUBXYxMwgTViB4 +AEVTgVKGJQMAZIYDh3hWQFGEAgYhhEZHSIh1VBcwBBRXaAKCgAQCA0g1YlZnCEAB +dkaBNkYRFTEiAwZCOGA0iIeHhgdXOGcoEHZRARFkFkEWd3d0V2cFCAAQWCRwISdo +NBYAU3VWIYGCMGNEMFMWJCAEEIBlNhCFZxcwSCh3EBgoQ4UjUUEmFGUiMmcVRBAH +GBRiNFgoADgUEBIDR4BQYFFggoNmIQEnOCMwEIJnRHaDIGIEOFcYYRVWcGB4UWFn +MzACU3doRUgIIhJFdFcGJjIWdHWFURQjYgISh2ZxF1cxU3RmFRAxJQdoZogVRkQz +Nic4N4V1AjSHMBVXBxhwEjaIeJ8jA/GwRCv271RCBmT18yHeLpMYgpN5EUIlSApM +bvaIWow/FUJAx+ejUiTiS3BVbeAylfianswTnxsa5kmeSNjgPxAO/U0fSzkyKcCF +v7z+xpg0nrQrLQQyr4s+pnmzgI7kaTMXqG6b0l1R8pWfI/5DzobR4Q5v1Gb4yAfi +NA1uEBFRmzJGNWukgttxygeiYesIqimCUDI5GAEJ+ZIAox/ie4Oi29DXwzQRW+HD +HeK97iLZon1+RFEiKfvzq3d5/NkdigJFZsBTXdFrfPwBcRJTIrUrXt+5qEaz1wB9 +qWsRwFynfnMjhRXClqkUmwBYhB5lrRNHzq7hyVztLR3hykBQ2S+9MdxHsCnO96cg +mGISQsEZXVNpPl7pvQG9oclqkPn0PYD0pHsNpp9P5HQVxFVMSdS69B5nJaLh2Mes +WWhs0WoyfTLK+/MKGCnDKB8SaAIbx9CN9FI+6YSBzJFGUVNiDOIGC0ETaimQDYdc +dcE4vDKIeHlznGWHYTWzfICn3suPyUzf/3Uy+yJgmfaU/oY5NAovObyGuQTXd3bL +Cv1NejFuLShScgfAnu4/JA1gxHwTAVWHrYW8mLbBwCLF9v08aj4Sj7A9660jNxt6 +Vce4P1841aEKbpCsWnWKK1hwsJcSAoAESr/QDyRt2klK5isRrz6OpTKKTuje6/zw +OeEefI2ov84J5wttGCOw1fvOaYKUpEzeq02n4eY4eCJSRjNDxbbhfridmkGwFwPL +GhHOR61BOXtAwxZwKo1v6wql9Kfyi8opKeHLd2QYrkVdX2Tj7yScYWJJ77c1aL8X +sej2dq0LLAxq+xfR3VxSE4PPhY7YybRlwx9azpWPCqoEplRpllhBltf59EYWo7Ah +k95ZFa6ClAXWxhEzcQNUQjjsseXJJmYVv1ssmpUsg3Lc4DbK3yBOqkDMIYBobyUc +Zou8dihrKr5qUdUA80GHtR8S/uSu52Giaiqf1mXWEXzRmtqRXP5V1paWBLxqBwlm +s+gYo86iYtlnfcZEz07ipi2X1FhX90FJx5Dqdje8tFlTo4+x2BtSsI6lu9DZn4ab +/KkSx5CkqNhy/8Kn5buDzQhm7tdEE/vYz7I8DlSd3yqnp/9hPN8umVMX+W3dmgHc +podtFe7bPxrWHXFJotI1XwZnHbnJT8rgehcLHDji/OrkJBdCHc8Gg2xUiOz3Seko +faWL6RHT7zVccP+RhIGkfOZwyDiO0DIzUn3oGX36ntjjkKhpOsGNP5LpClXe2xTW +a41ZLkM4WBeai0HT1RpSuOmKyfzacSlk6wDFKYlNofFUoLyz9hxlBLiLsJajf7HE +kNpVr7M3w8nB2un68+Ipu3/+EgC5xRGllLu51Am9UE84Oei9Tp3FZkptfqId09t8 +9eMDxVnQYUBWS3kUlcQVfMh59N5JecoR+qHYlgSEhA0iLk6pfUWUdsqp14hL+q2f +iXc5j6SCfKTVC42J1ISnldEqTCtjcErQeRPA7Onufy3zuBeNbKhPIaDnm4I+M5FF +SvBH0R3p6i0Yy7uPgn3LBdhXcF22S/F/U2M0oc3tInwJOm/BYWVAwdY6WYkGtc9f +JMfl8g6Q0khmnRRssHqcJAnwa7DZvy0nJjJC0uhpxxHd29nUcgFXHq2IgiPPnxa5 +zLb5uaNSLVi/ybb8x8Nyk0iqfIgnKf7CYebjFnh/Ue0PZf/CZNCR1UYYL9cy6oxO +Hthf9Wc8ENhpYYXzoYObWDoyJa/Uj/0fx7NfSwLc9+9EQBejjQmmOaN+yQ2e2GN5 +nnUpDWEdsdQmDHQQW10tHkP6Dks/kT0gzECM/a3f+nTdABGN9yBet6EAUcjC09fL +MHAikLOB/oTa4lkqCW8bFf121sGGX20KhB1P7fXOhmAHYoJknNJLoiDMDpDJVbma +wRnCml2AS03yOr0ap4RR/qWaYkmPv3fY2wOu0gzpKZrJC0rgbATonpOPzS3+4ta2 +CtfdiipKdk8XvnEhFb8Qk4WNk/54wML9UIIevdInHGjfhF3hoMVhetp+6sxUMAhr ++stAPh3wPnZ7tNMRNzKPmv20ADzeco5mzN1umJGmRspc8dYOIQtqcung7/Z6TUhn +HGPCSQZuvXRDaMv8JpsROvvVLwFtC7+QzyzqR7dL4OxspIzT6GwdsMXc3ArnDfQS +Y0uqzXa67Xt3ho4RB7YxUPRAhpVPHS3v5t6GENom6ZkmsorLZ7mCbyBBSPGzp/ff +mklk0gh5JB5IQOaKIggpBKA+vrq/eGDdPQcUuYkSSxuvvmvlYGiEC4khRS8YlJTz +zQFSGaOnSO1kQApMH6sm7eISuCnTqFY8n3v1mQ8S+O6da0mNKItLpExtUzZNGWJB +PaZTw2CsiuXj3VsCWZKR2MJPSh0JzAl2WJ+W3qxB0qAlwwAFKDyDCzpEuwcyzZYH +rjGrep5LQTOUZbNIHR3guY1z7YY+YgHhyYOd48v7mknW6c2KLAmbZ2AJMlAhUXDm +PDQK1cN3+CKjDeq1IxAq9/j4lgbo+p1IjfWkplkCWKNb5un7rtvqoWT7paemhaJH +clfHTMVswnq1xxl7CFmOnyzmR6dcV54xAJpcWYUwgUQPGaZ1nIjTs11I86IzArJn +WJg9aJ3p9mjIc+4e1cxgXXSfyS1oL8zuFCaHP7R3XM7F0Uuh0F/RIS16TEYBmvRX +AbStjOAlgcWPppIzCSrqWor8O7C/Omsq5EniZgVZHDRnYMEKcb+c+evyaUwL0z5I +N+aSaGN2i5yVudw5kyEQsP2gC5H8pgWNDdL8tvxK2uaTmJN8jIvFjlxDpE6spBRD +MIyQZ7KQ36Us1zCWDVwcmeiVaiMK0v2xaSXt2tmsZHZQ/gxRujaYK7J9EL8rfulf +UgS2S5lxaYfJ8L2VFLBPiXHvdNlX8UMUVdThqsghBbesaLE4i+YhLNUwsRBl1hSi +BPS24gGVnuDAm3mOu9qDpPawx8db5XrLL2KRMwJMlfG2ZtS6a8OSFRfO0NX0VhuS +96mVA++Z3RXlvu7UHTBfbns3QFS2GgbMU3loOZ22+wfEUwgmi3Z3dPnLY1JtDjHu +0WSdbz0l2J1Qw8OszNNtPQmVIw02htIRVNt7OYGF4Doqg+7MmjHb0s9kNZRtCyqC +eFjniIk2z4FSnXPlByLGzrywhHyTz5z4D/YZd+3LlaSihJXH/+F5V0HVRZONzrwh +zMLbwwdhrpupZVlZOakVXRLtwFpf0WCUdZSJPsyuv2kvndCAQpbOKJR1qkVBWmEu +sZKrE4H3tF8Y4NR9j8dbynCsu2y3DtN9oHok/3sS5FH9ml/mC2ojsXBY9exfLaC2 +5/C+6BuzkxxL/NVOWWf8cL7k +-----END PRIVATE KEY----- diff --git a/test/fixtures/keys/ml_dsa_65_private_priv_only.pem b/test/fixtures/keys/ml_dsa_65_private_priv_only.pem new file mode 100644 index 000000000000..e0e628291fa4 --- /dev/null +++ b/test/fixtures/keys/ml_dsa_65_private_priv_only.pem @@ -0,0 +1,87 @@ +-----BEGIN PRIVATE KEY----- +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 +I7FwWPXsXy2gtufwvugbs5McS/zVTlln/HC+5A== +-----END PRIVATE KEY----- diff --git a/test/fixtures/keys/ml_dsa_65_private_seed_only.pem b/test/fixtures/keys/ml_dsa_65_private_seed_only.pem new file mode 100644 index 000000000000..894b948293c3 --- /dev/null +++ b/test/fixtures/keys/ml_dsa_65_private_seed_only.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MDQCAQAwCwYJYIZIAWUDBAMSBCKAINV/VRK/4lzEcAb50srRJh67QPg6Q+hVgFKj +KwzZSVQY +-----END PRIVATE KEY----- diff --git a/test/fixtures/keys/ml_dsa_65_public.pem b/test/fixtures/keys/ml_dsa_65_public.pem new file mode 100644 index 000000000000..233d86a04574 --- /dev/null +++ b/test/fixtures/keys/ml_dsa_65_public.pem @@ -0,0 +1,44 @@ +-----BEGIN PUBLIC KEY----- +MIIHsjALBglghkgBZQMEAxIDggehAIcTz+S7xvN7dnycnwNU1LLCSv8na868qwhx +mbihcZp5eWN7MR0Qj1vyaRxKIiIEepIBC58Im2Z7nmsdcxXq0zkwO6NDcFxxYmhA +fvAJqiSPdw5L7W1DkkwosWt2nZkASlvz7YDAlbWhFbrrwrjhBYTsrmZMn756QcFC +jpM97fjtcKYK0pn/q3T1zhL/GHLEp/sXy2D0i8zwp7e4JyF/38LZIJ1463n/kKox +SpSmRNnuzJJh3lYieIhsu/K91M1YQR7JhRgtGTXPPok95rh+Up9El5javhdhKHq1 +iyALD8S9ihOlK6jwME2x59QebABlr4bFVS5RTyNbNSS1SwTUSeb4Yn+ducTSKTAD +LgGa7Xg/Nu6b3t80KPfxh41oMpI/VczPTxHFZlasWebuNZFF7DOD1mRdvTodrGLJ +idi3YifUXAPdb0Sxtg6hGJvleScCM/LsS9ew1LBAu82LYb7ahgEqtOQm3z0wXr99 +60FL+B9BLc/fVPPVqKE5NBYrBw89bhFIpVP1WNbTeW8iA4rVzX9I5890iBw1FGQE +Z+5ZdGMDtI7ZLE+vLEFty4suhMYZadbXdLKNqmVK21WWrI8gjlbom8G8L63aT90E +bKBuVKpAKpPEZtogqXUEoPO6bMDrHIAPAAvE3MxhzX13PT6swJm7BDyr5mbhOtBy +xs6qUahVC3958mFEFKm3ZiibCkNvS13g1W8st/n5E1A7mKjQtrQWOz5MxyUgPWeI +QwvwRxBcXHpYm0nEjcn+8uJQ1Vp7iTF6UNFkYd1JFD2tNOyHq4YscMbwbxV0Efsr +WIp4sb44q5XBBdcECNQ8xPCozl2GLhT0uGJfB3mR0PuuENEbsZSiET92L42VoeCA +1bxFbOWS82T2xN08HtDeWu4grtAc2Vk3hzW3DKFYhciU6XnNsN71R3iODyQfuR3i +PMbofvcvMrU2rvELTHuLYaETqGo4sw0C65MN3uq8iSd0fOItKJ4uL5mVsiw4pcHC +6jzpECQiAzI6u3sXZlV+bdw7QFuBegqM9M97H+7RpUjFcQO4swqFWxtMtv5dT9oe +31gbhD0+z1pTHT6rvT4+Y6l2OoydJ5Gkf6ae3Q4TtRymnuXnXAWLpx2alUEI0Wfw +7ys2z6w5Obel6vX3UpIgHj9weKp+blPp8ezml+w0aFRJ224hA8pyET0hGPk7N2pT +ybQb/M7s2hjcl9OWfTMmdMPlZQvlsTgXVRLCAKf+Lid5EN1LHxPQyyR/Fj7gyOLe +ItlZzTchZSNF0lKHHP9K1oKqdiNVM0s5FW5JcJLhcsDyOuObuBtlwJX3Xf8KYxRg +viFD14KXkn7KT8FtebAT/iE0voMLb380FS6UUtHrszfe8aPxjITT2eG1vmMmbfM/ +0fG7EPJLX6D/uUVFfss2A7dLQNNUCbGXQS3+Sfx+6j/JeHPFeIT3vwhS9N9qG28Z +gJ1TwD+vbtkmjAZS/Gs45OMBlRUKUKdSajCQmqNlvGSJglXoJD2cYRm8dJ5IFX8h +ceIoTHgzTNvPCWxguAhjjfAtNkPOK0M4cM2RPN2Pa0ntQW9H1DBzLuooQ+Yy3Xpb +bgS+GXSZSoC9uCmSuaOaauP5fUssxgIwdSgEJwpTTgdUsVfPQrSC7vuucG9e7NM9 +6sNvjRdAelFZRkBXm420si0L9gEWhE4f/HAYj7oFTIASFdytSgcDclno8iNWQwrL +LyGRyQhdkkVtx5iXq04gdt3hhxWCki3cVuyxM6ByHNsWRHN6cEeN4Gr43qC9KTXP +hzRVf3NfcIh+058NyB5XfxX06gCD56ijDSGOw/w9A5hTUznZ83IqaisVAdAL3PsK +/Bc9II3kaSx9og0giVrb1o6HmLx05LRrG5QwDOY/cc58BL2X0L4/H01JxcZd3JZA ++nvVdY6w0A5F3zrZfmwyL/T7TMGpnyRbvs9rmxfoCsrVHsDzaNdLocK9kwzXVGsg +mQ0dk9x6ESzfIKCMNmxaDyffC6D3ErpBLygAYx9A4hzXqhRCzWT8f7gseTfmBZFG +cR1gNUFKBoakN0RLXE93PkmX/0wxTj78LOm5sLeJXFqS5rmzgCSxbeifJvBwpFVL +IUXRc7x0Jv9CRLwNybcl2c77D1L+Z43ZNJ8U2ZLb7J6l9OeEUJOcfFPpQWPmyt7j +DqBZx47uOSzKBwlIBiYttnlJu5yxmRIfOGQGzZTy16X2r17zyYdtTluRDgHrkPsl +jR2NsW5gIhzZ2/idlaWXNVcvNrMZ/LphbSnbrkLiEDDrH+Kh6o+TMw2P9TY6zOFp +u1wIiwuDKUNtsPT1jUF0mVr6Nn4/FlJ3xIm6YMkZKA9j9uRkUKrESd/mJJeW5v9l +X3uot6FxzsEMGcChl3wKl8qOIlNVCO3vqguLI+VOuKAfwPzUgWiSa2aENn1Xhk5x +cQOEDDKFgk9FZcAVytAd44bfF2pd1nCPovXLUAdfhq5sMIBtrbXjx7dSCsuvW0mR +NxS5BYnGh4OlccqRunn/K1bJjK36UwEzpxef4hGizWPeNvBxxltIs+L18GhPjJGM +uzStijDxYggdHnPToyETsGsiuC0RL+KpJ1h51UEUptuUa/Q3FRVyo9egLu19Yb+0 +7lR+4duV +-----END PUBLIC KEY----- diff --git a/test/fixtures/keys/ml_dsa_87_private.pem b/test/fixtures/keys/ml_dsa_87_private.pem new file mode 100644 index 000000000000..4ee303b92d98 --- /dev/null +++ b/test/fixtures/keys/ml_dsa_87_private.pem @@ -0,0 +1,106 @@ +-----BEGIN PRIVATE KEY----- +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 +3kDDdVtohnHxepbHfY4aVmkl +-----END PRIVATE KEY----- diff --git a/test/fixtures/keys/ml_dsa_87_private_priv_only.pem b/test/fixtures/keys/ml_dsa_87_private_priv_only.pem new file mode 100644 index 000000000000..71a1267c8845 --- /dev/null +++ b/test/fixtures/keys/ml_dsa_87_private_priv_only.pem @@ -0,0 +1,105 @@ +-----BEGIN PRIVATE KEY----- +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 ++589VN2umDAHnN5Aw3VbaIZx8XqWx32OGlZpJQ== +-----END PRIVATE KEY----- diff --git a/test/fixtures/keys/ml_dsa_87_private_seed_only.pem b/test/fixtures/keys/ml_dsa_87_private_seed_only.pem new file mode 100644 index 000000000000..4a712f03f3d8 --- /dev/null +++ b/test/fixtures/keys/ml_dsa_87_private_seed_only.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MDQCAQAwCwYJYIZIAWUDBAMTBCKAIC2UjpRD21PUuf5krDFC3308sWbuqihDkNZ3 +xItjQrHI +-----END PRIVATE KEY----- diff --git a/test/fixtures/keys/ml_dsa_87_public.pem b/test/fixtures/keys/ml_dsa_87_public.pem new file mode 100644 index 000000000000..c734e59000bd --- /dev/null +++ b/test/fixtures/keys/ml_dsa_87_public.pem @@ -0,0 +1,57 @@ +-----BEGIN PUBLIC KEY----- +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 +S9+/QEkRno/BZDVmjsqhj+gJ6uT0iQ== +-----END PUBLIC KEY----- diff --git a/test/parallel/test-crypto-pqc-key-objects.js b/test/parallel/test-crypto-pqc-key-objects.js new file mode 100644 index 000000000000..1b4f6e6be435 --- /dev/null +++ b/test/parallel/test-crypto-pqc-key-objects.js @@ -0,0 +1,110 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const { hasOpenSSL } = require('../common/crypto'); + +if (!hasOpenSSL(3, 5)) + common.skip('requires OpenSSL 3.5'); + +const assert = require('assert'); +const { + createPublicKey, + createPrivateKey, +} = require('crypto'); + +const fixtures = require('../common/fixtures'); + +function getKeyFileName(type, suffix) { + return `${type.replaceAll('-', '_')}_${suffix}.pem`; +} + +// ML-DSA +for (const [asymmetricKeyType, pubLen] of [ + ['ml-dsa-44', 1312], ['ml-dsa-65', 1952], ['ml-dsa-87', 2592], +]) { + const keys = { + public: fixtures.readKey(getKeyFileName(asymmetricKeyType, 'public'), 'ascii'), + private: fixtures.readKey(getKeyFileName(asymmetricKeyType, 'private'), 'ascii'), + private_seed_only: fixtures.readKey(getKeyFileName(asymmetricKeyType, 'private_seed_only'), 'ascii'), + private_priv_only: fixtures.readKey(getKeyFileName(asymmetricKeyType, 'private_priv_only'), 'ascii'), + }; + + function assertJwk(jwk) { + assert.strictEqual(jwk.kty, 'AKP'); + assert.strictEqual(jwk.alg, asymmetricKeyType.toUpperCase()); + assert.ok(jwk.pub); + assert.strictEqual(Buffer.from(jwk.pub, 'base64url').byteLength, pubLen); + } + + function assertPublicJwk(jwk) { + assertJwk(jwk); + assert.ok(!jwk.priv); + } + + function assertPrivateJwk(jwk) { + assertJwk(jwk); + assert.ok(jwk.priv); + assert.strictEqual(Buffer.from(jwk.priv, 'base64url').byteLength, 32); + } + + function assertKey(key) { + assert.deepStrictEqual(key.asymmetricKeyDetails, {}); + assert.strictEqual(key.asymmetricKeyType, asymmetricKeyType); + assert.strictEqual(key.equals(key), true); + assert.deepStrictEqual(key, key); + } + + function assertPublicKey(key) { + assertKey(key); + assert.strictEqual(key.type, 'public'); + assert.strictEqual(key.export({ format: 'pem', type: 'spki' }), keys.public); + key.export({ format: 'der', type: 'spki' }); + assertPublicJwk(key.export({ format: 'jwk' })); + } + + function assertPrivateKey(key, hasSeed) { + assertKey(key); + assert.strictEqual(key.type, 'private'); + assertPublicKey(createPublicKey(key)); + key.export({ format: 'der', type: 'pkcs8' }); + if (hasSeed) { + assert.strictEqual(key.export({ format: 'pem', type: 'pkcs8' }), keys.private); + } else { + assert.strictEqual(key.export({ format: 'pem', type: 'pkcs8' }), keys.private_priv_only); + } + if (hasSeed) { + assertPrivateJwk(key.export({ format: 'jwk' })); + } else { + assert.throws(() => key.export({ format: 'jwk' }), + { code: 'ERR_CRYPTO_OPERATION_FAILED', message: 'key does not have an available seed' }); + } + } + + const publicKey = createPublicKey(keys.public); + assertPublicKey(publicKey); + // TODO(@panva): test public JWK import + + { + for (const [pem, hasSeed] of [ + [keys.private, true], + [keys.private_seed_only, true], + [keys.private_priv_only, false], + ]) { + const pubFromPriv = createPublicKey(pem); + assertPublicKey(pubFromPriv); + assertPrivateKey(createPrivateKey(pem), hasSeed); + assert.strictEqual(pubFromPriv.equals(publicKey), true); + assert.deepStrictEqual(pubFromPriv, publicKey); + + if (hasSeed) { + // TODO(@panva): test private JWK import + // TODO(@panva): assert private JWK import with mismatched "pub" fails + } else { + // TODO(@panva): assert JWK import with "priv" set to the expanded private key form fails + } + } + } +} diff --git a/test/parallel/test-crypto-pqc-keygen-ml-dsa.js b/test/parallel/test-crypto-pqc-keygen-ml-dsa.js new file mode 100644 index 000000000000..674fbe1eaadb --- /dev/null +++ b/test/parallel/test-crypto-pqc-keygen-ml-dsa.js @@ -0,0 +1,66 @@ +'use strict'; + +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const { hasOpenSSL } = require('../common/crypto'); + +if (!hasOpenSSL(3, 5)) + common.skip('requires OpenSSL 3.5'); + +const assert = require('assert'); +const { + generateKeyPair, +} = require('crypto'); + +// ML-DSA +{ + for (const [asymmetricKeyType, pubLen] of [ + ['ml-dsa-44', 1312], ['ml-dsa-65', 1952], ['ml-dsa-87', 2592], + ]) { + + function assertJwk(jwk) { + assert.strictEqual(jwk.kty, 'AKP'); + assert.strictEqual(jwk.alg, asymmetricKeyType.toUpperCase()); + assert.ok(jwk.pub); + assert.strictEqual(Buffer.from(jwk.pub, 'base64url').byteLength, pubLen); + } + + function assertPublicJwk(jwk) { + assertJwk(jwk); + assert.ok(!jwk.priv); + } + + function assertPrivateJwk(jwk) { + assertJwk(jwk); + assert.ok(jwk.priv); + assert.strictEqual(Buffer.from(jwk.priv, 'base64url').byteLength, 32); + } + + for (const [publicKeyEncoding, validate] of [ + [undefined, (publicKey) => { + assert.strictEqual(publicKey.type, 'public'); + assert.strictEqual(publicKey.asymmetricKeyType, asymmetricKeyType); + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, {}); + }], + [{ format: 'jwk' }, (publicKey) => assertPublicJwk(publicKey)], + [{ format: 'pem', type: 'spki' }, (publicKey) => assert.strictEqual(typeof publicKey, 'string')], + [{ format: 'der', type: 'spki' }, (publicKey) => assert.strictEqual(Buffer.isBuffer(publicKey), true)], + ]) { + generateKeyPair(asymmetricKeyType, { publicKeyEncoding }, common.mustSucceed(validate)); + } + for (const [privateKeyEncoding, validate] of [ + [undefined, (_, privateKey) => { + assert.strictEqual(privateKey.type, 'private'); + assert.strictEqual(privateKey.asymmetricKeyType, asymmetricKeyType); + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, {}); + }], + [{ format: 'jwk' }, (_, privateKey) => assertPrivateJwk(privateKey)], + [{ format: 'pem', type: 'pkcs8' }, (_, privateKey) => assert.strictEqual(typeof privateKey, 'string')], + [{ format: 'der', type: 'pkcs8' }, (_, privateKey) => assert.strictEqual(Buffer.isBuffer(privateKey), true)], + ]) { + generateKeyPair(asymmetricKeyType, { privateKeyEncoding }, common.mustSucceed(validate)); + } + } +} From e3d32072ffaa03a543a57130750513e376d7ab63 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Sun, 27 Jul 2025 21:08:29 +0200 Subject: [PATCH 2/2] crypto: add ML-KEM KeyObject support (keygen, import, export) Note: import and export in JWK format is not supported yet --- deps/ncrypto/ncrypto.cc | 6 ++ deps/ncrypto/ncrypto.h | 3 + doc/api/crypto.md | 27 ++++++- lib/internal/crypto/keygen.js | 9 +++ src/crypto/crypto_keys.cc | 9 +++ src/env_properties.h | 3 + test/fixtures/keys/Makefile | 48 +++++++++++++ test/fixtures/keys/ml_kem_1024_private.pem | 71 +++++++++++++++++++ .../keys/ml_kem_1024_private_priv_only.pem | 69 ++++++++++++++++++ .../keys/ml_kem_1024_private_seed_only.pem | 4 ++ test/fixtures/keys/ml_kem_1024_public.pem | 36 ++++++++++ test/fixtures/keys/ml_kem_512_private.pem | 39 ++++++++++ .../keys/ml_kem_512_private_priv_only.pem | 37 ++++++++++ .../keys/ml_kem_512_private_seed_only.pem | 4 ++ test/fixtures/keys/ml_kem_512_public.pem | 20 ++++++ test/fixtures/keys/ml_kem_768_private.pem | 55 ++++++++++++++ .../keys/ml_kem_768_private_priv_only.pem | 53 ++++++++++++++ .../keys/ml_kem_768_private_seed_only.pem | 4 ++ test/fixtures/keys/ml_kem_768_public.pem | 28 ++++++++ test/parallel/test-crypto-pqc-key-objects.js | 58 +++++++++++++++ .../parallel/test-crypto-pqc-keygen-ml-kem.js | 43 +++++++++++ 21 files changed, 624 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/keys/ml_kem_1024_private.pem create mode 100644 test/fixtures/keys/ml_kem_1024_private_priv_only.pem create mode 100644 test/fixtures/keys/ml_kem_1024_private_seed_only.pem create mode 100644 test/fixtures/keys/ml_kem_1024_public.pem create mode 100644 test/fixtures/keys/ml_kem_512_private.pem create mode 100644 test/fixtures/keys/ml_kem_512_private_priv_only.pem create mode 100644 test/fixtures/keys/ml_kem_512_private_seed_only.pem create mode 100644 test/fixtures/keys/ml_kem_512_public.pem create mode 100644 test/fixtures/keys/ml_kem_768_private.pem create mode 100644 test/fixtures/keys/ml_kem_768_private_priv_only.pem create mode 100644 test/fixtures/keys/ml_kem_768_private_seed_only.pem create mode 100644 test/fixtures/keys/ml_kem_768_public.pem create mode 100644 test/parallel/test-crypto-pqc-keygen-ml-kem.js diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc index 3d388fa7f2eb..7bd46c36fa2f 100644 --- a/deps/ncrypto/ncrypto.cc +++ b/deps/ncrypto/ncrypto.cc @@ -11,6 +11,9 @@ #include #if OPENSSL_VERSION_MAJOR >= 3 #include +#if OPENSSL_VERSION_MINOR >= 5 +#include +#endif #endif // EVP_PKEY_CTX_set_dsa_paramgen_q_bits was added in OpenSSL 1.1.1e. @@ -1949,6 +1952,9 @@ int EVPKeyPointer::id(const EVP_PKEY* key) { if (EVP_PKEY_is_a(key, "ML-DSA-44")) return EVP_PKEY_ML_DSA_44; if (EVP_PKEY_is_a(key, "ML-DSA-65")) return EVP_PKEY_ML_DSA_65; if (EVP_PKEY_is_a(key, "ML-DSA-87")) return EVP_PKEY_ML_DSA_87; + if (EVP_PKEY_is_a(key, "ML-KEM-512")) return EVP_PKEY_ML_KEM_512; + if (EVP_PKEY_is_a(key, "ML-KEM-768")) return EVP_PKEY_ML_KEM_768; + if (EVP_PKEY_is_a(key, "ML-KEM-1024")) return EVP_PKEY_ML_KEM_1024; } #endif return type; diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h index fabec90e67be..f580f85e163a 100644 --- a/deps/ncrypto/ncrypto.h +++ b/deps/ncrypto/ncrypto.h @@ -29,6 +29,9 @@ #endif // OPENSSL_FIPS #if OPENSSL_VERSION_MAJOR >= 3 +#if OPENSSL_VERSION_MINOR >= 5 +#include +#endif #define OSSL3_CONST const #else #define OSSL3_CONST diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 0b30f468026a..42e47892b078 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -1916,6 +1916,9 @@ This can be called many times with new data as it is streamed.