Reland "Add support for ML-DSA `ctx` parameter. Add corresponding tests including a fix of a segfault in setting up context for the VerifyMessage scenario." This is a reland of commit e0455c792569a6826d201a6ed514d1e0a24e077e Original change's description: > Add support for ML-DSA `ctx` parameter. Add corresponding tests > including a fix of a segfault in setting up context for the > VerifyMessage scenario. > > Change-Id: Ie1e24b8e5e38c8856e7b67ff3d97fabc00620429 > Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/88607 > Reviewed-by: Xiangfei Ding <xfding@google.com> > Commit-Queue: Xiangfei Ding <xfding@google.com> Change-Id: I73108c4c52d9f2434feb1287e7696cae5115ec39 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/88747 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/evp/evp.cc b/crypto/evp/evp.cc index 0f22a15..3ac7896 100644 --- a/crypto/evp/evp.cc +++ b/crypto/evp/evp.cc
@@ -339,6 +339,14 @@ 0, (void *)out_md); } +int EVP_PKEY_CTX_set1_signature_context_string(EVP_PKEY_CTX *ctx, + uint8_t *context, + size_t context_len) { + return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, + EVP_PKEY_CTRL_SIGNATURE_CONTEXT_STRING, context_len, + context); +} + void *EVP_PKEY_get0(const EVP_PKEY *pkey) { // Node references, but never calls this function, so for now we return NULL. // If other projects require complete support, call |EVP_PKEY_get0_RSA|, etc.,
diff --git a/crypto/evp/evp_test.cc b/crypto/evp/evp_test.cc index 85302c7..1605199 100644 --- a/crypto/evp/evp_test.cc +++ b/crypto/evp/evp_test.cc
@@ -531,6 +531,14 @@ if (t->HasAttribute("DiffieHellmanPad") && !EVP_PKEY_CTX_set_dh_pad(ctx, 1)) { return false; } + if (t->HasAttribute("Context")) { + std::vector<uint8_t> context; + if (!t->GetBytes(&context, "Context") || + !EVP_PKEY_CTX_set1_signature_context_string(ctx, context.data(), + context.size())) { + return false; + } + } return true; } @@ -904,12 +912,6 @@ return; } - // We do not currently support signature contexts. - // TODO(crbug.com/449751916): Support this. - if (!sig_ctx.empty()) { - return; - } - if (EVP_PKEY_id(key.get()) == EVP_PKEY_DSA) { // DSA is deprecated and is not usable via EVP. DSA *dsa = EVP_PKEY_get0_DSA(key.get()); @@ -932,6 +934,12 @@ ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1_md)); ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, pss_salt_len)); } + if (!sig_ctx.empty() && + !EVP_PKEY_CTX_set1_signature_context_string(pctx, sig_ctx.data(), + sig_ctx.size())) { + EXPECT_FALSE(expect_valid); + return; + } int ret = EVP_DigestVerify(ctx.get(), sig.data(), sig.size(), msg.data(), msg.size()); EXPECT_EQ(ret, expect_valid ? 1 : 0); @@ -989,7 +997,6 @@ // TODO(crbug.com/449751916): We also test these in the low-level ML-DSA code. // The EVP-level tests are not yet redundant: // -// * We can't yet run the tests with a context argument. // * We can't yet run the signing tests with external entropy. // // When/if we add |EVP_PKEY|-based APIs for those, we may be able to remove the
diff --git a/crypto/evp/internal.h b/crypto/evp/internal.h index c948e4d..2ef3571 100644 --- a/crypto/evp/internal.h +++ b/crypto/evp/internal.h
@@ -218,6 +218,7 @@ #define EVP_PKEY_CTRL_HKDF_SALT (EVP_PKEY_ALG_CTRL + 17) #define EVP_PKEY_CTRL_HKDF_INFO (EVP_PKEY_ALG_CTRL + 18) #define EVP_PKEY_CTRL_DH_PAD (EVP_PKEY_ALG_CTRL + 19) +#define EVP_PKEY_CTRL_SIGNATURE_CONTEXT_STRING (EVP_PKEY_ALG_CTRL + 20) class EvpPkeyCtx : public evp_pkey_ctx_st { public:
diff --git a/crypto/evp/p_mldsa.cc b/crypto/evp/p_mldsa.cc index 1f02932..f855799 100644 --- a/crypto/evp/p_mldsa.cc +++ b/crypto/evp/p_mldsa.cc
@@ -18,8 +18,8 @@ #include <openssl/bytestring.h> #include <openssl/err.h> -#include <openssl/nid.h> #include <openssl/mldsa.h> +#include <openssl/nid.h> #include <openssl/span.h> #include "../fipsmodule/bcm_interface.h" @@ -36,6 +36,8 @@ constexpr uint8_t kMLDSA65OID[] = {OBJ_ENC_ML_DSA_65}; constexpr uint8_t kMLDSA87OID[] = {OBJ_ENC_ML_DSA_87}; +constexpr int kMaxContextLength = 255; + // We must generate EVP bindings for three ML-DSA algorithms. Define a traits // type that captures the functions and other parameters of an ML-DSA algorithm. #define MAKE_MLDSA_TRAITS(kl) \ @@ -146,6 +148,11 @@ } } +struct MldsaPkeyCtx { + bssl::Array<uint8_t> context; +}; + + // Finally, MLDSAImplementation instantiates the methods themselves. template <typename Traits> @@ -345,9 +352,30 @@ return Traits::kPublicKeyBytes * 8; } - // There is, for now, no context state to copy. When we add support for - // streaming signing, that will change. - static int CopyContext(EvpPkeyCtx *dst, EvpPkeyCtx *src) { return 1; } + static int Init(EvpPkeyCtx *ctx) { + MldsaPkeyCtx *mctx = New<MldsaPkeyCtx>(); + if (mctx == nullptr) { + return 0; + } + ctx->data = mctx; + return 1; + } + + static void Cleanup(EvpPkeyCtx *ctx) { + Delete(static_cast<MldsaPkeyCtx *>(ctx->data)); + } + + static int CopyContext(EvpPkeyCtx *dst, EvpPkeyCtx *src) { + if (!Init(dst)) { + return 0; + } + MldsaPkeyCtx *sctx = static_cast<MldsaPkeyCtx *>(src->data); + MldsaPkeyCtx *dctx = static_cast<MldsaPkeyCtx *>(dst->data); + if (!dctx->context.CopyFrom(sctx->context)) { + return 0; + } + return 1; + } static int SignMessage(EvpPkeyCtx *ctx, uint8_t *sig, size_t *siglen, const uint8_t *tbs, size_t tbslen) { @@ -364,8 +392,9 @@ OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL); return 0; } - if (!Traits::Sign(sig, &priv_data->priv, tbs, tbslen, /*context=*/nullptr, - /*context_len=*/0)) { + MldsaPkeyCtx *mctx = static_cast<MldsaPkeyCtx *>(ctx->data); + if (!Traits::Sign(sig, &priv_data->priv, tbs, tbslen, mctx->context.data(), + mctx->context.size())) { return 0; } *siglen = Traits::kSignatureBytes; @@ -375,19 +404,39 @@ static int VerifyMessage(EvpPkeyCtx *ctx, const uint8_t *sig, size_t siglen, const uint8_t *tbs, size_t tbslen) { const auto *pub = GetKeyData(ctx->pkey.get())->GetPublicKey(); - if (!Traits::Verify(pub, sig, siglen, tbs, tbslen, /*context=*/nullptr, - /*context_len=*/0)) { + MldsaPkeyCtx *mctx = static_cast<MldsaPkeyCtx *>(ctx->data); + if (!Traits::Verify(pub, sig, siglen, tbs, tbslen, mctx->context.data(), + mctx->context.size())) { OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_SIGNATURE); return 0; } return 1; } + static int Ctrl(EvpPkeyCtx *ctx, int type, int p1, void *p2) { + MldsaPkeyCtx *mctx = static_cast<MldsaPkeyCtx *>(ctx->data); + switch (type) { + case EVP_PKEY_CTRL_SIGNATURE_CONTEXT_STRING: { + if (p1 < 0 || p1 > kMaxContextLength) { + OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PARAMETERS); + return 0; + } + uint8_t *context = reinterpret_cast<uint8_t *>(p2); + return mctx->context.CopyFrom( + bssl::Span<uint8_t>(context, p1)); + } + + default: + OPENSSL_PUT_ERROR(EVP, EVP_R_COMMAND_NOT_SUPPORTED); + return 0; + } + } + static constexpr EVP_PKEY_CTX_METHOD pkey_method = { Traits::kType, - /*init=*/nullptr, + &Init, &CopyContext, - /*cleanup=*/nullptr, + &Cleanup, // TODO(crbug.com/449751916): Add keygen support. /*keygen=*/nullptr, /*sign=*/nullptr, @@ -399,7 +448,7 @@ /*decrypt=*/nullptr, /*derive=*/nullptr, /*paramgen=*/nullptr, - /*ctrl=*/nullptr, + &Ctrl, }; static constexpr EVP_PKEY_ASN1_METHOD BuildASN1Method() {
diff --git a/crypto/evp/test/mldsa_tests.txt b/crypto/evp/test/mldsa_tests.txt index 2732f6f..7156895 100644 --- a/crypto/evp/test/mldsa_tests.txt +++ b/crypto/evp/test/mldsa_tests.txt
@@ -122,6 +122,41 @@ Input = 48656c6c6f20776f726c64 Output = ba4275ff54c22d2d09ea1937a0667362acd44925c6d6965fad350b111d1cbcce68ddbd0e576d1a8810eb4e71623781f32f747d44c8e693749df191682f588906949d97617a4b0ec54ad966818dee88b95f0f28ca24bfc5bfe0c316140b0662c43093ae48b899cc71e5739e9d67095ed987a79b6a0e7aac960c3c4125f0e92bc9435d10bfffae34bb3af05e977ebe0bafcbeb2381c5afe3379667b4c201aebf162dbd0a4bd1baa88fb2f88fa970499a848737d3cf94cc8ce278880a169cad91f304e4e8f1091d4cf39d9a3ab9f88dcc6f3bc4df311a5be0cba290365b3e879527e2a77f0cb6eccc9d85a5e592fb00f3a2e925a26d295a6b82746d7f534c83c35bc4826ee4910216b9a2867032698996fb0e1669b539ccd2ec74d181f4844e8f4d28f9c174316c12dadb54cb1dde7338238a20731c2565bb959f8e3086273ed03abc7ac515728750633083c0b397b29d385d13f5afd2529b32f00dce66c9dc8ea93d99c8b61c5e0ab2fc70de2a8dabdcaf290d53e8fca7561bda8c516ad475e4ec6c7cd2603aa3c8a71d9fa5dc7efc33cf318bebc1f1594e6ea25c69b8f9ce34a65b8ab0ae8dd3538bd267d86c584b8f354d7e4776ed4dd59a73f9e70a1df572f033b69b3eafa5a901e02515472e37258608875ca469de07db71cd6b8dc7edeb3d866ed2d219e44fcb133a066e89d8e3013569ca6f1fee7bf4ae56a6d32a5f3e5a530819c31aadabc8a88503edbea9cdfa3171762e1e8bcebaf9bb6af7e540102d5fc810bbcf1e02ae564e04d9dc55dab0a9392d6c95a317730d9793954da2cb16544d15403d0db01e85881e2d4f1b9b98458e1af0985f98b014f08f200558f2fed7a70c352a27423bedeebb3775c0a1ede9d461d2aea303c09c8b1f73fc37a5b3a01fb24a131574f7eac90c78baa38cebe81e2335dafda20299f76d6a0ba77d2954d11381674f4069f45e133886d64222d92583d5908e3ab6eb6a72cfb41f7dc3e71c1383888f61624bdcaf12fb716de98232ee329af1dd045f30d377234db7bfd11ddab0b3108329e16ce568c8bada39a98df5a5f72a72f063fa4253313a806013f61ce5adbe54cf42180ebf6e496bd4b42aeacf069aaa8e1c231fd037b394d78a69d1742b45bc5784ab8593a198077423c4c357d734f9899cfe9b3b62b6b9c3f4d781b8484a3fd0eea7e8d6945f4ba2b046fee079b7f032bebbc402918daa2aa1c9433dc3bcfbd7f49a5d7a293833c21c1bade3e8a7ec3c83d485529de51b5993cdffe23b770e25acab0ab9fb3059f14952d9464ebfa36a6274d8da317a7b07c2afe38ba28ca942cf7bfaee4020e59911c047b2aa24d1787baae1bc3546364b782358676d75c7698769f1d4a0d5dccade7fcf80e308437f7fc24fdfbf72625abf1b0f534da62cf860da1efd986950e3e19a085999f4d008fce38459c673befcdf2287c1766e106beb4f3175e97812da141330dcb2beb3265e38c8423c19dd50a655c9e8dc969f6367f3383b644d53a26875d53cea26de429266b506e70e7e6832886ed06d81738b0b482bd23bda396eb674ddfdb64803d6c4fae2f040170b5a28923279838b7b876220d02dc7478666f7c3287b1ba4a2f8228e8c491a55ba459805c601b986caea27ee9436f63383351c74d673643b15f6007fc6dc49e337a65a8a96ecd7eef4ad730bf3dc1972fc396703ee26af1156dc4beb46c47d99bb69ebdaf81c2d738d0f70e57a2c7162f5a55242255675f22082aa43f5b3dd862b535b2a15bb815b4e9faf16a302552cd6098d40930dfad7a7c609d6aeade814242a8bf0721c1c26d0d3daa7a638880a6411c6538d80c259d31b639aadaea49563a8d7f5ddb64291d6b086c80d72bfe7d26802cbd20fd6ba5495011e42da1c82483cbe8e37838e73c48f79f65b205476bee600399feda6aaaa939eee12cb34be4e6bdbd18032c85b54a2713551de677a16ca0142ff97b77bc963e8f3c57d91df9b49474b01ca514641842893abc3181caee3f49b635d17daf41bcc4aeb1116ec4b3e78ff1480cf3a5d9c6a154384b88516834d19196976e2ba97cee91f7a0d73f7f8146e58dc0fc8f510511d39d82a7ba531a4abcce6b624035d753a37c5980343cfc7724cf83efb0c33fc4abb5b002241bf57a46b67cb5a4cbd637b2f19bc93b368d97e13c6a62c8443c8222e0a90c3ed1972cc739b824fdf729ed8eca02ad96bd78bf6d2b3d2853e24fa93199ff41635176b31aab2207013d0a9317fa49668dfeb672b8129e6175a2998642ab8e74f0823e3b5480ae80180ca395f5348744a3c7b344891f008aab65914760b5fe852615ad6425216b1c5e777db1a46517cd01a77b277cfa2c6f250c2d68c495fef28feee6e0716817d6b30716f5ca48001805042133eca17a41c2219784ce0f12858ccfd371c77b90966ea04c3996851edf31aef962946628007de5531b06fddf3449f6c552eaf6e16b3e9160e265900b8c8e414732505e02660e123d45a3d6f1b15e56fd759d38e821e27e84967e95c4b0d2a48e008897e655d1b65b76299f1e3074209abe44b37f8786b02df23aa4dcebe512e6312f1a3d6d781d749635247aca897626f5ee688f517df6cfe947ddead820f07fed4bcbe7f1bee3f19117b5666dc123d528f2bf03db346d6afb53804b0681aea98a9479fc6de5ae974d2c0d2055f07ba8a1d2d8b6a7e08a6805bd8634cc190c4988b502f475c36d78c7b3dda0057c818835bbf21c5a7c13bb6fd91cd3cfd76abe4c2ff908a08a3000b9021500ff94b297cec0fb3e51b1cae7026ab4347bfd5b6a641a3d347f45a2a2aacd22e521e00da0c3986c67672c5d7d7e61e7edafc15d42aa42cb37fa8621f79e9096b092efe853ab318b3e4bbd90f20165a1be1d3aa5b3de43751b65abbd952599869778393c4351ab8f534fd49e16547df01c40bfaf56de60b4fb0019bc34177cc8e2236d219fb3c0b84dedae6b88e134280eabd1823420cd1afe6d929774967fd7d885fbad33d89ed9dc5e0eb978eab5d96c50bed5887aa8277880c7b06bf2780cee82ce639a1e3344c88a25102edcc17a4cb48989c4ad6a998726ede31deb0b98107f40858bad7864983f6ecdf0c9761a42751b19d5360daa7fddbbd2e2292638b95c763ca1e747eedef0dd387e9d9ec9e5afee207d8c45703c5befc2de3878d313655ce85ad984250cdf054360f33d41dc193060d42cf9528b1fb91d6ca3395199e25a1a7739eba9a6a4ac2c417ae615940b3eb1b746dd0ecc7b2f7acdff887110115629f70877dafcd7a6625fa1b9e256bc8fe1d66005dbcf12fde0a5fcda5d4f23d58ece91d60eb91274df8d9d17d4a39e63533acf1b317db979b04ca3ab9a0bcba652d0010ca3fcd33ed8f8a62faf42f78b37912d3adb410f20bf16b31359cacc25fb783083a3f065f0a2dd6fe58b8f594e11a87bf0f4c5f5493f334c18b03ebdefebce50228937ec13a8c221b617450486291071f3c14f64f66c927dd4bd623c214ac35433b8a6875cdf00916476eac0f196858aa1484bc1cd45b726d33a965619829b8deaa9d9fa0c3c210f23967ce26a4bdd939cff8aa662f70fb0af97ee44bcb9e2755000a195741d8919e4dcb1a5caae21009f686fa1489c72f16f9fee76b5410ece7f406947f4a19f394a5121da79f3216777b0fee5423328156ecf0b4548dbd5b3f7b526d6b9cfd57576f67dd521c314c2d37474ed0cf732c3b073a101c735a4c4e6b33c9aaa12c91d147ad1075a20287d36c388657614a9c648d8e49cce8cfa282b2a2e8e9da6e4444e4b6aed1bd0ada5009a335cd0500bdae9a01b97f7e8cfe8372398e750de92ee4a524393a19826d19de5e762fb53a88b9b4657e9c6d7d01a4124e3e39532f614aec5cb88d982b78b2ff568017c92f6a1ce5298b5f323b5ee61695038ef0c3a7a339cfac31cf7875a4563046a40e7b35cef1d37d811b342fcbb5373122415befc23cb656a619f7c262c443403b23ba20e341a079918dec6f4f801b92781179ad7ac1951f39ddb0b1f1fb95b28c0f4593a04486f0e0e86bb3b014674879aad10f41e0bad34d40bc817b6fd43c1dde8547882d82e5111e208107e9c9736d16ca77ac7453d7b6c7976a7dd6a4c6c0252185bc9948660a07b66151b09b980d8572ae829ab2f6d900cc63066c4ecb3a0317e8a9acaa8e22a216721f3d69c67843df2fbedd88bc424f761cdf420de4ff2c55b6925b1826c1c4134090d2aae82a7f64a8d428efe1b21097a6fdbc9b8a31c4d46c7b32d478bf5b9181bef8af4d3486958d7c198c46a5ad771090bb64e7fc2bd7677ae7618b861c83c13177075063517eff40cfd52ae56650e9e7035f783bfe8920c754e98470b327909ac2a407e07864710544b8adbc075502c75b5f0fdbca0cde5d94b013141c96b55ae1b60ab63f9e792641690af41b05a78233935fd7f82852ebb2602a10459a709256c41d108c2aeb71925089cc79b121eabd5edc54f3f7c8929685b88ab29700c7fb2f247cd7962c8ce6dc9f79f9358d6a7989d24ccc17d0dbaa0b7fbe73479164181ae7d6b6a02678cce46f74ea2bd387ecb73041817b429a0220e1c3635fe492f5f3a8e2b65c086fe24c375563d7220856dd8f970716d548492964a156554dc88810c3c4f81dcc3ae80243e19679a3be9c9b1b8c707b416e9166c54a568bb9d84728c1a283d9231a12b13688ce2362901342652d66bf44cec223f561d2735d977c6adcf57e9066220d0770fc77fdf6ff367a2f36ae20062887beb88d1b453f267aef9bc763ab716bacb9214c38b95f4f2f3f6c236aa71aef83c1ae4b26133678884476c1d7c6d3e7b99f13e028ac6cebddfae4793f9ae975f3d66b725b500e7c7d2f664eaa0c358deb91cb2d6173394b306749d2bfb2684b985769bdb682e922b75555d38dad1899057a64ef6ea361e4712244d02d0dfec8c3d40770122770c2538d6a14a8462ef18eb705c16e5ba30aa5366447c94869060e4df155f7d01ffda04c1ced0ad5fbe5fdd85856e1e49320319687d31a6e4c7145479f45f43a9b8e9ffe4cbacfad4a21e5445e119df2996cce8b11d0f224efb4f18b544d456e2fb1d96fcd99fc319dbd86720621ac25b490f3611f7e5655bb3940a503c07dbf41f4b87593595a66008808744668371a54ce1b9dfdaa16f90415e57470bc23898d13d8351ba34369e96347da13d012b4eab32ada90668654c5ed2b433716b1b4170f640cf4b40659efcf4150237bbc25f72b248be85cd482b55ce2f5f73e8f02efd2465805b37d12487465ec1085bc6602b71862771af13e13baece4916b1ddef9ce016c92db9fb9e82aee5e1c4e22c45090ad1c19801ce1c541ff3902baea7a12dbcac6ec2d128ac7acb203463921ca6ce1d182d60d553ddecc4a3175eec2e924e9191e0d69aa49ca0b653495b8c62b802e443e669220f2a4047a56ed5cb7431a3387a435070795e6e63d242a74555e97371989c6d0040748e89ac316618d5d6eb7bff8d91e953afbe00464df4e4f6380c273b7ac5934cacb6c3be4da6649c8a5ea12bdf9afa1ec1e5053db7668c10ae2df75c4b3b14525369bf33741525a7630158aca3d3c7da5c1d71d3f63c0c2948a43236968d623c6c163eb757f0c78d6ae682ff4e4b673be07193e8d6c106c92851b393f0523491d5152e06de675fa22ae7bded329836a8ca0b955a59cb575395952c6ea0cb1644f2cada196b96b44ee12115ff9668e32886103d8f8109fac4a2287738ee1d2d4c1c19dab94eaa2757ea32016df60d7286099eb010ba570b5791ce4c54d860b15d56c53a5ddb543b0b602b3a87ca5213aa9647e51b1cb1736697506081240f4f7163a646f2be30e62c617d7572d820a113f96320834a2f43842160511923bd1ef4f723a2ab9b242fffe97cf0199c9f2ebca266a63beea0af279f2d18651b2ea9789d03025857c8aefc5f8bc6ee92ab7c6ffed2606f9c7ef25cb6c96140256a08cc58218869c52f3e5074fe5ace87a86057cc29fc845ff275f1b2dbc5991cbebe4c556b29ce3da3415958f0c9c68a5c664a1da60365ce56b9a4df24ec5d69c6f5a2e685885f6973c0ccd4caf7e000346bdea502b1418c8819e05bb7bee31bbd235819b49c892f7dadade576cb8ca68bda916a598c32ec03cceba2d01a7960f38680facccdaaf05e254dd8c3631a7222d1561c998c54b16f17a425f3247232dca035d545202e1b180340219ce31c66987bc86f983240e7fd2c926e8af77e6ea9f4139ff1edc0c323b67ceadead8f64a8004164d942f6aa65a28544d7205d41aafe62c5bfc6fd9fc322e2a8b620532d00d1add7a0d25a9dbaff90e19de14ac2ca97e83a2d77e63888ba0f7eaf9b18a7f2e5f148d16887580e55e894ae79024385f439acd071494e6469b77d07e763553652a470f3b4bd8bb7968052f3a969dacced51572bd125870849ce3e55359b2e17eabc3153b5f62868ea0ca1f40738488dbe0020c103f53678b9eb1c10000000000000000000000000000000000000000000000000000070a111518202731 +# Valid signature with context +VerifyMessage = ML-DSA-44-Public +Input = 48656c6c6f20776f726c64 +Context = 436f6e74657874 +Output = e11d24772c24efc107ae3abb0149817436f11684d3548748cba19fc0b373ddcb7c8f68f00407d964570c155a9a34823d5b33345a2bb4dfc43d2e178331bc6573f39d634239230cfc160bf03f41d176854dfee5be915ed6c3f4112fff50d8effcc457708261e715fdf0676831989a15cbd16b92fc97bec06c75919c114c167d2bfae8d7dfa384068c0d96a8e6039e755f9b90cb57b4b0e678854a88a8fada69b91bbbea873f81a7489c0e3612774e8a00370b9b9650331bd2184b9037ce340d82b39436dab990f0c176b90421e71fd182bc07ed70e54587bf2b92c038e8794aded666a6c9cdb29d8747c223967c5a283d3be2946584202a021c5264e04587b3c60bb5ec7a73e2d4d7caf4619e388d1beff4ec4bf7d104fee34765ab6a51108660f052a05d16aa46efc49d46ff42d65bbc6521d8a18c8cbe104de453367bae5c72b43854def8222480746003fc8ec4efa2d122965ef9e0e5b3d68c9069af54ef4511036a079d9bb67a43eabec138d37eeaa918bf14815159b0216352a354110d5c835ea9631075317ba617085f2d86215c09c288a584add2809bcc7f50f9071fee5ea2fc08020f2a106fad222155155018f67162855ce624328724b659c645cc30c6382c6fdf48e1c9e8499bf6f8ccd63f06113e3262efd0800d2619d59cd8966d847c2de3854634f3b5e83f84e66cac84e1013b93fe3869f270380ccf8c26591a2635cfa048d1955516560c95ce0c39b0cd7c12c3234b13939386adcf557118f21811c3595151919da2bce155f9c6300703a7209fcd893305486df90a828bc551f23878b72f04fe471ed75982175b74ce135fbdf0c786acdefb09829afdaf7eab308cd8c181345e8f713afd5b433a6be59a4e70b421c216a02a16bf0e927630992211d48d71ac0aec3d0626d84456303c3f35c132571eeafa0106cc7ff333e0d2dcd9352b3cdf36a8fec2a750e5c8ebfeed52a94e5f41c1d295ddc01de6ddbf9df9970460f33fb362b0b94fac9b496459c6ca989e90d53ec8944d1518d7fcc21f1adca0bac93df266820dfbe9c7cbce4b762340ef8ea6464d26c5fd4f2b67b9776548b567d7426511aa9c2fdd19d85206130ab6cf6d7f5115dcb7f53b628b99ed8fa1bd6055764f950deeabae276b419370c4700cd37ca2a34b387d644d4e0ef6a380a5e2d2f32376b4b8752bfc3003c2b67111105b775fd21c3e5ae678f79975097e6c63e759eae6b14d60c9778b4bc31aaa4c9f4fa4911688dc390047aa11f9a998baa652eb9be561cb4039bd9801fd62eedb6f568ff4189dffa4c9a7bc11d9faf26499285098043fe699b565545a930d9ce8f5247eea4c5f6df27f3e050b8d01eee5dd1058efe65190eebeaa0742515d9f8f36bd29e6d84e56d9e41c1a551d3ce6ad7e8967872abd60488d4172c56006eb2db95cb25743287a1d73fb3a36ca4d7f7dce22fd2baf10ad47aeacf82b37dafad7c06a6795be40bd6abfc8f998219f2a0e58531c8ccd1bf3ce66b960741a2da9d36971bad67ee4d75e660e0805e889eab0f0be62b38439476ec289e77176341461b474f66f44120f784de5490529a1f6f013eac2dfbdea11275733f1b1723357740a903085e09e8d61a2e2c84f26ddf95fe630a398329e48cd58cbf358b98b839c7f17893b6e913ee286c976bea3a0bbc58177ce0a35a28c5bb4ac6d9d5ffdb9dc626555a55bea17386237d8ccf2ef60a31393b1f49a37329598f706eeeca9c2d0b02ef13dfa6bb9f1e84517aa51d7d7e85ffbdacf23892962d231f67c142df49d6236630bdb50dad047bc84fec4f517758c3f54c77f5f25fe78a12db9e4dd766198d6014b35cdbab0257cc50c7f9dfa5ac0a88c7d107c8f6bb50dee4d7a3e35cc54fb12572d901f02f4e8bf15cb6fef1910fcd5d54530dbca4046bd9ba3039c4ff97bcbfb6d00a16c1f902a25005c30d3d0d96a9d7116b15f81699614afe0aa448973b6da55c18f20395a15d2ac53c5725e45711f9b3050ca8f409d4776b568afa8d6657668e7d6d3553d23bdbe09cd1957fc5c76fb733b237e60073dfff5d64ad3f03d3116fe1db0ee27c36b9671b0efa079cb0ae0558023ac6a0aa36f1f2d887805658131398f78b4c2fb2e0bfc4a37e444015879f0db10abd5b56d5993a3ccc0798651c0b85b658285cd00e898be4406a431e29d861379c26ed26cee7f23c05fba0519fa6d0336120dffd6d441d7de14233ff6c345425b852e1cbef6ac4d442e6f121975b912b9e60538b5efe74c3df3861671b54d96d1d512725fe63b511c4d90261577f8a992746cfe6a4e1426a3d9fcbdb3098a626681ed5c41c3158667708c321a515a978c47c337b1d9cdf6be83fae368d57843baaea2b8b7a94398a8fcdb3b3e39c55a8feceae53f4b2b8967f5a7f671d7cff584596682ed7436979ee9e8610bdcdd0c065b39e22b3fefdb8ebbe7ea59ddb2058980f8c186ec95428a8cea2c41376312a073543283f2c8a970b11f1f31dc531748292cf198c63b2f21996f2bf769d397083f5f7c2da8952b38a199a2fa2698e156cc5550f123d99d4f65852fab97e184f0f615ac419af60c236f4e1c3c209b4eda22ec47c963d6b5318031cda0b1ce9dd0876b0a011d9d1a8a1233c38538581401dcb8766c4c9147d257828a0068a91e458e3a312e398c2b1affcbd7a702efdcb3f79a28d131667545f2ac3d04fefee0228f257e689a85fb92f528d901768a2dfda51f65ad31e1b781759cde2a44adf0a4b84639a8160bf863445f94a04ab7885fa247fe057c161246f1202bad84345aea9e34b77ef93fe01d090f49e1ba3e214acfea26bc04e4bb2ef2f4fa2af4751a873573ee273d8ab7f1d59aad74c8da98232e2562966b6816f01c1db37c0b5a55710011656ff76f8eb4bbba1e5875e954f1dc43bbd0d77b09cfbc57890acedf796507d31fee63305cc97209964cc7897befd20db3d6203a317bc8769b8b0081016f2180eb3b40d24ac1458d0afb8034b8babe87c91ead17f25715104be58a526409e8f5053b67e48d7de17a2f81f68a679a6d9192120eda7564c7970c88d4aa266f7063d6b24de7b402c69d9d14f8d51b3bdff45e952c45ead4e729d195f930870fda380f64085011fff63caca5e79d1dae0b2b0dad7e01c4b7b2714b20d3bb69dcee4fe9e0412420b55abba95bacbc1b1fe498474d8d3a5396968b057b8b5081ddb57eaae581da0a1b482879cdc1bda82fe83d4007375831cf06bcd334ac42c780cb91121eb4021f39f9292a6a023b1010b35d378a798601cd4a6cfebc0f45b1e7879a8f884e3d465a6680a0b8cbd5e0f210111a40464a586184859299a5e329384751b5c5c6eceef1ff1d3864879398a1b5b7cbd80000000000000000000000000000000000000000000000000000000000000000000b19242f + +VerifyMessage = ML-DSA-65-Public +Input = 48656c6c6f20776f726c64 +Context = 436f6e74657874 +Output = 3a1f0e89fa72e489e2c4c1607b0f22ad03513725660d1ed7cc9a6b83580247a101ff45480e4ba49b1feb3bde46952139d3e1d34d7da0124e8ffa05bd19698be57ffbd5c2411f01a0588898cf4af2b3f3e1fd83e8befe03806d91869eb496c8ce989761da7190e036eb2bd14a8f9e195d5ab8a1b2b11dd56a098c1e7ec6d508856aec98b74850e1b934600b8b7d33cea5f79877cb9b1452a2fbf5fe09651c83c2b965aeb496a2a4edacd4f6f39d56cde44c2f99c2f0b548501220f553a1ad14c6d8a970d1cd6dabd4356568621d22c70dbbb21dab61c10876e34fb20d3f012eec956cdc9ed81c98e2810c218dfbe1de709ceec9dc2eb2590d31fe9855f8a1d14849f9df5120bda5a0392fd6cd93e2e8e5f80e6b30f45e9b409f9e251a0ca2aa8ab99394e9190f3c2cbd1bda77b49f9ac887e7ceefc333cbc49d080726cf373753addfd13fd4204f12c07a21fe2ae5d513eff664c0ae4780f4d4f87a807ec63efe098e7d196223276f4564efdd574402c77390d2cd72f4785501f89175f6d38768b6c77838723cfa66d42e3556077039ee8fb363b67c174fb70f78008229263350c14b54fd9361a9cdb29fdc57909c757f96f9f2c13905f44c3e40a16a92b0fe509ae9cc3647afeedb032464b176b6a1afa78df4fd6bb765e37071172bef2b6d045b9a51701d111b60d0a639c0ba034d5c6b4c146d079a340fe53e9cace778a995ceb2d39f302f066097eec6f65f775a5e803f10af031dcb3eecb2bc4939f478c5fdb96e0513d9ea90ee2cd46ba7fd45f88e8c38a23e06fc5b2c624708a5dee0d00bcd976a8f75e35c80caec5531ff4ef8bb735cbe7ffce86290eef23248b19272692b758bba1de7a66c63a58315e48f5b127849c759d185908a730f1f29272003e6491a0b4aa9446da297338e04a60bd5f8413778aa08cc0d146ba76a5ebadc775af2b0b3976acb54de8910417f857499d8395be90d207615dd061317e5385b886281699e484a7f958715dfdf3ec30d5423d94e0d1657a24478967513fc741fce01f848f9fdb8fa407b7cda2f7a0eed64d9795a2bcc9e12c1d09b4d71cdc9dc3fd2ba82251f0a9fe5ff32732d2306900184e4296bf4b5b92c106d72a638c5f6713f49a7099786b32ba7a8081aaf0ca40f9919e0645fb255c8a7f4aa672999ab84a19b9d759ce478b7492b48a83eb9bde46e7c5ea1883d03487ba01c8a9c4c798a765b18b311115d02911dbaa5566190006ba40f5ee86bc22eda4ca3d0e8fee49b1a61c4057d95cf797c30a7e06d1012c1af3622629de1765d3bd928df0cb9cc7e30299c5148f782af4871556a0ec4358019ef6a434ea3e0292e97c714fbdb3ab14837257947eb7adc9c1d682123a016432e1eea5afd039bfbade397a9360b674832d2c55d521820c0cbe68bdfbba6eab8189aeeec781362fb289883d2a2fe87e287b8d940ad6a4136b7b388b38b0913f2fba42dd079cac04a071636b7e5bca67b44860cdd9e5f9cd77f07e524e9491addac1c6a66dedf5a4f814fa54eb9586bfcb1a6d4a1a166b1074d28a9915167ac4cf279e8d22555df57cfba8bde251483d9b2aef08a180ff74edcbc1bc2219f01fef23d77fcdc1d41ebe683ec96a75a4784945335736770f63a5f000da542958558b5ee375c1c16a109d488d8b17daf2450f35e0ae08fecc139bf8d5f51f1d9a1cd738ac3bb1e91a3bcdbf79c6bcc9a09eb11bc97a7062fc4e4e1c2e796241dc42481d3dc89b31d2337e8cf727c43dd393bb738710ef7ff96521dd92be410f295c765a823e1984e63c534d5f040753715edee4c3f0c78cd468eb9322ae8d5aa92b88bb172082cd08148a8d208d21dac81f0cc516d08f9c0b7097d91bf73badf049b62085328e347e20cd6ac26c64be5271f4761a16ce90ec9c58b2b71c998404e1411f1a1c5c6a6fcbf260eb3e325d1f70132b5f41a279b082712005347fc7d8a6a960ac1ffefb33de83cd6bc704eedd8ee937487635b696975a7156473937d7c301579c4e531170a6d109d50185693d9dbea24781f391fdc1baca492f00867d362797392af50da481552b86f323bd297b6a0cdce20287f0ee6119be14905ec55851768ef95d50130965c6877ee8d91e1fe19fdbef7c80ef7f93968a0d717c354f071bc8cde4d69c84a6e876a261e620a0f7c959da0c638b32d58325b13ddc9fbf566e1f411edc9b38a2bd031a7225551c4bc596958b1c22d5ecfabd2c09448417ba8568938a1cd02068d4ae3e0821dc96247ca6b704a0af99acbe5ec66b28b7c461da48743ccf387771a15eaca6392341dc4657d5c4c986b0648e712ec50f22e3d68b272dd9c34b63aec5686daa5a0f9bd259138b6d967cfa368c04c48657b2de2133b4c47147877e080d5588b09ab0b19d947b6554aaf43601b1c7384707f3091331a0583abc41bf448283eaa4bb001a44836de63e66eef64b04d82ad32c4369bdca012df554097e493e77e1b26acd103b564b6e8134012aec9cdc52eea80955a76d1beb2cb87782157adeadf2ae6c6a4b49c031d6769be9b42e6f85c8c5a6d61947f931c321b45dc34822c8523408c77bfe32048719537361fe6a1c9a8f3467cf5529dd597e19285304c716f9144debdfbeeb16ed742fa17440e02cdae4816699faab22cec162054df5d6ceb6394cadadf5d60abfe5c1dbb3790e4a98bcd9a84f6d4aa8e5934d80b40d8da632ce6640ceb070ee6034947a094337c013075c1a1267a95c820b7eb5f2aaaf20736f09502faa043cecc39f2ce7ebc0a14f846e38fbd514b935d2a46dbeb778223f20694985d27273a9be7e1be3c7dc9b8af87c58d35f4cf6559f48d27cc7eb1c050c76d85edd69995ea3b2e54868556758014ea18e18c11db61c56436ca2ac66260635d927a72cd707ff5e533704477bf9f578848196e311369842846588febd3a229d0b4fc04a5848d98ca55c3996e34d2154efe73a63f052da1ceb72bcd844dad8a4a4546cc6f94b2029b4e2c8a65d2b50673668e7abce6f054d50145b744b8103592bcb4804b446e1b7f4910843f5cba5a34e5b17309eb287c39bb98f6c220024e7582367d3e5e83737ef64944437c9d462c94f61c754a887ae4e5f1d2d64497d2b7fe8e885af00e8e8ad2d998b921a654616866e492a32742f319efef91df3f2e3d2697a4a12b107ad94da1d64ee6c67f0e9cf5aadae3eef52a22ebe342199cbcad564cd11685e0678ea3c91bcb67278ae4a6ce5664e39e86c3233cbdaf812516aa824754f6493cd5559848a71275b35f503ac84ccec4fd172b09f9ac40543a54059eed72f77eaa8d56645986ec8767e78c2df76f33e549b561b977fc5daec7436735a46956077b661fd05dfa124fc30165d5a14d9215e75c3134cae2a7a8fa490dad2fa745003c2d74d83ed13db927f4dc5cfd856c758b39915ccfb695c915c3ec5f3257ec38a0ddfa1401c3527ca271c856f2b00fc4f44416f7a387aae1e88ca212d81a6b4ca1e61c1ed2809e41e78ad8fb170ba1e0b138f061fde62eb7cce2eb8ae434b37fd4eb78b85990e7f6d21b32b4cf9dc57fd9b46fdbaaaf25139315a99419cfca963b19c3fc2923c041bf43ccc6147c3f9736a162a20152ee40effd6a3a29523d77dcb14a70b4ab512bfd11980e30bfd77304eec045d50b5923e22def0c83439e4d0326d9a20e53c43797dcbf17014f80ebc2b66fa6045a8b402b7fb182b43bb8ed6d569568732723b0f7807ac79bb676f35221258fb1283bf7c275b2872f2c625b7e1211b381454ce044a3e8a634488ece71e6fc58b84668aa744302b8a061b5674cdad160c2d9ef600385998c9f002fde9c829a6be84fd27b8cdb8f328064210918f28189e0dba18535d978efa8a8157cd5a477db7e3c909a54ae886008a65ebdc3eb3f06b89ca21ac3981d064fa15f01b1ce801a2c515af3298c4fd5979e6a651cec9ca50476773a755f96478397dda65db9fc32b2166dec033bb46fbad0edfd03f3c543e144c15dbdca9b83f2c3f0d5357cab1180472c7264317b319ad50dbd476b8f6545d86e5e399cf6177461141ce2e438db3100a0bdf957266c9758f7039817141bab0b3ea234c317554a1b30081eeaa6ccf3406a2a3e38d0376d2c50ff03e770be90cc3bb1c05ae9ab546e21d5f1cad5a4df5b53684789e534f2983bdf41bf9244d9594e889a2eef8a64789b0e327d3b48a06229ff0e48d669cabd64b7d0aeaeb4990571e275c3026a75106083b32dd1f33511877c7bf78fa415243d59474044bad21c773e39bf48619a7bec8b55b951b79f097cac697860b20c09bacde7a5e8054774db8da54742c32264f62246ad1945be13f1f7c856810e9205fa8dd797fbd4def035107f85ea309c1565f0ee1fc1e312d0bf753aed6a8b7704d8a1b2e88703511e6ec48c17ad33cac96aced306c8c08dbfc12c242d6fa52c4e51faf4cd3b331f57544f371fdfeff6c2d5abd7a38ef1abeef3a003aaa7ad6d4dbca80cde878cee6c46429d86c64c73671093e9567cc807f9f3cd9dc501878051166220c2d90915ef8e5eb46c0c07befd7a63cb38f5e9b4a8f32483d998b67fba733e7888c6297359fd32791beda81f7e8cb5d8ee05124b646db4ebee1e477c86bbbdc8d9f2151d99b8e6f0f23250649faadbe7ed2642505d7c89919bc10000000000000000060e171e262f + +VerifyMessage = ML-DSA-87-Public +Input = 48656c6c6f20776f726c64 +Context = 436f6e74657874 +Output = 62217e84cf857b184906ba906b223394356d695808a3beac5c9df51dee7b21500679e5b9ca4e4abc35c150ed56356d3050f559d54c176f57139afaedf4b688d440f5db3eb9e5fc6adfdf9767a53ca1db1e74b9072bcfefae88b4d0f2c6de415ef52621f4adb28ef54a0c6e86049548a5b2152f56d4c394114bd088ffdae4fcbecc2ada3b0ed796b5c5e4e46ba101d4082137d93c9d0ad31c5e6117cf4bccdcff664b0d284c994d9ad7a523c9eb202df60c5a1213489af6a13cf4870d60825e41ee282f1012cec3a69edab1c7ab5747c357fb084c699a6f02ba11728b25de7fa9de00cefefe82a62127dbed26a94c4618ddd47e8f781c21c38d42c5c29ae7e0e4250646396bdbb9537327e1f13fde1e4e5ec2aacfbab95204f9a623a625bb4bdcf04acb1c26f36c77909468c733bc379e7c5d9aabdbcbe21ec13c955d461a6721936d7850e2b13bd72947493af86d7dc955fadf1963dff6ae298606ca365f9f89d32c405d8783cd9450a0263733d13dc71223a019fc23b0bd9f80b031961b4088f50b04eab8000bf76a550f28058e6f6b9f5464d8c83d3114223dd29803ec0e4a7af815e21d97a6613bbd21476bd383792b3d3d65eb7cb87b3e18a883ab2051e7d8856237859eb352a24525f48258374615ed9983d3a9f0a30295d6f2e43919ce321d8508796646834d16803eb2185de0374bd61f3f0875e569635380bd063e5a66145289a80ed002c0474b4dfa8e0a2d7e3659684e2a3298fed67e53dd75f3024326076d3df7bf0b8554b46e271fd2c1075fd86df402fa2069964d1748f44f0fa79931335cf2855724f50ff62d72e316a06a82d85a7a1a588291aeeaadcead38c53f1cda880bd441caae66b2588bb93c18dc5db8bad4eecd43859ab2038e5eb151061fb78c6efd9476c0fe2ce070d0b0d832d46a3dff0d52d585c71add41e3a62f4f8b0f70818064bc4b06ce7cb239186b50fa687271056786b52a1f37be5454550091591aa5cc84971c5d8f1e4b894e31e2108907d0be93a4497bdbc668efd6abc9ca9daf86413a4746288200486f2d2c607d5f09c8cd7a1bf9484cf9335fe5d06f60412563e79c41b80f3e56ea3e02391f1c4aeaca8622694cc26bb1fb6101b199f263ca81db6a75d335a814389e5df5c12fd00d510feea725a9109a1adf00912ec7f2356e55b96ee7303561f0fed9548487fe3633442df5cdb61ffc33080803a8962f413159859345871b17183e783cec8db3a2ada8ea3d55eb7ec73161073d88c654e56754d2f8d1f421048f1046672017e2229e17df61f03109e993a02102e6807f8756b0d1ee499131ea0ca8d4156004a6a0637788bca407093ac59052edfe0de9dfc53f50f545777d2bdc0bccd985013143fc464595f084e67e342271741ce38a96d4c4e3c4f6f9239aba9d2ad5c23f1fa8d7bfb60b83beb67436ad3881ff481543febebbee46f9e56b6eae7df3ce8b1f1203c38fbee440d6a51edbd10e4c8894df60312ef3261949c9d79244e47d5e98c4ec23c10eef7459d01d485df2d13403a16949df5a6603c73925eaba5fcfb49d70acbdb3742f45725f50224fd4062516b04dffe6845f78051f94366b0f78e9daa12cdbc6afe81434b7bdf9a66a81a2b68c5aa91f8dd6f02a49ede5f4e5947b33ea072790dd77159d7caa71ff67670eff0d164b1cacefbe5af46c68cc124e680f74760064df229905c670bb573a61c74dc8d948b87dc948d5b12d6327cfa3ac48270c3713f4b96ce7b9e00185ef74effca6a4994dba8a3712a986d72f8b95d00f4c17022c1ef97deea0346402723d62f8550037a604d8aafe6cd0a5063892449e94693e53b3a71dcbd9c94d8f78b1eaabdae982a5c7a23aef2b7e055851ff53206785c6270aa10c3f12df291bf61140b38603dfe75179a47736bc069abe2d115bb74585b86e2a449ad51445123eabc54070a42719e67f75c2fc411ce3d05141353cb33da779b0fa6e2aa6f9a55da5edbc85952832a39ccdd973fc7fe0fdc5c5ec4bdb68913ce8f2580507e3b5e16c4c981a14c027b8becda417cb1a9428693e9505e5a0cf5d9afc1ea715abecb49b083d05a4efd5e717bde7cbcc4eb74f3011ccc28ff31b9a74459d9fcf1d036eb78c1c85b4e56729c1d7e5135b99b89a8f238ab69b7d730b3a47da559ab45e004d844ddf7c9444241df1291e00e89e91b42d93a1bfa1168042819e28758c5d2b45c50870ae4e1d3f7a05510e72f422e684a29d71a7ba484afbc24026263078bc152446cedf142102d3395ecc6d32e98e5e6e3cab52918cbd86c11b86dd3d80c4b75035e62ad78474f5870f0fb9f421e109f0c3152891c070989d5ecc660f3c9b1bfe86694b7712c4b63cdda78380710268a72c87275641c7236e3c7c40b368f53c98d708794b469b1e19c728d2ceb836262d15f975d14ae5c822b13c3a450e5c0a4784b7b93949084597ecc4f86a06960619e92fc3f5ba1e71270f0f5f8ca6fb35aa9fad66e93c3b169af95572022900a3ac4507c005d518b7727639cbd6e315ca0473ec98cf2975df8bbf7f2ede7090801cf5931c396a5eb123a1c73471c5483fee67948dd28e5a9e6fffd612f59323a39cc3630b43c0b66a74d610236aceb442cce8c67c051cd1b56af5f299c3e90a82848eca945602289cae9ba4065e86b502147c06e8c7b76fc18f6ae33a27a1661f60cebc713802f43ebed8ea8867c69e97d4fedae2679f88579f7bd9cface5ccc1bc48eb0095659dff03f1b0babeff8a09f36e7a29a9afc69965e7b70f63c8e7a0c5da68ef6bcd074a427941045fd96c18497c124f5fcdf34b0f17b29b22110fad3d42a6399cbe6d7db7e3b0a93c3b9e71c068a9f52aa70f677147689fc79e367edd5abefe23252a4536ad1458abd91916c28fec848ebe1add87a9e5b63460a04163dc8af8051b24193b1d38ad64740d10ee2bd426e36548edb8183e8a2bf788b0a8323217ec286054647d1996f4f88772f11f4eb64b64d0a240c332de938756a442ebce2a6602c01bd382f5c532a574c5cb3401187590c83f84708b72600e87abc0e77a1093b5d0a70c8bd62067a7bb7a2ad7350c1543817c62c5bfbb6fd3b45fee0d77496ff7e3a8b5945da9990fca764849257f4b95f1e266b8fdf433fba3815c250253def569dae59a366d6cfec2b4b07c907fd48dec46be900505b1cf58f0c43e47bfc9976368887ad85bcab920f3d5ca37bf28b4a14b463a61f71f5705607077d8eb7a21d111bff390508367c05caf85bfa6b91fdbb78902b1cc27e24ed274c456f77e8c08fa6086c5473c4097241377d579e0661a0e5d0c220c2f1c133019e9cbab3d49804d0e1e51379926d65dc28a2a77e3227b3c8574978845d68bc8e3a2009c1f78cab1a56a5bdf0e7101c2069e9f450aa2d671a24f8c22a97b7c505e58a8d0f584adca28e082826c6b35b0510966fd7d8d654bf73f55392eb3c29f51a34156f94e63fb563c1707fe4f0ec99e06e2d6e61c7390084aed4334b74a24b690f4b3078bc88ca62c29f10065cf23100c9fc9a74ac389b2ccb112cfd9c7f244e306d7c18ad64112a7fb97721b256fd4a740841a26a4682f34c4b739f734389598bd4c03d910c3e3ecaab5846dc3f7a6cd4c04f8e75ad7a7ebbbbdd7c88856c0d9508c4fd17e4348b8b6d37b3baa849c1bfe14ff7e616d3cf8fb9f25e41a9c364a77ffd47e17eb69285bd1e1d1588e7101a52cc67ff28d49f3f679958f1f6557b02ac52d459d9402ce167ae510f07d6823b12c5ab53ea2ff3e8b808e14e7617886cabd14eefbd5240170acdead50e240a259c026812454c242f63a9705ab4b25edd5f7234ccfdbaacc1bbaee7326666e4829010723c0bbab7ee0b4adf4f063e1b71f531f7847ea1c336d42358b37d398795a0fc5f239aa36131af6488eb6c032f2f2985073a4ec1b2ee7820c53ca42c5bc3dc8fa2fca0b460b4e4ee927885004fd2776670b5ae12c927c6a6b9067132e71eaba5d28981620534c6f97086a747eb8489aa0fb33b42ed74aacc0c01fa5619f48d8cc35af60e4d28608f4de93798905b3755c20931b9b190baeabb2f66d40684124ec44d467b474c55e4eb7cb8d6ffb31fed60f431da8ff665da4f8bb878570964a412d72e74720fa1fbfbfe11dfa6795dadc7db02f9ad62e6f93d3da8c1948f6664cf0f723f944741b83565cc2a78a82631a806026db5c4ea68f322c03b722812aacd56379833a14b288725502603bd540628808f9b6b0d085aeb3190a42a4b8d2d61b7ee4da8d68b5f8cc21d822a3413fa21497f0700b41b98fb6ea0ae570572a4b8a851dc8f8075cc2add19485271278d9f3d8ac4aa04175e65bb3278e33276afe0373f55e8fe67ece00a11de6ce42eafff13b56d14edbff5025c6a170f592e45608c8d0651e5026dda50df3afdf680486e5db5529834bf338d580df00f3f14d5e59565575eeb1aaea2521415a6926fa4963b16488b17767a279d457877cc71c6bbf77a636507baa85954bf889fac3823a3e6350e48d151b30311f5f08376f4d153fbba6dde1556ee9cacd47137f20112196f99e33a2a8fc2334e10b561c02ec70eb863adca5d7a988f33c00fa21473c8c2eecc8332e0b05ac4c6407e5987b94985b72531dd945391e4720fd0b33199e35866c9b68d88664cd81c9073af42c796d29fa8b575379c44336dc12a18d9faf7934d767cd156fed42c204c1f0739fb76fe11ee69a766be3257cd3cefe40af817797662e4424cb9fc7226eb23f14249bde2ae7bff15313d47208d72722b46a7042bddad08522b77c0e04c200cff19dcf78ecf34ce8763ddc95f67c01284887a3b3b45adaebe97040ff871f336e37d86f27be5dca7b8c98e95f0f6eded509a4337ea8a2ef3d8313fe8b413fe06199542f8cac04433f02775cd4df62a412d26613977ad7870daeb8f2fa50f7340dda3fe8490858ae686de7ed19068818b57ca9d31beb413368b0a31a247a5d22775c33e1e684aec3f4b696311f2d1cca69f09ff7bc98c4f2e67184affcf8dfc2e8f55a643ffc2666f13d669dc7f999dd75f722824fdb2cdf388147be3c1b72853160214d1b4eb0fc4c3563df53f6f848161de8643979853c32eaad84e9abaca21d896aacfba9c10f79f709afe4845395a5a6114a9b8424ea67a5de6493c295c1c6df434fae8a017163c7e355d46dd7cfe4a2ae8035900c280c2f347faf62fb503d90673e812081296117f1195e67121c6c03893ed3a784a0a0c2104838c8d179e07df7803528ab6186034c68e24b362b752284f7c22a73d73189af93c4cee07c87ef2bfa84f47d04ab111bb684808722e6aeba4b7cf593af4a0cd05057419d2752618d4f5a0a84b7a75864dbeacb8c78d6c6c94bfebcf29eed3e543c941f1a912616db4551b39a12a84f6f43f89244893a489b15c1af5e3a2f7af01975101fc6321564561d056740d0898a1597e8795fb53eb7cd9f126a992e136ed014ff506287e3d2599cb520204696508bd00c66eb4c70a78e24df1802db88448519eebc4f3d09cadccd4c15b0bad8edfb8181de86bbca1cf0f8b07974676fc5662911398a5168a9eecef932f0eadd9a6bcc26c1ba5640e6a539f6b64692dedc96f44629e74f1ea8bfd23bd66e6666c06b7146ac947d9147b724a1f2c0adee7e86ac1110baaf3c430d1e1d892047c5bebfc3fe47b0bef928141213b943b1ec1ddafaca1b0bd48275e9258ec9449ce4fd1e7d2491ca4a6fb2bae37d6a9e8f67581c6bcbb611a8653383518d565287218c53f250c3e7c40649815f6413c0740b1be6021c4c7b2eaa19a0314355175f39b07c695e83cc1da41cdcbe1e7851db91814f8c3fc2ed9f5c192d696e75109c366e426e4486a707cf27f2cf48fbf1acc38879cc846ae09cf63ebe84698601df4def027b080eedf4f173dbb0282a6028b99042ddd36e27f78fa05bd279ae776f50d83f802bd39e6b4201c02f753186eb105f00fa089d57d25983798610b51358cd9c344dfc57f254bc9af3f34b0ee56913fcfef914f14f97a91387238bd2bd328ff37c2c9d71603fdbde89014a3cb0f2ea39ae86988d6762f99669b70fab81b353a73e6731c60f70f35a8a1da777f760441a1b24981e1cd98ef070d8b4d095f200ecfc3a085f6fa5cf6b2346ed90d8e96e21fa207dbd8facb146e8a3f23964aa6c7c1b7f124ffc2f77306fc6a504bcba9ae2dde7b12ecf77b4370a4afaca183e353b966345d092d254b5ba34e9afc3460fae9f4413bbd58e2ec8518bf243d50f737feec6d167914410218be4e2f9e83de9cf822039bcc4696b282fb4a6d33a6f93570133ca5e1d1f54d14025a1813fd74aa587ba7db0f0974170f28ae378f5d2b2dcaf8d412b75e8310f2c0a92498d4e0211b1327b96cdfd648b3548e342a96cf3770681981d20dd69b2bb404bf615946c0de26cde04666f8ea0b3bbdae5f5f61b25515cb9e7f244496d72536c6db2c7c9db093339418a95deebec3337445391989cf60306101220b4e3ebfafd3a464b577f88b3c700000000000000000000000b12161d262e3840 + +# Context string too long +VerifyMessage = ML-DSA-44-Public +Input = 48656c6c6f20776f726c64 +Context = 41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 +Output = 709f29109a222d7b6d7940b47871f1df24848d52ca384eeaabbdcc4a885429eb21ff9365296045fb58ce67df5385e91a3410e156bd08afcbee41651a9cc82206a73e4101a97d14b7d047be924e63f7cffd15110f6ca3449bd49471691d2d1837c6c60a6663214227d3f929f395f032ab2e902731b3ed1a9f7f914dd01ba1bed18aafd3b3e7ffb754e6c7379d1b1380ec6d4e8b48450d8017ae70e689692e7485d54bd12c89a3c5f03232dc76c36f0f2f817d844879be68f6b894417691de393a1b3be56e9c55b353ade6c59c31a6e92deaba02e2acb0b2d71fcfadcb7c28c4b5ac7544c23376a348cec1459b6ef65e03cfb5bc94254a2f9999b08e7fc4a3cdb821e77762b5204125e676eadca4522b578469587f2411da7ab058c12bdd8bd9bc8c1fc7fa20f9c32d9f152e56cd1668c772dfaed02190c10ca6c5972a068b029ef40e65a0bb5728b188b1a4ff892e5ae825f76e5e145f52b63ab137867830be43ad47f33801ce3f92ec53d6b2fc2a9e50d73aa01776bd75d82abeccf7e42d7fd62ede9ff7d7d8075c1fd6a6c9feb0141b8d0500e21e093059dff78791a52da4fd11bd74603ce0eb8b407f8e4cbdd905f0535e851bf3b554b1e9cc21e5f8ed83574c96bf12090a5d5bd094012b9cc63d01bf74e755a7c40f72c0fac2a01dc630a308b01e8397569dc956f3a461193ac6b8559ee3ba3d36ff1424a5cf930a873ed1120d8a85bbd910b6ec1d6d98c4785707d55ff764feb7cf3891673c4c76ebc569f5c6dc317d1e28dff0a81db366fd0b5035b7860876dbacf88349425448f37e344c260ff922bebe0e596cf5a437b4547f0389eaf1eaf23c6e247d19006a53a25a5f71b965c99d78c4939ad7228da729a43edc333c559de94bdc620d1d6814bde11e8473bd65be8fc76b2b57e7b3610afc8351551b1de5c1b853e6c022a61b2a46a5ce5a86d3e781218531c2d1869bb9b316d0034faa51dd6ea6c97fda52500dfec10dbf207f4a6aad067cee25e55bf53dea3b74a684fc42f42715b7bee9d3532039cc829197fad6b23dc8ec102987ce09dc6aaaa49e1e6c5a23b09701a1e51c2f299938ab2a6c3f40aecf0e2b88441d1a23174e8711e05113dca5e3b937bcd53cbd8906e977170233b15149a020b8e6c74374ca4ab4cbb97d22f25922fdebed31aacb512fc2a83731a7f691c92196943b35a151ed961e53f4e7df7a57b13b60886a0a9aa4dcc6c3a661ac4b8f2ee823c5efd9d3d19a0c3129bb0732be910a448017b53248ad012e83877fb1885e9709063cd0e960240b2ee32f5921deca2f919b9f8c1a461774813ac5904dd1cc46305196332f6947f13ef115e139611fc9379bb51d1bdf686dfd99d86c5178b80c6c5bb1f32d8b66f4591cbb4e3647907ff6621f3377bddfd577410a5f0aecfc7d0ea46906145d02542e16526468642868bf3ab9c22a06a041abf75ae14b09d4612a89fe2b0c0a9d7958fecfc411ecb7516f04b67d0dc51bede29f3708918d7ebe82f0d6f53179cd5843d0e157353282a2e58efe44c40adab9dbb67bf73d43abae62c6f7b2f7a7cb03a56cc7360c59ac89712829bcf4b346417835df4652e370ef8b6fc76b53405d75b985e0c3b7368ec3c9bf5002ff9424cbda0fc3f117e6cebdda7332ac272a708c83545e77bec5b4f1292d56df80f9c318b80ce6f6ece05ea1b922bec11e0d287a22c0c938ea5088961c3c584151edf865557a2db9ef86da8cfb7fa8f306f5037621c1324034874cb531fb81d8cd50410e80ccabea6a48d106129bc6005459579325a42b064244b03b3bb770cc4a9eac34fc12e77b99c6d5b832a6fea29ebb6087173001717835997a341c7a5d94613a0d739d0c1bfb77e7325e783e3a97fea3f0962e8d71e0de2b5dae36005436db0c0df0ef807b6cf11eb9baf695eceaaa49afcfb5511fed0ce4a5eff8b33a5464ae79ac33ebb30ddb3a37313ecd0eb575b77d057d13130e3fc482c55863f068f4b2fc1d9723ca103f168b7bfaa468ee77f46f30aed8f69c06669835dbf525ee65ef19c6bf3928ba9faf2576e266955cd6a9c9561a9c0825a9828f1362aa4ed55d7d6c5140629c0d9492742b0dd4417e5baf15361fe559b62a56708f6d1013b035a4960b0c015953196ccb6ae2378c689d7f22681576e7635ac56b84201451c9425cdd13e5e2b5160c6087f6923df890a7288cd0433e4e3d670184e722bab7db889805350a5d55cc51bce195a734b4f2cbe28fc5eb738fd77a4abee5b3604ea5eb62f71df5dec11efffd1d521129a7649b0d121aad8bc0b347ddc36dcf38f781b7112771bb814a4c40885bb86a8c05bde18417994e6a3bd245bcfb2bdd2eee5f0b82d8a86c7367d5b212686e980b95f0504d7c5d8162785e3d3405d31c5dfa923fbacc41544fd00c903eb8b9b71d28923250c0372a155a50f2c116a13e54417411722dea560c82cee8d086077fbeff0aade138ac721a637b0de485bc36cfca5b21bf59d71f2ac54a58eee767f40bc2066a954fd14d37e20883e2a8d13f8834983f9c342ac43a30408af7599be7de83b8ac12bbf94405b1fa55daad5d4b603d75ecf53a3a0a8293240be2ffce09890e20a0c7dacf923fa2f562be21649873e160934f8d627ae05c33a75a920fcdcfea0c7b8a960033adafc46ace3f112f3c094e09671bd3d57e2e98b1f57f207a255ffd53e7a695cb5487024da2a119679220ff69f7db3c9d0bec657980cf490f4f2f3a6572288ad74758a91c51001340e2ffb95e020fa498770c423fc712611cef8b2cccf3764336b98616819113ea0e9339433da6fa8bc5526d013e037551cb0836bfb91338a3781d0436d5d3d04a9dcb0978d9348543bbb7d8f9ccbc3d8272fdc7d1c611eedaabf573352a32c66b49276782ed153f5e16226bbadb929a2b431cb7b311ad0bd89c550f7df283bcad576af4075fbb5a15707322f2d6541154d9e2c589c4332c38115f84f24a31323dbd77c64a624871482dc13da4a6276b52b4342bf3fbbb3ab86ca199900998181b9c8ae6c84f0d1debd72a74f5d0fbdfec3990a897ff4f2328d0f3f1de853bdbfb40e7a954a17d452339705e0680988c635a903595d5f5da97c7a8d7173e084aa7f4d22f21e505b7492f5c073c0fe4f8283a4e1147dceeeeb2cb1b284922f27ad62386f852fceb0210ef49dc6a523aaedaa91388fcfab4a8efa202d1ddfae6030fe1675d52e721a9eeb62aef75cc19f60dcdda75c5f3b3b86ade0e1b6c85638272effdd24e7c75df507888ef5f14688ff852500e966e2e726674b24e29c98663d783081c2b324e6574838b91e6ff1f223c4748a2d8ec06293e47485256768ecbee092933393c6f73799aa6c0c7c8f4fb000000000000000000000000000000000000000000000000000000000000000000000c141f2e +Error = INVALID_PARAMETERS + +VerifyMessage = ML-DSA-65-Public +Input = 48656c6c6f20776f726c64 +Context = 41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 +Output = d75d495e0aff760275e801ab0c6ed1ac7f180c51b112122fc0fcf303a999261efd3473bb1e46c7298a2d49b2b11934301145799e58cd91cb24f052e90b7bdc1cf590b6736abe772f211d8deef50fafab63033bd04411534c233de584ea1bb0a73d6cda890c1f0206891d55e9b1aa3352c0365dc56449356732e74b599ce33724ffef2a97897ada2a37cfe178a3ee47f8002fd2e02873afd935890f1e31043a7d17aea570285b94024c7fd8ab135e515799e1b2816d4131e3c5a5e1199eeee82f292cdf3a1c290838db1c46baaa2dc75c379342016b06ef1768cd30989bf5297ebd57adb6d6e0b4edbc685a2258ad3393c555bedf933c566f0f848960ab6c2036b7a1eb971a4519898e2b25d8a9fe0aaba7620e580d1c1a6cd6826b70c155b4135831986126613c2a78cc4ca93d900b56f77db9c7214d46420ebe9be0995f9615a73f74b66a4ad1d5570e07f2f9a690750852426f1ed0e61c3c7467ef8af0301b4e4caf01b7eb96f8ffdae739cae1ccbb39631520709e70494c36f9e15610eee5b479eaca35028c1f7ae1da78e4e9bb03dc8f228687f414c4d3ef427fc25ce44c1a06a8437e12974478d84bc566f752a0ea08101ae60c49facda27481d52038fefe5eba5db3dab643bcd7b00b8f9237937bba76df5adb3139a605bf52ef93c2e9a56631b0f86e7be961e0b1e42e8ea4401be99af9b45b01104f5b879b81ce07ac4732eb5c937e7a017c430eefd4cc8baeaf57eab48042f3fbb2a290628873702a9196cc8fa793466e8d381f28f5c050deaeaced44889520af258b897e5427c3deb74760e9557fbaaa80d721f21792a5e8c97e536ad3319f58d2f1089a82e35aa77101aa8e8e8b249a608cffb921987e16dfb2a34ba8590f0c9c2a6c879c59fce2ddf8b2d9747136a81749698b7ba4f5d56f12718dd7c9e296fd2fc52a0a33c9bc7fa5632cbb8c73bf0f4ef427c28aa7e57ad5c069d4b68095c539b1f16623aedaa1f30d43897380cbd1d8b9f6699a38c7dbea893457937aca16aacab67db5bb60195dfa1c0cf02e3d368854ce2191b59b05c6005a1fa09b275966035ff68e91f3c820d8f3473748557904206ab6af36a343ef93e3e121f9490e8770f0b2a703b932b16d4ea19629b7c2b26bf2ca7a07ec6fea8cfd4db85d185d39731b0f3df6cb07d152cd960640facf1c3856cf5b47937644ff9ae17f2037bc7b2a31619273d012afa35b331f78cfb50d23efeab8525be11e313cfd9ce731696a558cce05a68fff8c55bd103af1b6b1b13c8bfe9bfb9d0e86da12b5d9d5385829490a89bdf4e4cbae80be22ffb624ef729917d849c572c44e35ec5cd8354d770bffa5b031ee1f2a76b077b241767f384092a21b016b5687752f23199f0a09e5fd701090fa9c289ea50d26bd3a8676f49b29ba54785b3d20431cfeb519ccbbc0141266a77e7d5bf4bf3299497c8b1d1b40c2f00cfcb29c3a99876a43076a89a13cc58b5af1d72f87e1171d2b6ec9fe4fd318e95590cee63f1a2a6a2090ba3eea95061222db4c8b7cbffc10b450bdae10c0f82fc6861cbd24b9e4d18e4a477f7491586ae23f7ff10e1963a874e0ec97779cb33b4d3262c504cc59bf2c518b7a6de0744297fdbafd8be05bcda2b2e8fc98808594e2a204bb72aa9a425c493ec3433ef5af84208c7c47105a7ba7b936f189a64002a0bf07aaa16b449f79b32e7bf238fe72ab2bdb3e3b2a64c6f325e8486318c50bd905d23afd2988cc92ec26078b2fe9e6fdc5e27fca279c5ad535a70e66b5a55efffa1583b8011b084bbb9b028d2154f2aeac02ca66ec8fba4cec93feea0291e0017c8ec14e49c0cc2e5eac9276f64ffff107dfdda08baa8aa43df97c6adb792e7b781d2edf79763b9656794f0910fc0c17c45cad7f7173401da1f7fb9697b571fa6bb23fb687b71dffd21092e78966ff61fd385f0a236c93aa2d550305e183eca91d284f161d5d2a18824e7148c2c615e939fc4299e84b686e3577f16e8489ec0cd1ed80e8edceef398d007957b571d6e1680e641fa1cda305f993b92ee77f5dfa2e2b4bacecebaee0085c1c87762554c76c5db6d9515647ed615b42366c05d77bd0c7cc37da56a52374f1c4a01ffdbb50a05956f5a5c9082b1de4bf9e7abc3bf8f6bbf983a49108ece5f68ad07b3f309757e26e9bee76ea44223210422ad192f1d1102cbdd0047f07146be860860c28fbf5aa9b401b96cedb9097d9c95fa71524a5827fd562d600655e7ad3e4c592c67faf8a71dae5094e4beb188197ea635cb8d9b25f91f5df2e192b55d991dfcb7d696129e956e13e5518cb7f126b5d0cc9e87c5ed00c2a15eb0d343f283f658001f1addef1043ec46885099278477de6d329506659fe29f7d192feb93a39d3dc8d06913d4b7b621c300d8c01efbc37740d15d6c8f2087c2db3a2f6dff819e8b2af5f5ec52718c970df9e5694e7390cbf7999d5c739845f2ca98d5a4789887f0a6648134c518172ff62b6e85852dedf351d3c5a2727c7e0a9460d595df70961730ebd283519668cedd430621b9af7e04a54058dd6c04770262a75455f7c5f477a4f339ab6d4293a02eee565e3c7ac464db588a64d0bfe1e1b9f3f1977ddeb57e20449153da8881db0565a37be1506f551b8d0490353b799dcdf3003c4ee378dc16d76592310135c3879c2d05e69ba1f9aeb58c6187945617691e5872a0f322506408d5434818cde200e60fb6f40aaea77b94e4c30ee295e8e49b26ddc69c54b5f12bae4186b2e7e886585f0cd14b6475fb37a217ae79f87ae3303d67968f3ce82a40c6590b6cb7a6f764c1f6f69642f67459fa1f53f04eb73142351f0249f4970d3828ed7cc6f7cbd74fdcff388b98ca3a9747d1b70de11694a5e8fe1bb81f37445c6b53933b47a1102818ce623f914be67f51da77f8d666d6d77162aa323c5673749bbb01555d3d204de2c4053989348fd2cf61e185ec8a453d91b09d08a10ef3762a630c53adec121af51958cedba5f82b8b0ea755e74197a61a09c7350547767c2ece07dca5737a97b885bb1dfcc9030838acb4c356224af7672ef9cc0435b404be37f74ed3f042d00f05be35781e977abbbd46e594831c07b3ee45c0e170f2040e543743503262a59c9880c1603c79f316587cde475d6236279a194986db710216f1169a6c7b42e987a9ed7b4fb4212b8bb25bee469ec96d0af41a2e794ab54ba72326069cacf2f5e49b2eeba2ed0177c2ac71816d9f6e2c893fb54369d901e6716d2d04fea85c809cdd9d2fc4cdca6ebcb10d810f764f1792f4a557652da371a3ad6f039d14bd9f5235c8b9c5b5a48333c798ec000fe44ad6c9e7c9e5f57d406e5e8ee8154574b7c76a2f7521947c54a67ec44807622aad566df4d463b3bc0ddafd0fc017f1392cdcfee32e96ea8cdc42cb6e4587cc72d03ac789070c210a1278abcf286e23225ebbdb5bdf917938047e9ec980434ea6566d3aea655ca8a1ea9651d2f0c30169c29cb73a975bf69510e1b6ef8db72e3bb7892e2991488627f716fb7b5ff194757de8a2479a4497f6da76a421b988534b78f8571b4d7c3a2493c2b7b8b02a07eb43fb2fb1d203b02bab2125e7ce41db5b1ce0bc2c7f0706837715223ddb0dd2ba58a98db96e79fa28b1ca14be60058b2ff7b15ae2cdfd38f1d63b77ecd0de4c6e0342b6535724231e797bb717111dc0f0714c40e786a55a2dadaf853bc3cfa324063147802dc2a3bd6a881d3072fb8addf1f8607a7b4d4dc8386c40593ee6e5651c90786077128c9f6ea10aff3fff1e524b3ac1ae1cfb2cc6f659f70c718a821b25e31d7393eb5f5b95c06f0958770cd1b3ca5a6b882aa5c3bc0e300560426c4194b00e4dff3d300c8a47f6c5139bade447b1357eee0164414d75379ea6f696bf15e7a47c31cb47fa4b5608eb0593ce58b61199955e243a8b12cf26e21e05390c2a61b562de5d70f0113f1adc3f3a4d2de7fd5994f6360a3566128104a886e27b349671087c348a101e6f6ed673699962c96f699fbd3aa37a95517a6c99d83c69c16aab974d144b3dae33c9fb850b20ed6153a212ab940d63fb546154a0a377ac16eaa58e97e1a1a5bb4c9e845ed098755bed89abe251e8898f3aa9fe22ecf8b780f32e741b59e4c56a6db067aae97db9cedefb39fe580af8f218bb13bebd51ccdff133fda9d696bffef58f0a46013a31ec1a75918ab5d8e9cbd6a79421ebaea74007240a6ee379f1fedd904e8af829a2dc92ced035f60e8831c73bd1070ad4d5068ec3b2d58069adc6166231ccde5a49a779340c52032cc9434fa479270216037807f37ad0875bcc509ff183c9c518ac22ab527e01eb5dfeeca74c78a400d1ebd2e0fdc1ec19acce8e53352b8ce154e2f671e930cffa1a3a388739f73824eb085ad54aac583dc0d2624e07da1e0c32f61dcb83e632d260fe9c453cb957ee54d1437b1c1c1c6f919916146fd4c91d7ce0e25ee7209fce21c7a6f77abb91dbe9c6d9e3993897965f1cc2fac0e4acb768eaafdaec0c1b1f6e16517be4a7b946f422e61896eb4a368297dd222b8a2f0ef0f80a9cdf168e5e13ef7eb974bc73768655352271e4c38eca8ac5210a4724e5ea0c0e18aa2cd101f216872cadefb05133062c9ee39567a868dacb2c1c43e4e5d6aadf4000000000000000000000000000000000000050810161f25 +Error = INVALID_PARAMETERS + +VerifyMessage = ML-DSA-87-Public +Input = 48656c6c6f20776f726c64 +Context = 41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 +Output = fd544d3e34ffe17c347a27e09141e80251e7dca1e8f3d226f3d0afe48bccccb0a2029724a25942de396d66d7d62b8cac638e131bdef8908dae9d0cce2dfec34e912e772cd28cfbb8f5c92bd05552da7bf0e06a3623ae1f2b02beb16c4df832d74c48e8c27fd6b7e67a9ebc71bca5139f5b614e49e7220544ed930f4918c5262eb26217246edfb50eea73eaa85676127bb9bfebf34239e8f6a159be3630e02ad810ccaeaee9035b6b7f464e3f70c2cb0ae60748c1b38201e5f4126ed19964fe960aabebdee7bf5bc00125ca9d04570691dbb037dc6db940d5689b16828d73db1098776905f679d5cda58e67448e8bc8d7215a81353d4657fd478ff19efbe5315b29f94193ecfeed43b0beba9c4d06255764bd980d34661902f58854c58f07ea4677f6cd9c348601d76e66f2ecf9c86a321f06dd585fb5b9cac17a50d18f28bad74b2749c1a143fb35053a546ef5e68394d0024a0587eafa35a23791418ed0c8e14e572bb1c0002ba65ca01b0e08b0e054c8f4611bd73d8888a2c6dc380f384705058f62ddb7d0b8f4844d4125fc4bd286fb513ebf4f1152d225792954a482172a4f33fd57a9f7302bdf59b3ee19e42cdcd3ae27b981b0b902e91eb9e84623f3bb9436a7463253e5d2e2e0cb8a11065d78ede565866758ce5202f2e46ac259e566e9d18b607dc8a6e1440264549df73945cd2df996570bc0a12fd9ee4faf5555896b25e413a5a1aa545d27bdb0bb2759c5f798304010d21b6b4b1d83bfd55ee022e6987b05ae498970990cef890927be6f76b5c7aa1ec3567444334c0a7a9e4f3adb321d5ccc24013552352cb4dc5295ad61c7548a0fccae215192896cc15b96f65fc3ea83cabb505a63ced78ca7cfa1d2e8a12e91d31f10d763373a438cb6e527ec2cbd06cfbd6033895f71ace2c2f091401e420259978e73729aabd6cad8da4e9eb6c8d8e39a789cf9b37e84d1b38c8baf13758dd5a29a6797baef2b54756dd3ad68cae4f7638a803fa6783e8d830a42e454a13e8393d8e7c631ab8680fd5822dde3073f4d2f2e9bcba12a8c1f7282e8a4f19ab4c0ef1f7ebd52f6d1bc278c7d6d1440b2ff2b706893aafefbd2d46bb6e4b49c0c0c1617541b90968876df160373dab50e8e8605415d7b9a509ee8bab502e5144b884ef45b05f64d96cb70a3428ee0842c78220f8e5407bee35c2f2aeba68052b1dcd053c57f1a88e7709ccbb667603317fe9fcc40afb58cd38badc4f0136c2f60848270c6ea8afd4be9ff1d214a8dda6256dfd9d18d793984915120a489eedf31eb82550dae3b7c6878f0e79e4512ed19f0b67d08145627b069a36ddd80fa4a380aa92e6b0e591a96755a783c91d2e9611424ad9f0f3cb66ff3e79cdbf77dcf80c3701e1da0cd1e70a33d5754ce9a3a9843e9d2cdde47f11c65d430399cb41401f86cc78959b42f7b7463de3e6cad24066b6a6c25fe41a75ddecdb8f7d24eba99adbabc864e4d6372cf1a88c09a44eeffd6886a3505835685e13f0c70b63b6906462a9027541172b35b2fa9868249232f97f2d7dcfe48d1f890f77f14f6f16a5072de8c417331952d96f093734e562520d4643f3289e5f276fc3466d3ceaba92fee67b21a2eededfa31f3b5aa47777b2cf53b27afdac507b95ab59760cb284ef231f4558b251f7549f13e48a90876979c71f189ff34fb69f2c08a02259586feef717635d7d10ea7934376a50d8c212d4429392f6235241d0d7ff084c866c3fd76ef73abdb40769cd9b965016beef582f765feab3175e0fdde8b71d207f641d5ed8efa56f9fa8970e472b2f5eb6b98e928493ff2b5ce118bd04d155450f768612515d4809e93ea006a41e881e98b66a99683cf4449e92582ab70059a8963abe5989c3a10301152df95b2d17132dbc62043bfdfc38bdbed6c0eb02c2d2057dd495f7040c6b4446f9d63015ca9013d3519cbe4ef8ebf53490b9336daa650c7bdca437789cd30c63d9a094c1ab6cc7545c615284a6739873fd1cfce2a959b9896031eb9241c6d0db0c7085617fd6512c6e5aea2532600bfc9365b2f9f74774406712cd99d6c2dbe898064e999996616781c9841cb23ea913ebd1d0127f96273ee8cf63f915bb5578852bf02a9a79366e59567f98a438906db881f6ebad5d6f091fe302f5ee5ea36ce3341259b479b847da892a16d67550550a58471bfa880fe341366e882d644e2ae209ee69d1817ad5350cddf65247a57a1a8ed75b1edab2c63550a1c694eb1eb8ef30df4f8be2c0785e13752700fc1bbea959a712bf77272bd77ab46aef133a9e3812139017cb94e19148df5288182ca756c7fde5ae6a62879a72f2120b54f9717703002e71a6d28468f0926f514554420f42feea8c7c797b477080a355d911114cdd0ef6d6119fb617da1ff648228c2f8d54508235a0dc53091d362aaeae84bca933591c146e2e59819b70829559828b6ae4da5b615a01056edb55b99799b1c20539332f82d06ef58784e6d07743134a7b9727e75450d474182b49b2af4d2565cca8082be7ac48c1b17f519a76f1d13928062af34a9be27ba1d6a4c4ae6b4ac0dec08f11cc55f8e1b81191c301166b2fe73ed6c576d31575b6361e8394f7f0a30faf2e312adadf4789c7b045ed7258bdb0776601c3fea21fada1d154650ed05743e7f08201120c2f96fb131af0954594710cb5b9c7eb3dd0690fac1477ce913df7c2ac36e4a60d0d6cade2634499291d85f2a758bf65c202fb627dfa1f35f40699f3f3ae7be271302aa06461d10dd3690aff17ee62e717c5fd9a7f33ba328465fd107c4a3aae688672ccefb069af98046513956ade8b4e20829819ff502d0665e99a421f8d53782a73901a879996e538e8bd650518bcc2cd1e0b1457ccdb0c4eefca13b3045543e8b67fc9025f05c827537e827959577513fc48be9918e0f9f4595acf3563a97215473d3181353a211762c178efb6a900e782c50b38827a7b34d52f0aa3d2e398232a685899ca4520f7bae1f00471477e6ea2e844871587a5c6003445639dd699d7d30c01237bbde78b820af92e86d60c3de634fd56ed9502b22796cc363b4c113b2f2f2a6823ebd3c097c73e4b2de5f775da5414d22ab7da0a76bd34b5b792237571f94b24c55ae101e68902ab77fefed78bb554c51a3667d9039ff61b708643d32b6e9aa79d601a1daf7a3d5b37ec815ddc6836b08966b4b8d87d3f6d0e48eaa951ba10caebe2eb0cb1c9793b3d3ad0c965fa44fc7e951c34d4018ce82e4b5a317b3a580b4eee2c7637a3d3f38c317249adb497f6c7088c1cffea17f6b871f8c8e3d11ac8a060e7b74d6358cc741b18f19cb0cf5df052f66ceffba1e7e13f4eec0779fd68bf390b91c150f623faaa7d5e4bc6edc86f9a23fe6fdf7dbfd9a8e005b3ed1c046a74ce48263f60e7e576c1ae9a4faeda5d0dfa1ccf8ca7dbaeb9043a10e5aa3c8c86d13923821aeded744785a3201687d151cd1890bebb099e07387c1b4d57195679e081bd8167f34f3ede016a9a72e367931e1e92546de6194f0510f647f374a0c9bb3e5f5b422efdafa51fc233dc7acb49063858888f00f1cd5fbf2f61e71809145fe73add2030644159ff46e5dde146728b47be6e43ca1f82da7d396002d285a67b03588a6503c86fadc5193ddc684f7fc222f627ae4223ba133bb2728a3a93d0f2da29c8b22a2b6c3c97e0a1f496b07c2a451c27aa8fdaaa77b7d73c98a6f2363a8ed2811c597d187684bba9acc41ea9686542a93cd0d27084590b9e455aa4cf1af1198ef73ebdd2f32cd15b37d89f14f67a28e32f6fdd94d91cdaef7d40a90de57eb505ef6397a0944accdcd32dae49eb7543859cf49222014385a902ad497b9cf4a2f0516aa0e229ca836f7f2565a03c268800346615665823e7d3ecb5b40f328c0d8e307287b0f630acfb9c672c323af43a4476658601b782173dcac214ca63a7c022260cd737b3ef050b3b22c787441c1a1c3c82ae27766ee839aee4c80578556204908a2abebe7f0d1cdedbb863bf6e705f8862e15e100fc9e30cf0e4f8f5a16e985b5ad3efb589341107470bef1b781a49fb0bd5b7c5b4b396fb76bed3210ab1ec6e43e479555154d2fedebcab14c9d0b8010a2fc989123fb83c29fff3f6796af8d9c1ea3ad7c647a3271dd1aa797a435c95925b3aa09a5cf46d7dc24896d24fa7cc0747903a215c80e98de08ba4b30bf72b100cac0a1051656dfa2d3d791acdeb08d328ceae4d342fae72f8c914105ad6aa40510418e953f6f48b1e8823e1e4d5193bb6d52370d2baac0832d856123cc7dfcff6e7da5aa294a1ff51944ee3a3732208dd4c31b8008a63f560d8dae0e06a1c78e163fcb35045603039c54f5791c2df849ff3844a88e1af0b3835cb91a9fc55be34d4e9a5271d7eda26709ad6671cdf9f5fa0de9525748750d220e6f16fca88dfb1f0555bbdf28f31885febc85f8554b309bc74e902284229782c6d8ce74b9194a1b0e9e6efe256f8f529ca5d278fba3fe8f2232f9a261b91b7374fec05fadb734bb0b04f1327846c78b827beeda11d041386734d90f62d2884f8295d1866b7e549eff754cf22f28e9406f05a35dd46df3d04da7b1b8774976e208db649a517410818562e0f2535a0f49942d0fced3f73aa2da7b35c687f6cd5d488f9793b33be9d1de2410d6bd349e9197744cb5ff888c8fb307fa162bdd67034876b820957e41bc8bdb5ca49d0bd7ed18f55714de21304f826e6139908d30052e6c0947a056bc02fe18bff11e451b839be02602c3e71803a880abad17e7480a4dcf3656adef880d6520eb7f9a1366a1703b924a5f556fb74fce39c22a74cdef3d186aa38ea64c76937a5cf9ead53ac654c3947635b4571f85b8284aa0571251fd0b3a6883fcf0503ff8ea64700ab27f941190c399160462e210eb0e303bd01f7eea29f1c3dd4b604d84fc73243627e56718d732a9c6cfa89b642dd1b63307410f31787fe91a65ce9e666d5afe5cfedb0e5f1e0467731707120f078ce84840e33fdaba507a7f682fa3d6669fd668ac0571e532582a4dd29778ce0c31012ef749f3764a60479d46a8c913575ca737d4d541237aa39736b76a81723957b6be87c682e021faf0e8ba33333bd00893bfc3118c4785d7871abf5eac490fc01834dea1bb9146efadc4815b86fbf358038643b269afaed4294ed7dbbe2b47c1d669dc3af99439188d115fccee7f585d4b9c3b41c39ddb01405c5b17de27d2d00d8092a54fcac65360d84f52cc1b2b9fb246eb231aa0e06e45224dec2184f86c6ef9ebb94409618a504299c5e4fc6c3760299c6d7f07533ad1fb22da2fcaaf2b40506c063e0be29432b80b0758d1a03af33e1158b0b5df7583fa2facaa3094a700feff30c5b13d692e779a181bb05b8902a6020187b526d36356aaf9f2835810db587255f9b8a9442862dba873d3c8bcaf546253653d888577c75d8965f2c576a7f8754294e5cf458d3ace97b976ccc29fec5863e171153353d26364a9f10f5da18977e24985ad1231d61cf4f3ca1b15355f28dce005be928a2dd21f4d6fc0d8b71c26830e59f16927889be99c6fd78b72d9e7a8c0cf7fcb4f098a80bf1433b9875cc5cfe60a5a86e763bbb0f501e7c24070c90d196129105cc17a0d870291fcbffd9db6a028787beb5be2425ea819764c9906a444c097cde65939d6341d174bf493d6c98893c51fefb1f4b180366544dd8936f61abf7203520bb0dc2551c6cd935932402fa1413c9893392be23a0383d56b5e6b5e14fcdf95f8712afa4f995afd9c9702c7125b48dbfc35a036ff6297488d7f588b1353fbabec3bd2fcd449fec1fed66c53391172db8f642c8ae14fbe90b2795ff650cca5df0c278d1416d576850663ad4c836099f4d9dd4327fb48daeb958366572b886eb0bdb1db66f826dea7750b1d6947cc91900cefdf1ce308874e0fc8f3eb1d21f867e4100b025217487d1aa51b97e23caa41ca0cdde05df8128dd990404efbac0bf54e36ded9378e27de624a70b3ad711237e106641a80ad4394c5b68d497dc5fcfb9ca7cf868f6396a542d57524566bb967c759dc7aaea6e076b97e78b2e70e6186e305fad825a9ca1a42fd84fda502e7089495d300c8903b7eade093dba09d1706839f69e7c37c40f143c8990c29940ec3862f122606c621d113d33f34769f6934bd8b5c96ba19848937fa343647bfab5a51a8c92f6c5b5ca8f548c22bfda729e0bb8d8a53b99f23b5a9abaaaa3e8f41824e33e5b8fecf9fc1331300de2627100f66340ac330c210b44f773ad98a481a205fa2eb3e4e5aee1ee1fa1aa17688bf648f8131b18d42b7cfdbee75e76a03cf476be83f094907333f46a60eabb3b7f32d51f40044d513558b7b0c6a77421c0024fa161abc64239d308d97b183782bc50f6e90d22841b66035ac8ec448a4f3c2bbeb475296000b1443585d61717987a5295168d2f33659789e8485a3fb868d144f66868f90bdcbd7020e1b2b383e4b5c6f88ddea0710383b467bb9bcdeeb0000000000000000000000000000000000000b1014181a232f39 +Error = INVALID_PARAMETERS + # Short signature VerifyMessage = ML-DSA-44-Public Input = 48656c6c6f20776f726c64 @@ -197,6 +232,38 @@ Input = 48656c6c6f20776f726c64 CheckVerify +# CheckVerify with a correct context string +SignMessage = ML-DSA-44-Private +Input = 48656c6c6f20776f726c64 +Context = 436f6e74657874 +CheckVerify + +SignMessage = ML-DSA-65-Private +Input = 48656c6c6f20776f726c64 +Context = 436f6e74657874 +CheckVerify + +SignMessage = ML-DSA-87-Private +Input = 48656c6c6f20776f726c64 +Context = 436f6e74657874 +CheckVerify + +# CheckVerify with a too long context string +SignMessage = ML-DSA-44-Private +Input = 48656c6c6f20776f726c64 +Context = 41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 +Error = INVALID_PARAMETERS + +SignMessage = ML-DSA-65-Private +Input = 48656c6c6f20776f726c64 +Context = 41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 +Error = INVALID_PARAMETERS + +SignMessage = ML-DSA-87-Private +Input = 48656c6c6f20776f726c64 +Context = 41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141 +Error = INVALID_PARAMETERS + # ML-DSA does not support signing a pre-hashed value. Sign = ML-DSA-44-Private Input = 48656c6c6f20776f726c64
diff --git a/include/openssl/evp.h b/include/openssl/evp.h index ef12d51..f7785bf 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h
@@ -896,6 +896,22 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **out_md); +// EVP_PKEY_CTX_set1_signature_context_string sets the context string for a +// signature or verification operation. It returns one success and zero on +// error. The context string is an additional input to some signature +// algorithms, such as ML-DSA, to separate different uses of the same key. +// This is known as domain separation. Section 8.3 of RFC 8032 provides some +// additional guidance on context strings. +// +// Not all signature algorithms support context strings. Callers that support +// a mix of algorithms, with and without context string support, can instead +// separate the signature input itself. For example, callers can prepend +// context-specific prefixes to signature inputs. +OPENSSL_EXPORT int EVP_PKEY_CTX_set1_signature_context_string( + EVP_PKEY_CTX *ctx, + uint8_t *context, + size_t context_len); + // RSA specific control functions.
diff --git a/include/openssl/prefix_symbols.h b/include/openssl/prefix_symbols.h index 75d1ecf..9a6b269 100644 --- a/include/openssl/prefix_symbols.h +++ b/include/openssl/prefix_symbols.h
@@ -1099,6 +1099,7 @@ #pragma redefine_extname EVP_PKEY_CTX_set0_rsa_oaep_label BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set0_rsa_oaep_label)) #pragma redefine_extname EVP_PKEY_CTX_set1_hkdf_key BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set1_hkdf_key)) #pragma redefine_extname EVP_PKEY_CTX_set1_hkdf_salt BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set1_hkdf_salt)) +#pragma redefine_extname EVP_PKEY_CTX_set1_signature_context_string BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set1_signature_context_string)) #pragma redefine_extname EVP_PKEY_CTX_set_dh_pad BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set_dh_pad)) #pragma redefine_extname EVP_PKEY_CTX_set_dsa_paramgen_bits BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set_dsa_paramgen_bits)) #pragma redefine_extname EVP_PKEY_CTX_set_dsa_paramgen_q_bits BORINGSSL_SYMBOL(BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set_dsa_paramgen_q_bits)) @@ -4159,6 +4160,7 @@ #define EVP_PKEY_CTX_set0_rsa_oaep_label BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set0_rsa_oaep_label) #define EVP_PKEY_CTX_set1_hkdf_key BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set1_hkdf_key) #define EVP_PKEY_CTX_set1_hkdf_salt BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set1_hkdf_salt) +#define EVP_PKEY_CTX_set1_signature_context_string BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set1_signature_context_string) #define EVP_PKEY_CTX_set_dh_pad BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set_dh_pad) #define EVP_PKEY_CTX_set_dsa_paramgen_bits BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set_dsa_paramgen_bits) #define EVP_PKEY_CTX_set_dsa_paramgen_q_bits BORINGSSL_ADD_PREFIX(EVP_PKEY_CTX_set_dsa_paramgen_q_bits)