// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

#include <gtest/gtest.h>
#include <openssl/base.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/pem.h>
#include "../test/test_util.h"

#include <vector>
#include "../fipsmodule/evp/internal.h"
#include "../internal.h"
#include "../fipsmodule/ml_dsa/ml_dsa.h"
#include "../fipsmodule/pqdsa/internal.h"
#include "../test/file_test.h"
#include "../test/test_util.h"

// mldsa44kPublicKey is an example ML-DSA-44 public key
static const uint8_t mldsa44kPublicKey[] = {
0x88, 0x96, 0x9F, 0xBD, 0x4C, 0xC9, 0x27, 0x00, 0x57, 0xA5, 0xBF, 0xB2, 0x28,
0x9B, 0xB8, 0xB6, 0x66, 0x58, 0xB9, 0x65, 0x9A, 0x37, 0xA8, 0x2E, 0x5B, 0x5D,
0xE4, 0x85, 0xA8, 0x7F, 0x98, 0x3B, 0x57, 0x2D, 0xDB, 0xDD, 0x11, 0x7E, 0x74,
0x34, 0xCF, 0xFE, 0x78, 0x3F, 0x04, 0xBB, 0x9E, 0x7C, 0x74, 0x46, 0x00, 0xCF,
0x46, 0xA8, 0x9F, 0x53, 0x11, 0x4C, 0xBB, 0x33, 0x49, 0x50, 0x5A, 0xA5, 0x6D,
0xEA, 0x2A, 0x79, 0xF4, 0x83, 0x0E, 0x19, 0x8A, 0xCB, 0x0B, 0xDA, 0xBC, 0xFE,
0xD3, 0x0D, 0x12, 0x0B, 0x34, 0x35, 0xDB, 0x3D, 0xF7, 0x95, 0x89, 0xBF, 0x87,
0x82, 0x0A, 0x5B, 0x5E, 0x5C, 0xF1, 0x96, 0x7A, 0x46, 0xA3, 0xB5, 0x80, 0x60,
0xB4, 0xB5, 0xD1, 0x72, 0xB7, 0x2C, 0x7A, 0x99, 0x94, 0x48, 0x93, 0x0E, 0xFC,
0xEB, 0x02, 0x2F, 0x15, 0xC3, 0x5C, 0xC5, 0x4A, 0xDE, 0x84, 0xEC, 0x45, 0xBA,
0xEA, 0x1D, 0x8F, 0xD2, 0x01, 0x6F, 0xC0, 0x85, 0xDF, 0x7B, 0xBA, 0x1F, 0x52,
0xEE, 0xD1, 0xB8, 0x50, 0xBE, 0x93, 0x42, 0x87, 0x39, 0x46, 0x1C, 0xCA, 0x63,
0x4D, 0xAD, 0x5F, 0xBD, 0xEF, 0x0C, 0x9D, 0x11, 0x6E, 0xBA, 0xC2, 0x8E, 0xB7,
0x59, 0x4B, 0x1C, 0x22, 0xC0, 0x4D, 0x05, 0x37, 0x93, 0x10, 0xE6, 0xFD, 0x7A,
0xEC, 0x6C, 0x80, 0x32, 0xF9, 0x64, 0x60, 0xC7, 0x35, 0x81, 0x98, 0x42, 0xDD,
0x70, 0x0E, 0xFD, 0x13, 0x2D, 0x36, 0xF7, 0xDA, 0x3D, 0x00, 0x1B, 0x4C, 0x7D,
0xAB, 0x13, 0xAA, 0xED, 0x3B, 0xC2, 0x01, 0xB1, 0x54, 0xA7, 0x99, 0xAB, 0x7D,
0x6F, 0xA9, 0x29, 0xCF, 0xCA, 0x45, 0xBE, 0x0C, 0x2C, 0xFB, 0x04, 0xF9, 0x64,
0x60, 0xF4, 0x3A, 0x60, 0xDC, 0x62, 0x49, 0x9E, 0xBF, 0x0B, 0xE3, 0x73, 0xFC,
0xC4, 0xC2, 0x44, 0xC4, 0x6D, 0xD0, 0x3F, 0xD2, 0xC5, 0x7D, 0x0E, 0x87, 0xE5,
0x68, 0xC9, 0xEF, 0x93, 0x42, 0xCD, 0xA3, 0x2E, 0x6D, 0xA4, 0x5B, 0xD6, 0x66,
0x7B, 0x94, 0xA0, 0xA7, 0xB8, 0x7E, 0x30, 0xEE, 0x15, 0x3A, 0xB8, 0xB3, 0x68,
0x66, 0x14, 0x09, 0x22, 0xB1, 0x10, 0x52, 0x47, 0x7A, 0xDD, 0x43, 0x29, 0x77,
0x50, 0xDA, 0x60, 0xF9, 0x17, 0x43, 0xA3, 0xA8, 0x6E, 0x73, 0x47, 0x75, 0xCD,
0xEB, 0x00, 0xDC, 0xAB, 0xEE, 0xCD, 0x77, 0x3A, 0xA5, 0x0D, 0xA7, 0xDB, 0xD3,
0xAA, 0xD2, 0x21, 0xB4, 0x8F, 0xC8, 0x6F, 0x56, 0x9C, 0x20, 0xB2, 0xC6, 0x53,
0x28, 0xA6, 0x63, 0x48, 0x45, 0x78, 0x57, 0xB3, 0xF3, 0xCC, 0xED, 0xAD, 0x30,
0x38, 0x45, 0x02, 0x3E, 0xF8, 0x86, 0x29, 0xA9, 0x56, 0xAA, 0x8C, 0x83, 0xC8,
0x7C, 0xF3, 0x04, 0x64, 0x57, 0xE5, 0x62, 0xFB, 0x53, 0x3B, 0x9E, 0xF9, 0x44,
0xB2, 0x47, 0xFF, 0x0A, 0x60, 0x06, 0x34, 0xD4, 0x85, 0x9B, 0xF4, 0x2E, 0x13,
0xB8, 0x99, 0x6F, 0xC6, 0x9A, 0x9B, 0x69, 0x10, 0x46, 0x78, 0xB0, 0x63, 0x26,
0x18, 0x73, 0xEB, 0x0A, 0x64, 0xA8, 0x10, 0x5B, 0xA3, 0xBD, 0x7B, 0x67, 0xF0,
0x8E, 0x49, 0x7E, 0xB5, 0x7D, 0xCF, 0xA8, 0xD3, 0x88, 0xAD, 0x01, 0xC2, 0x12,
0x89, 0x31, 0xCD, 0x9C, 0xC9, 0x57, 0x97, 0x70, 0x79, 0x0E, 0x16, 0x71, 0x85,
0x79, 0x39, 0x41, 0x63, 0xF8, 0x2E, 0x4D, 0x53, 0x88, 0xBE, 0xED, 0xC9, 0x82,
0xBD, 0x0F, 0x81, 0x22, 0x40, 0x14, 0xAF, 0xA4, 0x07, 0x10, 0x7C, 0x07, 0xAA,
0xF3, 0x27, 0x11, 0x19, 0x2F, 0xFF, 0xFE, 0xBB, 0x0A, 0xF5, 0xC1, 0xBF, 0x2C,
0x93, 0x00, 0xCE, 0xF1, 0xF7, 0x7F, 0xEA, 0x68, 0x39, 0x04, 0x48, 0xBF, 0x42,
0x01, 0xBB, 0x51, 0x82, 0x36, 0x3C, 0x93, 0x55, 0x43, 0x7C, 0x2C, 0xFF, 0xE1,
0xD8, 0x51, 0x5B, 0xC3, 0xB4, 0x57, 0x72, 0x24, 0xAB, 0xDD, 0xDA, 0x14, 0x71,
0x0C, 0xC0, 0x9B, 0x73, 0x46, 0xF7, 0xE4, 0x12, 0x15, 0x8B, 0x26, 0x44, 0xD7,
0xD3, 0xF1, 0x86, 0xD5, 0xA4, 0x90, 0xA9, 0x0C, 0x89, 0x26, 0x8A, 0x67, 0xCB,
0xA0, 0xFF, 0x45, 0x8D, 0xB0, 0xF4, 0x5D, 0x78, 0x77, 0x38, 0x34, 0x7E, 0xDE,
0x65, 0x8A, 0x68, 0x69, 0x26, 0xD3, 0x2D, 0xD8, 0x95, 0xD9, 0x3A, 0x88, 0x4E,
0x8E, 0x9B, 0x9C, 0x83, 0x21, 0x18, 0x6B, 0xE1, 0x4A, 0xEC, 0x43, 0x39, 0xF8,
0xD7, 0xC4, 0x77, 0x32, 0xDD, 0x20, 0x51, 0x2B, 0x90, 0x08, 0x5B, 0x51, 0xF1,
0x3C, 0x73, 0x68, 0x89, 0x18, 0x8E, 0xD2, 0x9C, 0x9A, 0x32, 0xAE, 0x49, 0xA5,
0x19, 0xED, 0xE4, 0x1E, 0x6B, 0x78, 0x7D, 0x4A, 0x92, 0x07, 0x07, 0x75, 0x19,
0x7A, 0x0B, 0xC1, 0x79, 0xFF, 0xB4, 0xCF, 0x26, 0x28, 0x3B, 0xF8, 0xC6, 0xE4,
0x89, 0x8C, 0x92, 0x39, 0xC3, 0x81, 0x63, 0xC4, 0xAA, 0xE3, 0xE2, 0x00, 0x7F,
0xB0, 0x77, 0xE9, 0x07, 0xE4, 0x38, 0xA4, 0xFC, 0x2F, 0x67, 0xD1, 0xED, 0x22,
0xA3, 0xCB, 0x31, 0x79, 0xB9, 0x38, 0xDB, 0x12, 0x50, 0x1A, 0x0F, 0xE6, 0x53,
0x09, 0xD1, 0x06, 0xD1, 0xE4, 0x35, 0x2F, 0x93, 0x5B, 0x5A, 0x6C, 0x27, 0x06,
0xC4, 0x77, 0xED, 0x6F, 0xB5, 0x41, 0x87, 0xF6, 0x26, 0xAA, 0x96, 0xC1, 0x76,
0xE1, 0x1C, 0x0F, 0x13, 0x2D, 0x05, 0xBA, 0x38, 0x52, 0x7B, 0xD2, 0x71, 0xDF,
0xF0, 0xF9, 0x5E, 0x85, 0x45, 0x52, 0xDC, 0x2A, 0x8A, 0x20, 0x05, 0x8F, 0x11,
0xDE, 0x0C, 0x9E, 0x6B, 0xC9, 0x36, 0xDE, 0x05, 0xE9, 0xC9, 0xFD, 0xED, 0x80,
0xA8, 0x63, 0xFC, 0xE5, 0x3B, 0x29, 0x81, 0x4F, 0x25, 0xF3, 0x59, 0xCC, 0x8F,
0x40, 0xA9, 0x6B, 0x67, 0x1E, 0x67, 0x29, 0x19, 0x27, 0x14, 0xF2, 0xDC, 0x2C,
0x9D, 0xFF, 0x73, 0x60, 0x29, 0x22, 0xF6, 0x10, 0x12, 0x39, 0xE8, 0xB8, 0xB9,
0xD0, 0x90, 0xC7, 0xE1, 0x10, 0x0D, 0x30, 0xC5, 0x11, 0x85, 0x7C, 0x0B, 0x0C,
0x29, 0xD9, 0x4A, 0xBA, 0xBB, 0xE9, 0xF6, 0x4E, 0xEC, 0x1B, 0x62, 0x48, 0x0C,
0x7A, 0xFA, 0x9A, 0xF9, 0x12, 0xA5, 0xC3, 0x3E, 0x67, 0x0B, 0x7A, 0x27, 0x2B,
0x20, 0xB2, 0x82, 0x5C, 0x86, 0xEA, 0x31, 0x8A, 0x90, 0xE6, 0xFA, 0x45, 0x36,
0x41, 0x53, 0x78, 0x57, 0x88, 0x76, 0x97, 0x3D, 0xB0, 0x8A, 0x43, 0x2B, 0x67,
0x79, 0x96, 0x35, 0x7D, 0xEF, 0x9C, 0x93, 0xBA, 0xD2, 0x91, 0x86, 0xCF, 0x52,
0xD5, 0x96, 0xAA, 0xD0, 0x45, 0xD8, 0x3C, 0x93, 0xC4, 0xC2, 0xC3, 0x5F, 0x4A,
0x23, 0xD4, 0xC7, 0xE4, 0x1D, 0x3B, 0xD1, 0x8F, 0x91, 0x36, 0xFA, 0x64, 0x15,
0xA8, 0xA8, 0xD1, 0x95, 0xCD, 0x2C, 0x99, 0x8A, 0x34, 0x0A, 0x5E, 0x0E, 0xB0,
0x6A, 0x8E, 0xF2, 0xE8, 0xE9, 0xF9, 0x67, 0xF6, 0xD6, 0x33, 0xBE, 0xD3, 0xB7,
0x94, 0x8B, 0x27, 0xB2, 0x33, 0xE2, 0x41, 0xE3, 0x9E, 0x12, 0xE4, 0x21, 0x35,
0x58, 0xD6, 0xDE, 0xB5, 0xAC, 0xF2, 0x72, 0xC4, 0x32, 0x72, 0xB8, 0x2E, 0x7D,
0xD0, 0xF3, 0xE3, 0x56, 0x86, 0xFD, 0x5F, 0xD0, 0x66, 0x64, 0xB4, 0x92, 0x27,
0xCA, 0x36, 0xE1, 0x57, 0x9F, 0xC0, 0x0D, 0x0E, 0xBE, 0xA6, 0x42, 0xAD, 0xD9,
0x7D, 0x9A, 0x7D, 0x1F, 0x87, 0x17, 0x46, 0x3B, 0xA5, 0x40, 0x9C, 0xD2, 0x9F,
0xD6, 0x73, 0xC6, 0xFA, 0xD3, 0x03, 0x27, 0x01, 0x59, 0x8D, 0x5F, 0xB8, 0xAF,
0x2D, 0xCE, 0x06, 0xA2, 0x73, 0xE2, 0xE4, 0xC9, 0xE2, 0x14, 0x58, 0xA8, 0x2C,
0xC6, 0xBF, 0x72, 0x8E, 0x87, 0x84, 0x81, 0x7B, 0x62, 0x5A, 0x13, 0x7D, 0xFF,
0x38, 0x9E, 0x97, 0xEF, 0x91, 0x45, 0xB6, 0xC6, 0xCF, 0x0E, 0xC0, 0xBA, 0x2A,
0xAE, 0x41, 0x44, 0x48, 0xE5, 0x52, 0x45, 0x15, 0x01, 0xE0, 0xF7, 0x98, 0xAB,
0x45, 0x26, 0x25, 0xCA, 0x95, 0x6D, 0xB2, 0x04, 0xB7, 0x93, 0x06, 0xE2, 0x8F,
0xF5, 0x59, 0xA7, 0xD6, 0x69, 0x4D, 0x03, 0x07, 0x45, 0xE7, 0xE6, 0xA4, 0x8A,
0x8B, 0xBD, 0xB8, 0x09, 0x9F, 0x33, 0xD5, 0x58, 0x88, 0xC3, 0xD8, 0x55, 0x26,
0xCE, 0x94, 0x21, 0x08, 0x43, 0x36, 0x57, 0xE8, 0x6A, 0x5D, 0x4D, 0x5B, 0x00,
0x4D, 0x58, 0xB3, 0x29, 0xE4, 0x23, 0xF5, 0x3B, 0x78, 0xD4, 0x3D, 0x08, 0xE3,
0xC2, 0x26, 0x16, 0x86, 0x4A, 0xD2, 0x5B, 0x08, 0x3D, 0xE4, 0x31, 0x5A, 0x77,
0x40, 0xFA, 0xC4, 0x4B, 0x78, 0xB1, 0x16, 0xEA, 0x57, 0xA5, 0x63, 0x2A, 0x7C,
0x4C, 0x0D, 0xF5, 0xD4, 0xD4, 0x1C, 0x7A, 0x28, 0x96, 0xAF, 0xEB, 0x23, 0x32,
0x2F, 0x84, 0x68, 0x33, 0x94, 0x60, 0xDD, 0x65, 0xBA, 0x4F, 0x88, 0x25, 0x5F,
0x42, 0x86, 0xD7, 0xF8, 0x3D, 0x6D, 0xDF, 0xA1, 0x08, 0x67, 0xCA, 0xFB, 0xB0,
0x0B, 0x3C, 0x0F, 0xB0, 0x69, 0xD5, 0x44, 0x56, 0x6D, 0xB7, 0xCF, 0x1D, 0xA2,
0x38, 0x3C, 0x72, 0xC7, 0x6C, 0x9D, 0x08, 0xCF, 0xDE, 0x2D, 0x99, 0x85, 0x8A,
0xD3, 0xC9, 0xCE, 0x59, 0x86, 0x63, 0x9A, 0x20, 0xD8, 0x54, 0xA6, 0x30, 0xF7,
0x6D, 0xFC, 0x99, 0xDF, 0xF3, 0x85, 0xD7, 0xCE, 0xEC, 0x83, 0x9B, 0x45, 0x3C,
0xA9, 0x7B, 0x52, 0xBB, 0xB6, 0x31, 0xCF, 0x1F, 0xD2, 0x99, 0x1D, 0x5A, 0x30,
0xB5, 0x63, 0x3E, 0x28, 0x0B, 0xA4, 0x61, 0xD9, 0xE9, 0xBD, 0x04, 0x70, 0x76,
0x83, 0x4C, 0x35, 0x60, 0x7A, 0x0A, 0x55, 0x6C, 0x9C, 0x9F, 0x6A, 0x42, 0xBE,
0x1F, 0xDD, 0x89, 0x55, 0x87, 0x48, 0xF3, 0xBB, 0x64, 0x17, 0xFA, 0x17, 0x60,
0xC4, 0xDC, 0xB6, 0xBF, 0xB7, 0x56, 0x64, 0x6E, 0x0A, 0xC3, 0x6B, 0x33, 0x8A,
0xAC, 0x6C, 0x97, 0x86, 0xB4, 0x27, 0x0D, 0xB0, 0x36, 0x3F, 0x3C, 0x6D, 0x7C,
0x66, 0x13, 0x94, 0xFB, 0x0E, 0x8E, 0xE8, 0x0E, 0x49, 0xEF, 0xD0, 0x0E};

// mldsa44kPublicKeySPKI is the above example ML-DSA-44 public key encoded
static const uint8_t mldsa44kPublicKeySPKI[] = {
0x30, 0x82, 0x05, 0x32, 0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
0x03, 0x04, 0x03, 0x11, 0x03, 0x82, 0x05, 0x21, 0x00, 0x88, 0x96, 0x9F, 0xBD,
0x4C, 0xC9, 0x27, 0x00, 0x57, 0xA5, 0xBF, 0xB2, 0x28, 0x9B, 0xB8, 0xB6, 0x66,
0x58, 0xB9, 0x65, 0x9A, 0x37, 0xA8, 0x2E, 0x5B, 0x5D, 0xE4, 0x85, 0xA8, 0x7F,
0x98, 0x3B, 0x57, 0x2D, 0xDB, 0xDD, 0x11, 0x7E, 0x74, 0x34, 0xCF, 0xFE, 0x78,
0x3F, 0x04, 0xBB, 0x9E, 0x7C, 0x74, 0x46, 0x00, 0xCF, 0x46, 0xA8, 0x9F, 0x53,
0x11, 0x4C, 0xBB, 0x33, 0x49, 0x50, 0x5A, 0xA5, 0x6D, 0xEA, 0x2A, 0x79, 0xF4,
0x83, 0x0E, 0x19, 0x8A, 0xCB, 0x0B, 0xDA, 0xBC, 0xFE, 0xD3, 0x0D, 0x12, 0x0B,
0x34, 0x35, 0xDB, 0x3D, 0xF7, 0x95, 0x89, 0xBF, 0x87, 0x82, 0x0A, 0x5B, 0x5E,
0x5C, 0xF1, 0x96, 0x7A, 0x46, 0xA3, 0xB5, 0x80, 0x60, 0xB4, 0xB5, 0xD1, 0x72,
0xB7, 0x2C, 0x7A, 0x99, 0x94, 0x48, 0x93, 0x0E, 0xFC, 0xEB, 0x02, 0x2F, 0x15,
0xC3, 0x5C, 0xC5, 0x4A, 0xDE, 0x84, 0xEC, 0x45, 0xBA, 0xEA, 0x1D, 0x8F, 0xD2,
0x01, 0x6F, 0xC0, 0x85, 0xDF, 0x7B, 0xBA, 0x1F, 0x52, 0xEE, 0xD1, 0xB8, 0x50,
0xBE, 0x93, 0x42, 0x87, 0x39, 0x46, 0x1C, 0xCA, 0x63, 0x4D, 0xAD, 0x5F, 0xBD,
0xEF, 0x0C, 0x9D, 0x11, 0x6E, 0xBA, 0xC2, 0x8E, 0xB7, 0x59, 0x4B, 0x1C, 0x22,
0xC0, 0x4D, 0x05, 0x37, 0x93, 0x10, 0xE6, 0xFD, 0x7A, 0xEC, 0x6C, 0x80, 0x32,
0xF9, 0x64, 0x60, 0xC7, 0x35, 0x81, 0x98, 0x42, 0xDD, 0x70, 0x0E, 0xFD, 0x13,
0x2D, 0x36, 0xF7, 0xDA, 0x3D, 0x00, 0x1B, 0x4C, 0x7D, 0xAB, 0x13, 0xAA, 0xED,
0x3B, 0xC2, 0x01, 0xB1, 0x54, 0xA7, 0x99, 0xAB, 0x7D, 0x6F, 0xA9, 0x29, 0xCF,
0xCA, 0x45, 0xBE, 0x0C, 0x2C, 0xFB, 0x04, 0xF9, 0x64, 0x60, 0xF4, 0x3A, 0x60,
0xDC, 0x62, 0x49, 0x9E, 0xBF, 0x0B, 0xE3, 0x73, 0xFC, 0xC4, 0xC2, 0x44, 0xC4,
0x6D, 0xD0, 0x3F, 0xD2, 0xC5, 0x7D, 0x0E, 0x87, 0xE5, 0x68, 0xC9, 0xEF, 0x93,
0x42, 0xCD, 0xA3, 0x2E, 0x6D, 0xA4, 0x5B, 0xD6, 0x66, 0x7B, 0x94, 0xA0, 0xA7,
0xB8, 0x7E, 0x30, 0xEE, 0x15, 0x3A, 0xB8, 0xB3, 0x68, 0x66, 0x14, 0x09, 0x22,
0xB1, 0x10, 0x52, 0x47, 0x7A, 0xDD, 0x43, 0x29, 0x77, 0x50, 0xDA, 0x60, 0xF9,
0x17, 0x43, 0xA3, 0xA8, 0x6E, 0x73, 0x47, 0x75, 0xCD, 0xEB, 0x00, 0xDC, 0xAB,
0xEE, 0xCD, 0x77, 0x3A, 0xA5, 0x0D, 0xA7, 0xDB, 0xD3, 0xAA, 0xD2, 0x21, 0xB4,
0x8F, 0xC8, 0x6F, 0x56, 0x9C, 0x20, 0xB2, 0xC6, 0x53, 0x28, 0xA6, 0x63, 0x48,
0x45, 0x78, 0x57, 0xB3, 0xF3, 0xCC, 0xED, 0xAD, 0x30, 0x38, 0x45, 0x02, 0x3E,
0xF8, 0x86, 0x29, 0xA9, 0x56, 0xAA, 0x8C, 0x83, 0xC8, 0x7C, 0xF3, 0x04, 0x64,
0x57, 0xE5, 0x62, 0xFB, 0x53, 0x3B, 0x9E, 0xF9, 0x44, 0xB2, 0x47, 0xFF, 0x0A,
0x60, 0x06, 0x34, 0xD4, 0x85, 0x9B, 0xF4, 0x2E, 0x13, 0xB8, 0x99, 0x6F, 0xC6,
0x9A, 0x9B, 0x69, 0x10, 0x46, 0x78, 0xB0, 0x63, 0x26, 0x18, 0x73, 0xEB, 0x0A,
0x64, 0xA8, 0x10, 0x5B, 0xA3, 0xBD, 0x7B, 0x67, 0xF0, 0x8E, 0x49, 0x7E, 0xB5,
0x7D, 0xCF, 0xA8, 0xD3, 0x88, 0xAD, 0x01, 0xC2, 0x12, 0x89, 0x31, 0xCD, 0x9C,
0xC9, 0x57, 0x97, 0x70, 0x79, 0x0E, 0x16, 0x71, 0x85, 0x79, 0x39, 0x41, 0x63,
0xF8, 0x2E, 0x4D, 0x53, 0x88, 0xBE, 0xED, 0xC9, 0x82, 0xBD, 0x0F, 0x81, 0x22,
0x40, 0x14, 0xAF, 0xA4, 0x07, 0x10, 0x7C, 0x07, 0xAA, 0xF3, 0x27, 0x11, 0x19,
0x2F, 0xFF, 0xFE, 0xBB, 0x0A, 0xF5, 0xC1, 0xBF, 0x2C, 0x93, 0x00, 0xCE, 0xF1,
0xF7, 0x7F, 0xEA, 0x68, 0x39, 0x04, 0x48, 0xBF, 0x42, 0x01, 0xBB, 0x51, 0x82,
0x36, 0x3C, 0x93, 0x55, 0x43, 0x7C, 0x2C, 0xFF, 0xE1, 0xD8, 0x51, 0x5B, 0xC3,
0xB4, 0x57, 0x72, 0x24, 0xAB, 0xDD, 0xDA, 0x14, 0x71, 0x0C, 0xC0, 0x9B, 0x73,
0x46, 0xF7, 0xE4, 0x12, 0x15, 0x8B, 0x26, 0x44, 0xD7, 0xD3, 0xF1, 0x86, 0xD5,
0xA4, 0x90, 0xA9, 0x0C, 0x89, 0x26, 0x8A, 0x67, 0xCB, 0xA0, 0xFF, 0x45, 0x8D,
0xB0, 0xF4, 0x5D, 0x78, 0x77, 0x38, 0x34, 0x7E, 0xDE, 0x65, 0x8A, 0x68, 0x69,
0x26, 0xD3, 0x2D, 0xD8, 0x95, 0xD9, 0x3A, 0x88, 0x4E, 0x8E, 0x9B, 0x9C, 0x83,
0x21, 0x18, 0x6B, 0xE1, 0x4A, 0xEC, 0x43, 0x39, 0xF8, 0xD7, 0xC4, 0x77, 0x32,
0xDD, 0x20, 0x51, 0x2B, 0x90, 0x08, 0x5B, 0x51, 0xF1, 0x3C, 0x73, 0x68, 0x89,
0x18, 0x8E, 0xD2, 0x9C, 0x9A, 0x32, 0xAE, 0x49, 0xA5, 0x19, 0xED, 0xE4, 0x1E,
0x6B, 0x78, 0x7D, 0x4A, 0x92, 0x07, 0x07, 0x75, 0x19, 0x7A, 0x0B, 0xC1, 0x79,
0xFF, 0xB4, 0xCF, 0x26, 0x28, 0x3B, 0xF8, 0xC6, 0xE4, 0x89, 0x8C, 0x92, 0x39,
0xC3, 0x81, 0x63, 0xC4, 0xAA, 0xE3, 0xE2, 0x00, 0x7F, 0xB0, 0x77, 0xE9, 0x07,
0xE4, 0x38, 0xA4, 0xFC, 0x2F, 0x67, 0xD1, 0xED, 0x22, 0xA3, 0xCB, 0x31, 0x79,
0xB9, 0x38, 0xDB, 0x12, 0x50, 0x1A, 0x0F, 0xE6, 0x53, 0x09, 0xD1, 0x06, 0xD1,
0xE4, 0x35, 0x2F, 0x93, 0x5B, 0x5A, 0x6C, 0x27, 0x06, 0xC4, 0x77, 0xED, 0x6F,
0xB5, 0x41, 0x87, 0xF6, 0x26, 0xAA, 0x96, 0xC1, 0x76, 0xE1, 0x1C, 0x0F, 0x13,
0x2D, 0x05, 0xBA, 0x38, 0x52, 0x7B, 0xD2, 0x71, 0xDF, 0xF0, 0xF9, 0x5E, 0x85,
0x45, 0x52, 0xDC, 0x2A, 0x8A, 0x20, 0x05, 0x8F, 0x11, 0xDE, 0x0C, 0x9E, 0x6B,
0xC9, 0x36, 0xDE, 0x05, 0xE9, 0xC9, 0xFD, 0xED, 0x80, 0xA8, 0x63, 0xFC, 0xE5,
0x3B, 0x29, 0x81, 0x4F, 0x25, 0xF3, 0x59, 0xCC, 0x8F, 0x40, 0xA9, 0x6B, 0x67,
0x1E, 0x67, 0x29, 0x19, 0x27, 0x14, 0xF2, 0xDC, 0x2C, 0x9D, 0xFF, 0x73, 0x60,
0x29, 0x22, 0xF6, 0x10, 0x12, 0x39, 0xE8, 0xB8, 0xB9, 0xD0, 0x90, 0xC7, 0xE1,
0x10, 0x0D, 0x30, 0xC5, 0x11, 0x85, 0x7C, 0x0B, 0x0C, 0x29, 0xD9, 0x4A, 0xBA,
0xBB, 0xE9, 0xF6, 0x4E, 0xEC, 0x1B, 0x62, 0x48, 0x0C, 0x7A, 0xFA, 0x9A, 0xF9,
0x12, 0xA5, 0xC3, 0x3E, 0x67, 0x0B, 0x7A, 0x27, 0x2B, 0x20, 0xB2, 0x82, 0x5C,
0x86, 0xEA, 0x31, 0x8A, 0x90, 0xE6, 0xFA, 0x45, 0x36, 0x41, 0x53, 0x78, 0x57,
0x88, 0x76, 0x97, 0x3D, 0xB0, 0x8A, 0x43, 0x2B, 0x67, 0x79, 0x96, 0x35, 0x7D,
0xEF, 0x9C, 0x93, 0xBA, 0xD2, 0x91, 0x86, 0xCF, 0x52, 0xD5, 0x96, 0xAA, 0xD0,
0x45, 0xD8, 0x3C, 0x93, 0xC4, 0xC2, 0xC3, 0x5F, 0x4A, 0x23, 0xD4, 0xC7, 0xE4,
0x1D, 0x3B, 0xD1, 0x8F, 0x91, 0x36, 0xFA, 0x64, 0x15, 0xA8, 0xA8, 0xD1, 0x95,
0xCD, 0x2C, 0x99, 0x8A, 0x34, 0x0A, 0x5E, 0x0E, 0xB0, 0x6A, 0x8E, 0xF2, 0xE8,
0xE9, 0xF9, 0x67, 0xF6, 0xD6, 0x33, 0xBE, 0xD3, 0xB7, 0x94, 0x8B, 0x27, 0xB2,
0x33, 0xE2, 0x41, 0xE3, 0x9E, 0x12, 0xE4, 0x21, 0x35, 0x58, 0xD6, 0xDE, 0xB5,
0xAC, 0xF2, 0x72, 0xC4, 0x32, 0x72, 0xB8, 0x2E, 0x7D, 0xD0, 0xF3, 0xE3, 0x56,
0x86, 0xFD, 0x5F, 0xD0, 0x66, 0x64, 0xB4, 0x92, 0x27, 0xCA, 0x36, 0xE1, 0x57,
0x9F, 0xC0, 0x0D, 0x0E, 0xBE, 0xA6, 0x42, 0xAD, 0xD9, 0x7D, 0x9A, 0x7D, 0x1F,
0x87, 0x17, 0x46, 0x3B, 0xA5, 0x40, 0x9C, 0xD2, 0x9F, 0xD6, 0x73, 0xC6, 0xFA,
0xD3, 0x03, 0x27, 0x01, 0x59, 0x8D, 0x5F, 0xB8, 0xAF, 0x2D, 0xCE, 0x06, 0xA2,
0x73, 0xE2, 0xE4, 0xC9, 0xE2, 0x14, 0x58, 0xA8, 0x2C, 0xC6, 0xBF, 0x72, 0x8E,
0x87, 0x84, 0x81, 0x7B, 0x62, 0x5A, 0x13, 0x7D, 0xFF, 0x38, 0x9E, 0x97, 0xEF,
0x91, 0x45, 0xB6, 0xC6, 0xCF, 0x0E, 0xC0, 0xBA, 0x2A, 0xAE, 0x41, 0x44, 0x48,
0xE5, 0x52, 0x45, 0x15, 0x01, 0xE0, 0xF7, 0x98, 0xAB, 0x45, 0x26, 0x25, 0xCA,
0x95, 0x6D, 0xB2, 0x04, 0xB7, 0x93, 0x06, 0xE2, 0x8F, 0xF5, 0x59, 0xA7, 0xD6,
0x69, 0x4D, 0x03, 0x07, 0x45, 0xE7, 0xE6, 0xA4, 0x8A, 0x8B, 0xBD, 0xB8, 0x09,
0x9F, 0x33, 0xD5, 0x58, 0x88, 0xC3, 0xD8, 0x55, 0x26, 0xCE, 0x94, 0x21, 0x08,
0x43, 0x36, 0x57, 0xE8, 0x6A, 0x5D, 0x4D, 0x5B, 0x00, 0x4D, 0x58, 0xB3, 0x29,
0xE4, 0x23, 0xF5, 0x3B, 0x78, 0xD4, 0x3D, 0x08, 0xE3, 0xC2, 0x26, 0x16, 0x86,
0x4A, 0xD2, 0x5B, 0x08, 0x3D, 0xE4, 0x31, 0x5A, 0x77, 0x40, 0xFA, 0xC4, 0x4B,
0x78, 0xB1, 0x16, 0xEA, 0x57, 0xA5, 0x63, 0x2A, 0x7C, 0x4C, 0x0D, 0xF5, 0xD4,
0xD4, 0x1C, 0x7A, 0x28, 0x96, 0xAF, 0xEB, 0x23, 0x32, 0x2F, 0x84, 0x68, 0x33,
0x94, 0x60, 0xDD, 0x65, 0xBA, 0x4F, 0x88, 0x25, 0x5F, 0x42, 0x86, 0xD7, 0xF8,
0x3D, 0x6D, 0xDF, 0xA1, 0x08, 0x67, 0xCA, 0xFB, 0xB0, 0x0B, 0x3C, 0x0F, 0xB0,
0x69, 0xD5, 0x44, 0x56, 0x6D, 0xB7, 0xCF, 0x1D, 0xA2, 0x38, 0x3C, 0x72, 0xC7,
0x6C, 0x9D, 0x08, 0xCF, 0xDE, 0x2D, 0x99, 0x85, 0x8A, 0xD3, 0xC9, 0xCE, 0x59,
0x86, 0x63, 0x9A, 0x20, 0xD8, 0x54, 0xA6, 0x30, 0xF7, 0x6D, 0xFC, 0x99, 0xDF,
0xF3, 0x85, 0xD7, 0xCE, 0xEC, 0x83, 0x9B, 0x45, 0x3C, 0xA9, 0x7B, 0x52, 0xBB,
0xB6, 0x31, 0xCF, 0x1F, 0xD2, 0x99, 0x1D, 0x5A, 0x30, 0xB5, 0x63, 0x3E, 0x28,
0x0B, 0xA4, 0x61, 0xD9, 0xE9, 0xBD, 0x04, 0x70, 0x76, 0x83, 0x4C, 0x35, 0x60,
0x7A, 0x0A, 0x55, 0x6C, 0x9C, 0x9F, 0x6A, 0x42, 0xBE, 0x1F, 0xDD, 0x89, 0x55,
0x87, 0x48, 0xF3, 0xBB, 0x64, 0x17, 0xFA, 0x17, 0x60, 0xC4, 0xDC, 0xB6, 0xBF,
0xB7, 0x56, 0x64, 0x6E, 0x0A, 0xC3, 0x6B, 0x33, 0x8A, 0xAC, 0x6C, 0x97, 0x86,
0xB4, 0x27, 0x0D, 0xB0, 0x36, 0x3F, 0x3C, 0x6D, 0x7C, 0x66, 0x13, 0x94, 0xFB,
0x0E, 0x8E, 0xE8, 0x0E, 0x49, 0xEF, 0xD0, 0x0E};

// mldsa65kPublicKey is an example ML-DSA-65 public key
static const uint8_t mldsa65kPublicKey[] = {
0x9B, 0x77, 0xAB, 0x96, 0x9D, 0x65, 0xA2, 0xC1, 0x55, 0x65, 0x02, 0x9B, 0xA5,
0xD4, 0xE5, 0x93, 0xA1, 0xAC, 0xE7, 0x3E, 0x8C, 0x61, 0xB7, 0xCB, 0xA1, 0x3E,
0x74, 0x8A, 0xC9, 0xC0, 0xA0, 0x63, 0x4A, 0xF6, 0xF4, 0x1C, 0x72, 0x37, 0xB0,
0x31, 0x9E, 0xB7, 0x51, 0x55, 0xCF, 0x5B, 0x4E, 0x03, 0x46, 0x7C, 0x26, 0xBE,
0x84, 0x73, 0xD8, 0x50, 0xDF, 0x72, 0x87, 0xC0, 0x18, 0xED, 0xE7, 0xE4, 0x12,
0x4F, 0xCA, 0x4E, 0x1A, 0xFA, 0x76, 0x82, 0xD4, 0xA6, 0x3E, 0xDA, 0xEC, 0x74,
0x53, 0xFF, 0xDD, 0x69, 0x5C, 0x9F, 0xFD, 0x69, 0xA3, 0xED, 0x4F, 0xEB, 0xFB,
0xEF, 0xD2, 0x98, 0x8B, 0x45, 0x06, 0xBA, 0xD5, 0xF8, 0x9E, 0x0A, 0x2D, 0xA2,
0xC7, 0x96, 0x4B, 0x79, 0xE9, 0xA9, 0xA6, 0x73, 0x69, 0xF8, 0x8C, 0x01, 0x69,
0xF2, 0x66, 0x05, 0x37, 0x31, 0x65, 0xA9, 0x09, 0x3E, 0x0E, 0x73, 0x95, 0x67,
0xC9, 0x33, 0xA6, 0x57, 0xDF, 0xDD, 0xC0, 0x55, 0x1A, 0x89, 0x6F, 0xC8, 0x30,
0x71, 0x68, 0x3C, 0x2A, 0x7E, 0x61, 0x86, 0xAC, 0x70, 0x6A, 0x27, 0x31, 0x9B,
0x9A, 0xEC, 0x8F, 0x37, 0x2B, 0x71, 0x91, 0x91, 0x6C, 0x8B, 0x35, 0xED, 0xF1,
0x97, 0x87, 0x58, 0xD1, 0x4F, 0xF2, 0x06, 0x23, 0xE6, 0x1C, 0x44, 0x63, 0x02,
0x9E, 0x09, 0x76, 0x6C, 0x72, 0xBD, 0x0D, 0xB3, 0xE2, 0x1D, 0x92, 0xAA, 0x8D,
0x7B, 0x78, 0xD8, 0xB3, 0xA7, 0x5A, 0xAB, 0xBF, 0x22, 0xBB, 0x30, 0x5B, 0xFB,
0xB4, 0x3C, 0x52, 0xD2, 0xA2, 0xED, 0x3B, 0x99, 0x43, 0xCB, 0x29, 0x66, 0x2A,
0xBD, 0x52, 0x1B, 0x1C, 0xB4, 0xE5, 0xE3, 0x6E, 0xFF, 0xAD, 0xEF, 0x8B, 0xE1,
0xF9, 0xB5, 0x5E, 0xCB, 0xF2, 0x8E, 0xCD, 0x53, 0x39, 0xBE, 0xBE, 0x61, 0x72,
0x86, 0x31, 0x65, 0xA0, 0xFC, 0xC1, 0xFC, 0x31, 0x79, 0x93, 0xDF, 0x76, 0x13,
0x71, 0xE4, 0x61, 0x0F, 0x6B, 0x32, 0x78, 0xD2, 0x24, 0xB7, 0x8C, 0xE8, 0x84,
0xE3, 0xB8, 0xF6, 0x04, 0xF3, 0x30, 0xE9, 0x5B, 0xA5, 0xD8, 0x94, 0xA7, 0xA3,
0xF0, 0xE8, 0xAC, 0x70, 0x32, 0x42, 0xB5, 0x08, 0xEE, 0x2A, 0x77, 0xFA, 0x04,
0x49, 0xE9, 0x7A, 0xB7, 0x0A, 0x95, 0x05, 0x86, 0x33, 0xA5, 0xE4, 0x5A, 0xC6,
0xE1, 0xE7, 0x48, 0xBD, 0xBA, 0x80, 0xE7, 0x21, 0x61, 0x45, 0x24, 0x5E, 0xA9,
0x7F, 0x2D, 0x75, 0x0F, 0xE9, 0xEE, 0x79, 0x88, 0x64, 0xF3, 0xE7, 0x0C, 0xA0,
0xEB, 0x93, 0x2C, 0x6B, 0xD3, 0x51, 0x12, 0xE7, 0x62, 0x8D, 0x71, 0x10, 0x6D,
0x5B, 0x3A, 0x27, 0xF4, 0xEA, 0x80, 0xFC, 0xCD, 0x58, 0x81, 0x43, 0xEB, 0xA0,
0x4E, 0xF5, 0xA1, 0x68, 0x67, 0x74, 0x7C, 0x14, 0x12, 0xA6, 0x78, 0xC2, 0x08,
0x58, 0x3F, 0x20, 0x96, 0x52, 0xD2, 0x61, 0xDA, 0xED, 0x5F, 0x7F, 0xAD, 0x40,
0x93, 0x21, 0xEB, 0xC4, 0x37, 0x5C, 0xD1, 0x72, 0xE6, 0x06, 0x37, 0xD9, 0xF6,
0x09, 0xD4, 0xC9, 0x6D, 0xED, 0x07, 0xF6, 0xD2, 0x15, 0x94, 0xFD, 0xF6, 0xC3,
0x09, 0x60, 0x6D, 0x6A, 0x23, 0x50, 0x8C, 0xDD, 0x61, 0xDD, 0x66, 0x81, 0xB0,
0xAC, 0x7C, 0xE7, 0x7F, 0xED, 0x3C, 0x2F, 0x19, 0xB5, 0xF9, 0xB7, 0x2E, 0x35,
0xF7, 0xF4, 0x98, 0x0E, 0x6A, 0x9E, 0x6D, 0xAC, 0xF1, 0x0F, 0x90, 0x25, 0xED,
0xC5, 0x94, 0x9E, 0x10, 0x29, 0x97, 0x47, 0x05, 0x3D, 0x03, 0x6F, 0x69, 0xAE,
0x84, 0x08, 0x9B, 0x33, 0x0C, 0x1F, 0x26, 0x65, 0xC7, 0x86, 0x25, 0x10, 0x11,
0x97, 0x33, 0x3D, 0x98, 0x43, 0xB5, 0x7F, 0x9C, 0x19, 0x62, 0xE5, 0x46, 0x6D,
0x3B, 0xA2, 0xDC, 0xD4, 0x17, 0x85, 0x9A, 0xE8, 0x2C, 0xF3, 0x01, 0x5F, 0x39,
0xD1, 0xBC, 0x07, 0x8E, 0xAC, 0xC9, 0x28, 0x0C, 0x7B, 0xD8, 0x02, 0xFE, 0x46,
0x12, 0xA8, 0xBD, 0x0E, 0x6B, 0x23, 0x65, 0x5B, 0xAA, 0xFC, 0x32, 0x20, 0xF7,
0xCC, 0xC7, 0x06, 0x80, 0x09, 0x0A, 0x95, 0xD9, 0x69, 0xED, 0x3C, 0x6C, 0xEB,
0x62, 0x28, 0xE6, 0x4E, 0xF4, 0xFA, 0x9B, 0x5C, 0x36, 0x07, 0xE0, 0x25, 0x20,
0xB8, 0xF4, 0x1F, 0x2E, 0x78, 0x21, 0xEE, 0xFA, 0x9E, 0x80, 0x14, 0xAD, 0xAD,
0x83, 0x39, 0x2E, 0xD0, 0xE9, 0x56, 0xE3, 0x88, 0x0C, 0xC4, 0xD7, 0xBE, 0xB1,
0xE4, 0xD0, 0x42, 0xE6, 0xED, 0xDC, 0x44, 0x65, 0x51, 0x1F, 0x95, 0x9A, 0xAA,
0xBF, 0x83, 0x7B, 0xD7, 0x14, 0x23, 0x18, 0x81, 0x91, 0x0A, 0x07, 0x97, 0x10,
0x6F, 0x3C, 0x16, 0xF2, 0xF0, 0x3E, 0xE1, 0x45, 0x40, 0xB0, 0x39, 0x98, 0x33,
0x55, 0xFF, 0x7E, 0x75, 0x31, 0xE0, 0x10, 0x16, 0x81, 0x36, 0x56, 0x86, 0x34,
0x1C, 0x61, 0x10, 0x25, 0xAE, 0x98, 0x6E, 0xBE, 0xC9, 0x47, 0xCD, 0x14, 0x1C,
0x52, 0x8C, 0x27, 0xEE, 0x28, 0xDA, 0x18, 0x96, 0x4D, 0x16, 0x6D, 0x17, 0x2E,
0x5B, 0x7E, 0x88, 0x70, 0xC8, 0x3D, 0x31, 0x34, 0xE5, 0xEA, 0x08, 0x40, 0x25,
0x7B, 0x03, 0x75, 0x47, 0xAD, 0x19, 0x02, 0x7E, 0xCC, 0xB6, 0x43, 0xD1, 0xC9,
0xB2, 0x95, 0x7F, 0x9F, 0x93, 0xC4, 0xD7, 0x33, 0x5A, 0x7E, 0xA4, 0x51, 0x58,
0xC5, 0xA7, 0x23, 0x25, 0xF8, 0xF4, 0xDE, 0xEF, 0x84, 0x72, 0x0E, 0x8D, 0xE7,
0x9E, 0x1E, 0x40, 0xB3, 0xA6, 0x58, 0x34, 0x4E, 0xB8, 0x56, 0x6B, 0xA1, 0x50,
0x2B, 0x1C, 0xF9, 0xA6, 0x88, 0x21, 0x34, 0x79, 0x99, 0x5F, 0x24, 0xD6, 0x96,
0x67, 0xB5, 0x7E, 0x9C, 0xD2, 0xFB, 0x11, 0x40, 0xA6, 0xE6, 0x20, 0xD2, 0x8C,
0x38, 0x62, 0x9B, 0xC1, 0xD7, 0x57, 0x42, 0xE0, 0xD7, 0x34, 0xF3, 0x90, 0xF9,
0x60, 0xDD, 0xEA, 0x24, 0x67, 0x6A, 0xC0, 0xC7, 0xEF, 0xA7, 0x1B, 0xDC, 0xAD,
0x3D, 0x0D, 0x17, 0x90, 0x66, 0x70, 0xB2, 0x98, 0x24, 0x1B, 0x58, 0x79, 0xAC,
0x3E, 0x61, 0x9C, 0x67, 0xB4, 0xEE, 0x09, 0x06, 0x20, 0xCE, 0x39, 0x03, 0x57,
0xD4, 0xB5, 0x44, 0x3C, 0x35, 0x80, 0xDD, 0xEF, 0xC3, 0xC5, 0xC4, 0x93, 0x79,
0xF8, 0x84, 0x60, 0x31, 0x27, 0xB7, 0xF8, 0xEB, 0x63, 0xE8, 0x75, 0x74, 0x31,
0x29, 0xF4, 0xE7, 0x06, 0x51, 0x74, 0x72, 0x71, 0x9D, 0xA1, 0x3F, 0x3C, 0x73,
0xCF, 0x07, 0xA9, 0x98, 0x23, 0x1F, 0x62, 0x9C, 0x9E, 0x27, 0xFD, 0x1E, 0xC8,
0x1C, 0xB9, 0xBD, 0x16, 0xB5, 0x4C, 0x1A, 0xC2, 0x8D, 0xCF, 0x4D, 0xB8, 0xC2,
0x4D, 0x94, 0xE6, 0x12, 0x6D, 0x14, 0xFA, 0x2B, 0xF4, 0x4A, 0x2B, 0xD9, 0x7D,
0xEF, 0xF8, 0x81, 0x2C, 0xF7, 0x7B, 0x98, 0x44, 0x12, 0x58, 0xD5, 0x82, 0xAA,
0xED, 0x49, 0x40, 0x87, 0xBA, 0x11, 0x29, 0x7E, 0xFD, 0x04, 0x67, 0x20, 0x5D,
0x2B, 0x79, 0x42, 0x07, 0x03, 0x5C, 0x36, 0xD7, 0xBE, 0x72, 0xCA, 0x13, 0xCF,
0x93, 0x2D, 0xD8, 0xA9, 0xEE, 0x06, 0x0B, 0xCF, 0x5A, 0x46, 0x88, 0x57, 0x9E,
0x18, 0x92, 0x3B, 0x5F, 0x2F, 0x86, 0xCD, 0x3D, 0x49, 0xF6, 0xA3, 0x05, 0xE6,
0xE4, 0x68, 0xA4, 0x79, 0xA6, 0xEE, 0x85, 0xF4, 0x2B, 0xF6, 0x6E, 0x1B, 0x7A,
0xBD, 0x77, 0xEA, 0x6A, 0xC9, 0x31, 0x34, 0x8E, 0x5F, 0xC2, 0xF3, 0x87, 0x3D,
0x8F, 0xD7, 0xB0, 0x16, 0x28, 0x3F, 0x2C, 0x87, 0xA0, 0xA3, 0x56, 0xE8, 0x21,
0x83, 0x53, 0xCB, 0xE9, 0x1D, 0x28, 0x57, 0x93, 0xDB, 0x5B, 0xE9, 0xF0, 0x7B,
0x7F, 0xF4, 0x6A, 0x51, 0x48, 0xFC, 0xAB, 0xF5, 0x3B, 0x44, 0xA7, 0x5E, 0x67,
0x3A, 0x6B, 0x43, 0x9C, 0xD1, 0x03, 0xDF, 0xF8, 0xD5, 0x7F, 0x7B, 0x09, 0x62,
0xBF, 0x28, 0xBD, 0xC6, 0x3E, 0xC3, 0x6C, 0x91, 0x01, 0x45, 0x3F, 0xE2, 0x1F,
0xEF, 0x2A, 0x8F, 0xB2, 0x1B, 0x72, 0x35, 0x4D, 0x18, 0x6F, 0x4D, 0x57, 0xBF,
0x6A, 0x69, 0x02, 0x69, 0x4A, 0xE5, 0x5F, 0x74, 0xF7, 0x69, 0x5B, 0x89, 0x08,
0xCE, 0xCE, 0x15, 0x56, 0x3F, 0x21, 0x1A, 0xB8, 0xEC, 0x4D, 0xB0, 0x7E, 0x0F,
0x89, 0xB0, 0x5C, 0x6D, 0xDB, 0x53, 0x9E, 0xA9, 0x27, 0x28, 0x52, 0xE5, 0x9E,
0x1F, 0xEF, 0x84, 0x1A, 0x9A, 0xAE, 0x86, 0x8B, 0x25, 0x3B, 0xC6, 0x3B, 0x8E,
0x9C, 0x32, 0xD9, 0x89, 0x3B, 0xA2, 0xCB, 0x59, 0x35, 0xC3, 0x71, 0xEE, 0x22,
0x0C, 0x61, 0xEA, 0x59, 0x33, 0x25, 0x39, 0xAF, 0xF0, 0x12, 0x81, 0x55, 0x4A,
0x9D, 0x0C, 0x3E, 0x5E, 0x34, 0x9F, 0xA7, 0xD8, 0xC5, 0xB5, 0x0A, 0xC3, 0xA2,
0x00, 0x3F, 0x59, 0x3D, 0x07, 0x5F, 0x2B, 0xC1, 0x6F, 0x6A, 0xE3, 0x94, 0x90,
0xAF, 0x81, 0x11, 0x82, 0x89, 0xF4, 0x9D, 0x8B, 0x05, 0xE2, 0x7C, 0x22, 0x02,
0xEC, 0x00, 0x38, 0x39, 0xED, 0x04, 0xB2, 0xC9, 0xD8, 0xA1, 0x1B, 0xED, 0xB9,
0xE1, 0x62, 0x82, 0xC4, 0xCC, 0xA0, 0x61, 0xEE, 0x7A, 0x17, 0xA0, 0x99, 0xAC,
0xAC, 0x85, 0xA7, 0x5F, 0xC9, 0xC3, 0xC5, 0x63, 0x8F, 0x5A, 0xE7, 0x41, 0xAC,
0xB7, 0x89, 0x13, 0x38, 0xD8, 0x58, 0xBF, 0x71, 0xA5, 0x4F, 0x9D, 0x4C, 0x72,
0x57, 0x88, 0x2E, 0xAB, 0xD4, 0x74, 0xDE, 0x46, 0x9F, 0xF4, 0xBA, 0xB1, 0x55,
0x6A, 0x18, 0xF4, 0x87, 0xB9, 0x24, 0xA7, 0xD9, 0xF4, 0x9A, 0x3C, 0xEF, 0xF4,
0xA2, 0x2D, 0x0F, 0xC9, 0xE4, 0x45, 0xC2, 0xC9, 0x6F, 0x2D, 0xB6, 0xDA, 0xE6,
0x89, 0x38, 0x80, 0x2A, 0x89, 0xE2, 0xF5, 0x3D, 0x77, 0x5E, 0x61, 0x6E, 0x9C,
0xF9, 0x87, 0x89, 0xD4, 0x70, 0x23, 0x79, 0x93, 0xDA, 0xCE, 0x62, 0x89, 0xEB,
0x13, 0x77, 0xB0, 0x49, 0xB2, 0xF9, 0xFC, 0x84, 0xD3, 0x06, 0xD2, 0x8D, 0x5A,
0x94, 0x64, 0xC1, 0xA8, 0x9A, 0x60, 0x57, 0x8A, 0x8F, 0x62, 0x4A, 0x78, 0x12,
0x6B, 0x87, 0x6F, 0x6D, 0xC8, 0x32, 0xF3, 0xC6, 0x8D, 0xDB, 0x3A, 0x67, 0x95,
0xCD, 0xAF, 0x48, 0x28, 0x79, 0xC2, 0xB6, 0xDB, 0xD8, 0xFE, 0x82, 0x15, 0xE6,
0xE4, 0xEC, 0x79, 0xE2, 0xB4, 0x21, 0x5C, 0x30, 0x45, 0xD7, 0x3B, 0xA0, 0x1A,
0x3B, 0xAA, 0x3D, 0x6C, 0x1C, 0xC3, 0x1E, 0xDE, 0x4D, 0x75, 0x1D, 0x9A, 0x96,
0x51, 0xF9, 0x4F, 0x10, 0x28, 0x7E, 0x88, 0xEE, 0x3B, 0x93, 0x4A, 0x0B, 0x09,
0x44, 0x9C, 0x20, 0x34, 0xF6, 0xEE, 0x6F, 0x26, 0xB9, 0x4C, 0x76, 0xCC, 0xE1,
0x6F, 0x09, 0x91, 0xAF, 0x48, 0x8C, 0xC4, 0x31, 0xA2, 0xF9, 0x44, 0x77, 0x19,
0xA7, 0x00, 0x33, 0x77, 0x31, 0xF2, 0xF5, 0xF7, 0x30, 0xDF, 0xAB, 0xFE, 0x7E,
0xE6, 0x83, 0xE1, 0xC9, 0x2A, 0xC8, 0xE0, 0xA6, 0xAC, 0x5A, 0x28, 0x7F, 0xC4,
0x0B, 0xEB, 0x55, 0xD9, 0x5D, 0xBD, 0xB5, 0xD2, 0xF6, 0xB4, 0xA9, 0x76, 0x2B,
0x35, 0x10, 0x36, 0x3B, 0xCC, 0x61, 0x6C, 0x79, 0xCE, 0xC3, 0x9A, 0x02, 0x9A,
0x00, 0xBA, 0x43, 0x20, 0x3F, 0x26, 0x36, 0x66, 0x07, 0x11, 0x68, 0x51, 0x47,
0xBE, 0x78, 0xED, 0x4A, 0xFA, 0xBC, 0xDA, 0xCD, 0xFD, 0x02, 0xDB, 0xD1, 0x8B,
0xE0, 0xBD, 0x13, 0xFE, 0xED, 0x26, 0x77, 0xE4, 0x83, 0xAE, 0xB7, 0xAB, 0xFD,
0x2A, 0x5E, 0xA3, 0x28, 0xFD, 0x90, 0x40, 0x3D, 0x34, 0xF7, 0xF8, 0x35, 0x80,
0xF6, 0x6F, 0xA0, 0xE9, 0xCD, 0x9A, 0x54, 0x6F, 0x41, 0xA5, 0xC7, 0xED, 0xEA,
0xDC, 0x52, 0x23, 0xF1, 0x96, 0x19, 0x8E, 0x2B, 0x94, 0x3F, 0xD9, 0x27, 0x60,
0x1E, 0x27, 0xC1, 0x39, 0x68, 0x78, 0x7B, 0x47, 0x8F, 0xCC, 0xCD, 0xBE, 0xE4,
0xBD, 0x0B, 0x73, 0x03, 0xFB, 0xFE, 0xC0, 0x50, 0x38, 0x70, 0xDF, 0x81, 0x5D,
0x22, 0x4C, 0x5B, 0xCB, 0x27, 0x5D, 0xD2, 0x94, 0x64, 0x0A, 0x88, 0x67, 0x31,
0xE9, 0x08, 0xF0, 0x88, 0x20, 0xF2, 0x86, 0xCA, 0xBD, 0x18, 0x5F, 0x34, 0xD0,
0x96, 0x0D, 0x4A, 0x62, 0x4D, 0xBE, 0xE8, 0xA6, 0x04, 0xA6, 0x69, 0xCE, 0xCD,
0xE9, 0x5A, 0x1D, 0xD2, 0xF8, 0xCF, 0x19, 0x06, 0x17, 0x05, 0x82, 0x6B, 0x60,
0x3E, 0x5E, 0x6B, 0x1D, 0x1E, 0x13, 0x51, 0x5D, 0xFE, 0x95, 0x38, 0x33, 0x62,
0x9B, 0xBF, 0xD5, 0x3E, 0x3B, 0x8B, 0xD2, 0x6F, 0x24, 0x6D, 0x24, 0xC9, 0x0D,
0x2D, 0x52, 0xBF, 0xDA, 0xCE, 0x5E, 0xFE, 0x9D, 0xB8, 0x5D, 0x61, 0x57, 0xBC,
0x8C, 0x7A, 0x17, 0x75, 0x80, 0xEE, 0x52, 0x2F, 0xF5, 0x25, 0x48, 0x3A, 0x9E,
0x27, 0xF4, 0xEB, 0xE1, 0x01, 0xE4, 0xA7, 0x48, 0x93, 0xAA, 0x92, 0x68, 0xC0,
0x3B, 0x1A, 0x5A, 0xC5, 0x6D, 0xD0, 0x91, 0xB9, 0x8D, 0x44, 0xD4, 0xE1, 0x9C,
0x74, 0xEA, 0x14, 0xFA, 0xF6, 0x1E, 0x01, 0xC0, 0x89, 0x24, 0x90, 0x71, 0xAF,
0xF5, 0x2D, 0x6C, 0x35, 0x13, 0xA6, 0x73, 0x14, 0xAC, 0xE5, 0xAE, 0x88, 0x2F,
0x9D, 0x77, 0x3B, 0x8F, 0x61, 0xB1, 0x47, 0x66, 0x72, 0x14, 0x91, 0x40, 0xD7,
0x50, 0xDC, 0xEA, 0xFF, 0x49, 0x9E, 0x17, 0x75, 0x25, 0x49, 0x7C, 0x57, 0x41,
0xA7, 0x8C, 0x4D, 0x3B, 0x94, 0x9D, 0x65, 0x83, 0x62, 0x6F, 0x16, 0xBF, 0x0C,
0x87, 0x03, 0x61, 0xB4, 0x3B, 0x60, 0x6D, 0x07, 0x56, 0xB8, 0x1F, 0x89, 0xAD,
0x00, 0x25, 0x10, 0x4A, 0x34, 0x4C, 0x9A, 0x26, 0xDA, 0x06, 0x25, 0x9C, 0x91,
0xA6, 0xA5, 0xAD, 0x4D, 0x6E, 0xE9, 0x2F, 0x18, 0xC4, 0x1D, 0x09, 0xE1, 0xAA,
0x66, 0x01, 0x31, 0x6D, 0x12, 0x30, 0xED, 0x97, 0x3F, 0x67, 0xCE, 0x4E, 0x26,
0x0B, 0xF5, 0x5E, 0x81, 0xA7, 0x1F, 0x83, 0x68, 0x91, 0xC3, 0xD0, 0x4C, 0x2E,
0xD4, 0xDE, 0xEF, 0x34, 0xF9, 0x61, 0x83, 0x6F, 0xD6, 0x6E, 0x40, 0x87, 0x48,
0x7E, 0xCF, 0x56, 0x42, 0x21, 0xBA, 0x40, 0x64, 0x17, 0xFA, 0x97, 0xFF, 0x8D,
0xC8, 0x32, 0xFA, 0xB7, 0x45, 0xB0, 0xEC, 0xBD, 0x0E, 0x51, 0x63, 0x90, 0x05,
0x68, 0x7A, 0x45, 0x86, 0x68, 0x2A, 0x0E, 0x81, 0x5F, 0xDD, 0x12, 0xAD, 0x48,
0xF6, 0x87, 0x2E, 0x8D, 0xF6, 0x86, 0xC3, 0x6D, 0x69, 0xD5, 0x4E, 0x52, 0x8A,
0x8E, 0xE8, 0x01, 0x56, 0x11, 0xCC, 0x2E, 0x3F, 0xB5, 0x46, 0x1D, 0xF6, 0x6E,
0x4A, 0xEE, 0x1C, 0x60, 0x15, 0x85, 0xF6, 0x40, 0xFD, 0x56, 0xDC, 0x10, 0x01,
0xC3, 0xBD, 0xAE, 0x5A, 0x13, 0x1F, 0x15, 0x16, 0x10, 0x92, 0xC5, 0x02, 0xC2,
0x81, 0xB5, 0x6A, 0x4D, 0x37, 0x29, 0x40, 0x8B, 0xAA, 0x5F, 0xC9, 0x4C, 0x26,
0x7B, 0x2C, 0x21, 0x9E, 0xE2, 0xF2, 0x5A, 0x20, 0x88, 0x3F, 0x40, 0x30, 0xC5,
0x64, 0x0E};

// mldsa65kPublicKeySPKI is the above example ML-DSA-65 public key encoded
static const uint8_t mldsa65kPublicKeySPKI[] = {
0x30, 0x82, 0x07, 0xB2, 0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
0x03, 0x04, 0x03, 0x12, 0x03, 0x82, 0x07, 0xA1, 0x00, 0x9B, 0x77, 0xAB, 0x96,
0x9D, 0x65, 0xA2, 0xC1, 0x55, 0x65, 0x02, 0x9B, 0xA5, 0xD4, 0xE5, 0x93, 0xA1,
0xAC, 0xE7, 0x3E, 0x8C, 0x61, 0xB7, 0xCB, 0xA1, 0x3E, 0x74, 0x8A, 0xC9, 0xC0,
0xA0, 0x63, 0x4A, 0xF6, 0xF4, 0x1C, 0x72, 0x37, 0xB0, 0x31, 0x9E, 0xB7, 0x51,
0x55, 0xCF, 0x5B, 0x4E, 0x03, 0x46, 0x7C, 0x26, 0xBE, 0x84, 0x73, 0xD8, 0x50,
0xDF, 0x72, 0x87, 0xC0, 0x18, 0xED, 0xE7, 0xE4, 0x12, 0x4F, 0xCA, 0x4E, 0x1A,
0xFA, 0x76, 0x82, 0xD4, 0xA6, 0x3E, 0xDA, 0xEC, 0x74, 0x53, 0xFF, 0xDD, 0x69,
0x5C, 0x9F, 0xFD, 0x69, 0xA3, 0xED, 0x4F, 0xEB, 0xFB, 0xEF, 0xD2, 0x98, 0x8B,
0x45, 0x06, 0xBA, 0xD5, 0xF8, 0x9E, 0x0A, 0x2D, 0xA2, 0xC7, 0x96, 0x4B, 0x79,
0xE9, 0xA9, 0xA6, 0x73, 0x69, 0xF8, 0x8C, 0x01, 0x69, 0xF2, 0x66, 0x05, 0x37,
0x31, 0x65, 0xA9, 0x09, 0x3E, 0x0E, 0x73, 0x95, 0x67, 0xC9, 0x33, 0xA6, 0x57,
0xDF, 0xDD, 0xC0, 0x55, 0x1A, 0x89, 0x6F, 0xC8, 0x30, 0x71, 0x68, 0x3C, 0x2A,
0x7E, 0x61, 0x86, 0xAC, 0x70, 0x6A, 0x27, 0x31, 0x9B, 0x9A, 0xEC, 0x8F, 0x37,
0x2B, 0x71, 0x91, 0x91, 0x6C, 0x8B, 0x35, 0xED, 0xF1, 0x97, 0x87, 0x58, 0xD1,
0x4F, 0xF2, 0x06, 0x23, 0xE6, 0x1C, 0x44, 0x63, 0x02, 0x9E, 0x09, 0x76, 0x6C,
0x72, 0xBD, 0x0D, 0xB3, 0xE2, 0x1D, 0x92, 0xAA, 0x8D, 0x7B, 0x78, 0xD8, 0xB3,
0xA7, 0x5A, 0xAB, 0xBF, 0x22, 0xBB, 0x30, 0x5B, 0xFB, 0xB4, 0x3C, 0x52, 0xD2,
0xA2, 0xED, 0x3B, 0x99, 0x43, 0xCB, 0x29, 0x66, 0x2A, 0xBD, 0x52, 0x1B, 0x1C,
0xB4, 0xE5, 0xE3, 0x6E, 0xFF, 0xAD, 0xEF, 0x8B, 0xE1, 0xF9, 0xB5, 0x5E, 0xCB,
0xF2, 0x8E, 0xCD, 0x53, 0x39, 0xBE, 0xBE, 0x61, 0x72, 0x86, 0x31, 0x65, 0xA0,
0xFC, 0xC1, 0xFC, 0x31, 0x79, 0x93, 0xDF, 0x76, 0x13, 0x71, 0xE4, 0x61, 0x0F,
0x6B, 0x32, 0x78, 0xD2, 0x24, 0xB7, 0x8C, 0xE8, 0x84, 0xE3, 0xB8, 0xF6, 0x04,
0xF3, 0x30, 0xE9, 0x5B, 0xA5, 0xD8, 0x94, 0xA7, 0xA3, 0xF0, 0xE8, 0xAC, 0x70,
0x32, 0x42, 0xB5, 0x08, 0xEE, 0x2A, 0x77, 0xFA, 0x04, 0x49, 0xE9, 0x7A, 0xB7,
0x0A, 0x95, 0x05, 0x86, 0x33, 0xA5, 0xE4, 0x5A, 0xC6, 0xE1, 0xE7, 0x48, 0xBD,
0xBA, 0x80, 0xE7, 0x21, 0x61, 0x45, 0x24, 0x5E, 0xA9, 0x7F, 0x2D, 0x75, 0x0F,
0xE9, 0xEE, 0x79, 0x88, 0x64, 0xF3, 0xE7, 0x0C, 0xA0, 0xEB, 0x93, 0x2C, 0x6B,
0xD3, 0x51, 0x12, 0xE7, 0x62, 0x8D, 0x71, 0x10, 0x6D, 0x5B, 0x3A, 0x27, 0xF4,
0xEA, 0x80, 0xFC, 0xCD, 0x58, 0x81, 0x43, 0xEB, 0xA0, 0x4E, 0xF5, 0xA1, 0x68,
0x67, 0x74, 0x7C, 0x14, 0x12, 0xA6, 0x78, 0xC2, 0x08, 0x58, 0x3F, 0x20, 0x96,
0x52, 0xD2, 0x61, 0xDA, 0xED, 0x5F, 0x7F, 0xAD, 0x40, 0x93, 0x21, 0xEB, 0xC4,
0x37, 0x5C, 0xD1, 0x72, 0xE6, 0x06, 0x37, 0xD9, 0xF6, 0x09, 0xD4, 0xC9, 0x6D,
0xED, 0x07, 0xF6, 0xD2, 0x15, 0x94, 0xFD, 0xF6, 0xC3, 0x09, 0x60, 0x6D, 0x6A,
0x23, 0x50, 0x8C, 0xDD, 0x61, 0xDD, 0x66, 0x81, 0xB0, 0xAC, 0x7C, 0xE7, 0x7F,
0xED, 0x3C, 0x2F, 0x19, 0xB5, 0xF9, 0xB7, 0x2E, 0x35, 0xF7, 0xF4, 0x98, 0x0E,
0x6A, 0x9E, 0x6D, 0xAC, 0xF1, 0x0F, 0x90, 0x25, 0xED, 0xC5, 0x94, 0x9E, 0x10,
0x29, 0x97, 0x47, 0x05, 0x3D, 0x03, 0x6F, 0x69, 0xAE, 0x84, 0x08, 0x9B, 0x33,
0x0C, 0x1F, 0x26, 0x65, 0xC7, 0x86, 0x25, 0x10, 0x11, 0x97, 0x33, 0x3D, 0x98,
0x43, 0xB5, 0x7F, 0x9C, 0x19, 0x62, 0xE5, 0x46, 0x6D, 0x3B, 0xA2, 0xDC, 0xD4,
0x17, 0x85, 0x9A, 0xE8, 0x2C, 0xF3, 0x01, 0x5F, 0x39, 0xD1, 0xBC, 0x07, 0x8E,
0xAC, 0xC9, 0x28, 0x0C, 0x7B, 0xD8, 0x02, 0xFE, 0x46, 0x12, 0xA8, 0xBD, 0x0E,
0x6B, 0x23, 0x65, 0x5B, 0xAA, 0xFC, 0x32, 0x20, 0xF7, 0xCC, 0xC7, 0x06, 0x80,
0x09, 0x0A, 0x95, 0xD9, 0x69, 0xED, 0x3C, 0x6C, 0xEB, 0x62, 0x28, 0xE6, 0x4E,
0xF4, 0xFA, 0x9B, 0x5C, 0x36, 0x07, 0xE0, 0x25, 0x20, 0xB8, 0xF4, 0x1F, 0x2E,
0x78, 0x21, 0xEE, 0xFA, 0x9E, 0x80, 0x14, 0xAD, 0xAD, 0x83, 0x39, 0x2E, 0xD0,
0xE9, 0x56, 0xE3, 0x88, 0x0C, 0xC4, 0xD7, 0xBE, 0xB1, 0xE4, 0xD0, 0x42, 0xE6,
0xED, 0xDC, 0x44, 0x65, 0x51, 0x1F, 0x95, 0x9A, 0xAA, 0xBF, 0x83, 0x7B, 0xD7,
0x14, 0x23, 0x18, 0x81, 0x91, 0x0A, 0x07, 0x97, 0x10, 0x6F, 0x3C, 0x16, 0xF2,
0xF0, 0x3E, 0xE1, 0x45, 0x40, 0xB0, 0x39, 0x98, 0x33, 0x55, 0xFF, 0x7E, 0x75,
0x31, 0xE0, 0x10, 0x16, 0x81, 0x36, 0x56, 0x86, 0x34, 0x1C, 0x61, 0x10, 0x25,
0xAE, 0x98, 0x6E, 0xBE, 0xC9, 0x47, 0xCD, 0x14, 0x1C, 0x52, 0x8C, 0x27, 0xEE,
0x28, 0xDA, 0x18, 0x96, 0x4D, 0x16, 0x6D, 0x17, 0x2E, 0x5B, 0x7E, 0x88, 0x70,
0xC8, 0x3D, 0x31, 0x34, 0xE5, 0xEA, 0x08, 0x40, 0x25, 0x7B, 0x03, 0x75, 0x47,
0xAD, 0x19, 0x02, 0x7E, 0xCC, 0xB6, 0x43, 0xD1, 0xC9, 0xB2, 0x95, 0x7F, 0x9F,
0x93, 0xC4, 0xD7, 0x33, 0x5A, 0x7E, 0xA4, 0x51, 0x58, 0xC5, 0xA7, 0x23, 0x25,
0xF8, 0xF4, 0xDE, 0xEF, 0x84, 0x72, 0x0E, 0x8D, 0xE7, 0x9E, 0x1E, 0x40, 0xB3,
0xA6, 0x58, 0x34, 0x4E, 0xB8, 0x56, 0x6B, 0xA1, 0x50, 0x2B, 0x1C, 0xF9, 0xA6,
0x88, 0x21, 0x34, 0x79, 0x99, 0x5F, 0x24, 0xD6, 0x96, 0x67, 0xB5, 0x7E, 0x9C,
0xD2, 0xFB, 0x11, 0x40, 0xA6, 0xE6, 0x20, 0xD2, 0x8C, 0x38, 0x62, 0x9B, 0xC1,
0xD7, 0x57, 0x42, 0xE0, 0xD7, 0x34, 0xF3, 0x90, 0xF9, 0x60, 0xDD, 0xEA, 0x24,
0x67, 0x6A, 0xC0, 0xC7, 0xEF, 0xA7, 0x1B, 0xDC, 0xAD, 0x3D, 0x0D, 0x17, 0x90,
0x66, 0x70, 0xB2, 0x98, 0x24, 0x1B, 0x58, 0x79, 0xAC, 0x3E, 0x61, 0x9C, 0x67,
0xB4, 0xEE, 0x09, 0x06, 0x20, 0xCE, 0x39, 0x03, 0x57, 0xD4, 0xB5, 0x44, 0x3C,
0x35, 0x80, 0xDD, 0xEF, 0xC3, 0xC5, 0xC4, 0x93, 0x79, 0xF8, 0x84, 0x60, 0x31,
0x27, 0xB7, 0xF8, 0xEB, 0x63, 0xE8, 0x75, 0x74, 0x31, 0x29, 0xF4, 0xE7, 0x06,
0x51, 0x74, 0x72, 0x71, 0x9D, 0xA1, 0x3F, 0x3C, 0x73, 0xCF, 0x07, 0xA9, 0x98,
0x23, 0x1F, 0x62, 0x9C, 0x9E, 0x27, 0xFD, 0x1E, 0xC8, 0x1C, 0xB9, 0xBD, 0x16,
0xB5, 0x4C, 0x1A, 0xC2, 0x8D, 0xCF, 0x4D, 0xB8, 0xC2, 0x4D, 0x94, 0xE6, 0x12,
0x6D, 0x14, 0xFA, 0x2B, 0xF4, 0x4A, 0x2B, 0xD9, 0x7D, 0xEF, 0xF8, 0x81, 0x2C,
0xF7, 0x7B, 0x98, 0x44, 0x12, 0x58, 0xD5, 0x82, 0xAA, 0xED, 0x49, 0x40, 0x87,
0xBA, 0x11, 0x29, 0x7E, 0xFD, 0x04, 0x67, 0x20, 0x5D, 0x2B, 0x79, 0x42, 0x07,
0x03, 0x5C, 0x36, 0xD7, 0xBE, 0x72, 0xCA, 0x13, 0xCF, 0x93, 0x2D, 0xD8, 0xA9,
0xEE, 0x06, 0x0B, 0xCF, 0x5A, 0x46, 0x88, 0x57, 0x9E, 0x18, 0x92, 0x3B, 0x5F,
0x2F, 0x86, 0xCD, 0x3D, 0x49, 0xF6, 0xA3, 0x05, 0xE6, 0xE4, 0x68, 0xA4, 0x79,
0xA6, 0xEE, 0x85, 0xF4, 0x2B, 0xF6, 0x6E, 0x1B, 0x7A, 0xBD, 0x77, 0xEA, 0x6A,
0xC9, 0x31, 0x34, 0x8E, 0x5F, 0xC2, 0xF3, 0x87, 0x3D, 0x8F, 0xD7, 0xB0, 0x16,
0x28, 0x3F, 0x2C, 0x87, 0xA0, 0xA3, 0x56, 0xE8, 0x21, 0x83, 0x53, 0xCB, 0xE9,
0x1D, 0x28, 0x57, 0x93, 0xDB, 0x5B, 0xE9, 0xF0, 0x7B, 0x7F, 0xF4, 0x6A, 0x51,
0x48, 0xFC, 0xAB, 0xF5, 0x3B, 0x44, 0xA7, 0x5E, 0x67, 0x3A, 0x6B, 0x43, 0x9C,
0xD1, 0x03, 0xDF, 0xF8, 0xD5, 0x7F, 0x7B, 0x09, 0x62, 0xBF, 0x28, 0xBD, 0xC6,
0x3E, 0xC3, 0x6C, 0x91, 0x01, 0x45, 0x3F, 0xE2, 0x1F, 0xEF, 0x2A, 0x8F, 0xB2,
0x1B, 0x72, 0x35, 0x4D, 0x18, 0x6F, 0x4D, 0x57, 0xBF, 0x6A, 0x69, 0x02, 0x69,
0x4A, 0xE5, 0x5F, 0x74, 0xF7, 0x69, 0x5B, 0x89, 0x08, 0xCE, 0xCE, 0x15, 0x56,
0x3F, 0x21, 0x1A, 0xB8, 0xEC, 0x4D, 0xB0, 0x7E, 0x0F, 0x89, 0xB0, 0x5C, 0x6D,
0xDB, 0x53, 0x9E, 0xA9, 0x27, 0x28, 0x52, 0xE5, 0x9E, 0x1F, 0xEF, 0x84, 0x1A,
0x9A, 0xAE, 0x86, 0x8B, 0x25, 0x3B, 0xC6, 0x3B, 0x8E, 0x9C, 0x32, 0xD9, 0x89,
0x3B, 0xA2, 0xCB, 0x59, 0x35, 0xC3, 0x71, 0xEE, 0x22, 0x0C, 0x61, 0xEA, 0x59,
0x33, 0x25, 0x39, 0xAF, 0xF0, 0x12, 0x81, 0x55, 0x4A, 0x9D, 0x0C, 0x3E, 0x5E,
0x34, 0x9F, 0xA7, 0xD8, 0xC5, 0xB5, 0x0A, 0xC3, 0xA2, 0x00, 0x3F, 0x59, 0x3D,
0x07, 0x5F, 0x2B, 0xC1, 0x6F, 0x6A, 0xE3, 0x94, 0x90, 0xAF, 0x81, 0x11, 0x82,
0x89, 0xF4, 0x9D, 0x8B, 0x05, 0xE2, 0x7C, 0x22, 0x02, 0xEC, 0x00, 0x38, 0x39,
0xED, 0x04, 0xB2, 0xC9, 0xD8, 0xA1, 0x1B, 0xED, 0xB9, 0xE1, 0x62, 0x82, 0xC4,
0xCC, 0xA0, 0x61, 0xEE, 0x7A, 0x17, 0xA0, 0x99, 0xAC, 0xAC, 0x85, 0xA7, 0x5F,
0xC9, 0xC3, 0xC5, 0x63, 0x8F, 0x5A, 0xE7, 0x41, 0xAC, 0xB7, 0x89, 0x13, 0x38,
0xD8, 0x58, 0xBF, 0x71, 0xA5, 0x4F, 0x9D, 0x4C, 0x72, 0x57, 0x88, 0x2E, 0xAB,
0xD4, 0x74, 0xDE, 0x46, 0x9F, 0xF4, 0xBA, 0xB1, 0x55, 0x6A, 0x18, 0xF4, 0x87,
0xB9, 0x24, 0xA7, 0xD9, 0xF4, 0x9A, 0x3C, 0xEF, 0xF4, 0xA2, 0x2D, 0x0F, 0xC9,
0xE4, 0x45, 0xC2, 0xC9, 0x6F, 0x2D, 0xB6, 0xDA, 0xE6, 0x89, 0x38, 0x80, 0x2A,
0x89, 0xE2, 0xF5, 0x3D, 0x77, 0x5E, 0x61, 0x6E, 0x9C, 0xF9, 0x87, 0x89, 0xD4,
0x70, 0x23, 0x79, 0x93, 0xDA, 0xCE, 0x62, 0x89, 0xEB, 0x13, 0x77, 0xB0, 0x49,
0xB2, 0xF9, 0xFC, 0x84, 0xD3, 0x06, 0xD2, 0x8D, 0x5A, 0x94, 0x64, 0xC1, 0xA8,
0x9A, 0x60, 0x57, 0x8A, 0x8F, 0x62, 0x4A, 0x78, 0x12, 0x6B, 0x87, 0x6F, 0x6D,
0xC8, 0x32, 0xF3, 0xC6, 0x8D, 0xDB, 0x3A, 0x67, 0x95, 0xCD, 0xAF, 0x48, 0x28,
0x79, 0xC2, 0xB6, 0xDB, 0xD8, 0xFE, 0x82, 0x15, 0xE6, 0xE4, 0xEC, 0x79, 0xE2,
0xB4, 0x21, 0x5C, 0x30, 0x45, 0xD7, 0x3B, 0xA0, 0x1A, 0x3B, 0xAA, 0x3D, 0x6C,
0x1C, 0xC3, 0x1E, 0xDE, 0x4D, 0x75, 0x1D, 0x9A, 0x96, 0x51, 0xF9, 0x4F, 0x10,
0x28, 0x7E, 0x88, 0xEE, 0x3B, 0x93, 0x4A, 0x0B, 0x09, 0x44, 0x9C, 0x20, 0x34,
0xF6, 0xEE, 0x6F, 0x26, 0xB9, 0x4C, 0x76, 0xCC, 0xE1, 0x6F, 0x09, 0x91, 0xAF,
0x48, 0x8C, 0xC4, 0x31, 0xA2, 0xF9, 0x44, 0x77, 0x19, 0xA7, 0x00, 0x33, 0x77,
0x31, 0xF2, 0xF5, 0xF7, 0x30, 0xDF, 0xAB, 0xFE, 0x7E, 0xE6, 0x83, 0xE1, 0xC9,
0x2A, 0xC8, 0xE0, 0xA6, 0xAC, 0x5A, 0x28, 0x7F, 0xC4, 0x0B, 0xEB, 0x55, 0xD9,
0x5D, 0xBD, 0xB5, 0xD2, 0xF6, 0xB4, 0xA9, 0x76, 0x2B, 0x35, 0x10, 0x36, 0x3B,
0xCC, 0x61, 0x6C, 0x79, 0xCE, 0xC3, 0x9A, 0x02, 0x9A, 0x00, 0xBA, 0x43, 0x20,
0x3F, 0x26, 0x36, 0x66, 0x07, 0x11, 0x68, 0x51, 0x47, 0xBE, 0x78, 0xED, 0x4A,
0xFA, 0xBC, 0xDA, 0xCD, 0xFD, 0x02, 0xDB, 0xD1, 0x8B, 0xE0, 0xBD, 0x13, 0xFE,
0xED, 0x26, 0x77, 0xE4, 0x83, 0xAE, 0xB7, 0xAB, 0xFD, 0x2A, 0x5E, 0xA3, 0x28,
0xFD, 0x90, 0x40, 0x3D, 0x34, 0xF7, 0xF8, 0x35, 0x80, 0xF6, 0x6F, 0xA0, 0xE9,
0xCD, 0x9A, 0x54, 0x6F, 0x41, 0xA5, 0xC7, 0xED, 0xEA, 0xDC, 0x52, 0x23, 0xF1,
0x96, 0x19, 0x8E, 0x2B, 0x94, 0x3F, 0xD9, 0x27, 0x60, 0x1E, 0x27, 0xC1, 0x39,
0x68, 0x78, 0x7B, 0x47, 0x8F, 0xCC, 0xCD, 0xBE, 0xE4, 0xBD, 0x0B, 0x73, 0x03,
0xFB, 0xFE, 0xC0, 0x50, 0x38, 0x70, 0xDF, 0x81, 0x5D, 0x22, 0x4C, 0x5B, 0xCB,
0x27, 0x5D, 0xD2, 0x94, 0x64, 0x0A, 0x88, 0x67, 0x31, 0xE9, 0x08, 0xF0, 0x88,
0x20, 0xF2, 0x86, 0xCA, 0xBD, 0x18, 0x5F, 0x34, 0xD0, 0x96, 0x0D, 0x4A, 0x62,
0x4D, 0xBE, 0xE8, 0xA6, 0x04, 0xA6, 0x69, 0xCE, 0xCD, 0xE9, 0x5A, 0x1D, 0xD2,
0xF8, 0xCF, 0x19, 0x06, 0x17, 0x05, 0x82, 0x6B, 0x60, 0x3E, 0x5E, 0x6B, 0x1D,
0x1E, 0x13, 0x51, 0x5D, 0xFE, 0x95, 0x38, 0x33, 0x62, 0x9B, 0xBF, 0xD5, 0x3E,
0x3B, 0x8B, 0xD2, 0x6F, 0x24, 0x6D, 0x24, 0xC9, 0x0D, 0x2D, 0x52, 0xBF, 0xDA,
0xCE, 0x5E, 0xFE, 0x9D, 0xB8, 0x5D, 0x61, 0x57, 0xBC, 0x8C, 0x7A, 0x17, 0x75,
0x80, 0xEE, 0x52, 0x2F, 0xF5, 0x25, 0x48, 0x3A, 0x9E, 0x27, 0xF4, 0xEB, 0xE1,
0x01, 0xE4, 0xA7, 0x48, 0x93, 0xAA, 0x92, 0x68, 0xC0, 0x3B, 0x1A, 0x5A, 0xC5,
0x6D, 0xD0, 0x91, 0xB9, 0x8D, 0x44, 0xD4, 0xE1, 0x9C, 0x74, 0xEA, 0x14, 0xFA,
0xF6, 0x1E, 0x01, 0xC0, 0x89, 0x24, 0x90, 0x71, 0xAF, 0xF5, 0x2D, 0x6C, 0x35,
0x13, 0xA6, 0x73, 0x14, 0xAC, 0xE5, 0xAE, 0x88, 0x2F, 0x9D, 0x77, 0x3B, 0x8F,
0x61, 0xB1, 0x47, 0x66, 0x72, 0x14, 0x91, 0x40, 0xD7, 0x50, 0xDC, 0xEA, 0xFF,
0x49, 0x9E, 0x17, 0x75, 0x25, 0x49, 0x7C, 0x57, 0x41, 0xA7, 0x8C, 0x4D, 0x3B,
0x94, 0x9D, 0x65, 0x83, 0x62, 0x6F, 0x16, 0xBF, 0x0C, 0x87, 0x03, 0x61, 0xB4,
0x3B, 0x60, 0x6D, 0x07, 0x56, 0xB8, 0x1F, 0x89, 0xAD, 0x00, 0x25, 0x10, 0x4A,
0x34, 0x4C, 0x9A, 0x26, 0xDA, 0x06, 0x25, 0x9C, 0x91, 0xA6, 0xA5, 0xAD, 0x4D,
0x6E, 0xE9, 0x2F, 0x18, 0xC4, 0x1D, 0x09, 0xE1, 0xAA, 0x66, 0x01, 0x31, 0x6D,
0x12, 0x30, 0xED, 0x97, 0x3F, 0x67, 0xCE, 0x4E, 0x26, 0x0B, 0xF5, 0x5E, 0x81,
0xA7, 0x1F, 0x83, 0x68, 0x91, 0xC3, 0xD0, 0x4C, 0x2E, 0xD4, 0xDE, 0xEF, 0x34,
0xF9, 0x61, 0x83, 0x6F, 0xD6, 0x6E, 0x40, 0x87, 0x48, 0x7E, 0xCF, 0x56, 0x42,
0x21, 0xBA, 0x40, 0x64, 0x17, 0xFA, 0x97, 0xFF, 0x8D, 0xC8, 0x32, 0xFA, 0xB7,
0x45, 0xB0, 0xEC, 0xBD, 0x0E, 0x51, 0x63, 0x90, 0x05, 0x68, 0x7A, 0x45, 0x86,
0x68, 0x2A, 0x0E, 0x81, 0x5F, 0xDD, 0x12, 0xAD, 0x48, 0xF6, 0x87, 0x2E, 0x8D,
0xF6, 0x86, 0xC3, 0x6D, 0x69, 0xD5, 0x4E, 0x52, 0x8A, 0x8E, 0xE8, 0x01, 0x56,
0x11, 0xCC, 0x2E, 0x3F, 0xB5, 0x46, 0x1D, 0xF6, 0x6E, 0x4A, 0xEE, 0x1C, 0x60,
0x15, 0x85, 0xF6, 0x40, 0xFD, 0x56, 0xDC, 0x10, 0x01, 0xC3, 0xBD, 0xAE, 0x5A,
0x13, 0x1F, 0x15, 0x16, 0x10, 0x92, 0xC5, 0x02, 0xC2, 0x81, 0xB5, 0x6A, 0x4D,
0x37, 0x29, 0x40, 0x8B, 0xAA, 0x5F, 0xC9, 0x4C, 0x26, 0x7B, 0x2C, 0x21, 0x9E,
0xE2, 0xF2, 0x5A, 0x20, 0x88, 0x3F, 0x40, 0x30, 0xC5, 0x64, 0x0E };

// mldsa87kPublicKey is an example ML-DSA-87 public key
static const uint8_t mldsa87kPublicKey[] = {
0xE4, 0x36, 0x63, 0x53, 0xA7, 0xE7, 0xDF, 0x51, 0x06, 0x19, 0x34, 0x9F, 0xB5,
0x95, 0x53, 0x9D, 0xC0, 0x59, 0x21, 0x38, 0x0F, 0x8E, 0x2A, 0xEC, 0x43, 0x5C,
0x9B, 0x4B, 0xD0, 0xDC, 0x7E, 0xE1, 0x89, 0x77, 0x51, 0xD4, 0x26, 0x46, 0x8F,
0x25, 0x76, 0xAB, 0x5E, 0x68, 0xFE, 0x45, 0xC6, 0x35, 0xF5, 0xF0, 0xD0, 0x2D,
0xD2, 0x11, 0xCB, 0x2D, 0x3B, 0x6B, 0xF3, 0x2F, 0x68, 0xD1, 0xF2, 0xCC, 0x51,
0x9E, 0xE0, 0xC5, 0x1D, 0xFA, 0x2C, 0x55, 0x02, 0xE5, 0xAB, 0xC6, 0xA2, 0xA9,
0x2C, 0x35, 0xC1, 0x22, 0xDC, 0xFB, 0x9D, 0xDC, 0x9E, 0x17, 0xCB, 0x7C, 0xEC,
0xB4, 0x7D, 0x1C, 0x40, 0xA6, 0x40, 0x3C, 0x2B, 0x1C, 0x5B, 0x85, 0x97, 0x31,
0x5D, 0x9E, 0xAD, 0x7C, 0xC9, 0xF1, 0xBC, 0x99, 0x59, 0x2B, 0xE0, 0x10, 0x30,
0x58, 0xC6, 0x63, 0xBD, 0xD7, 0xF1, 0x27, 0x2B, 0x1E, 0xB2, 0xA8, 0x31, 0xD7,
0xD3, 0x2B, 0x85, 0xA7, 0x59, 0xAF, 0x70, 0x15, 0x66, 0x9E, 0xD2, 0x13, 0xB0,
0x50, 0xBF, 0x59, 0x08, 0x92, 0x32, 0x07, 0x9C, 0x81, 0xD7, 0x06, 0x55, 0x76,
0xEE, 0x15, 0x8A, 0xFE, 0xCB, 0x62, 0x58, 0xF7, 0xDF, 0x0F, 0xEB, 0x0A, 0x11,
0x98, 0xF8, 0x93, 0xD8, 0x96, 0xF5, 0x14, 0x87, 0x40, 0x4F, 0xEC, 0x9A, 0x45,
0xE2, 0x7A, 0x54, 0x91, 0x0B, 0xDB, 0x39, 0x90, 0x48, 0x5D, 0x1B, 0xE6, 0x63,
0x2C, 0x47, 0xC2, 0x2C, 0x45, 0x91, 0xDA, 0x52, 0x65, 0x15, 0x54, 0x35, 0x1A,
0xFF, 0x3E, 0xC9, 0x64, 0xED, 0x48, 0xE6, 0x7C, 0xDB, 0x2C, 0x72, 0x7B, 0x14,
0xC0, 0x35, 0x5C, 0x14, 0xE8, 0xBB, 0x92, 0xEA, 0xB6, 0x29, 0x29, 0x8B, 0x8A,
0x4D, 0x95, 0x1F, 0xAE, 0x54, 0x64, 0x07, 0x2D, 0xAD, 0x3D, 0xA4, 0x20, 0x20,
0xA0, 0x7A, 0x7C, 0xAE, 0x9E, 0xFE, 0x5C, 0xE8, 0x88, 0x63, 0x41, 0x2C, 0x3A,
0xCB, 0xF0, 0xA0, 0x33, 0x5B, 0x34, 0xE1, 0xD2, 0x85, 0x31, 0xB7, 0xB9, 0x4A,
0xD3, 0x29, 0x8A, 0x9B, 0x7E, 0x2E, 0x8E, 0x32, 0x72, 0xEB, 0x85, 0x8C, 0xA6,
0x61, 0x86, 0x36, 0x4A, 0x23, 0x22, 0xE2, 0xB4, 0x21, 0xF6, 0xD7, 0xCD, 0x40,
0xDB, 0xE1, 0x6E, 0x37, 0x0B, 0xB7, 0x08, 0x01, 0x17, 0x12, 0xB2, 0x56, 0x9E,
0x6B, 0x17, 0x2C, 0x31, 0x69, 0x14, 0x33, 0x0D, 0x49, 0x96, 0x44, 0x86, 0x42,
0x0B, 0xA7, 0x51, 0x67, 0x53, 0x2C, 0x86, 0x39, 0x49, 0xC2, 0x5F, 0x3C, 0xE9,
0xDF, 0x5F, 0x9C, 0x1F, 0x93, 0xC8, 0x28, 0x5F, 0x41, 0x83, 0xD9, 0x34, 0x80,
0x77, 0xE3, 0x6C, 0xE9, 0x81, 0xBE, 0x16, 0xC2, 0x6F, 0x85, 0x75, 0x93, 0x28,
0x15, 0xDB, 0xE1, 0x67, 0xC1, 0x75, 0xDA, 0x9C, 0x80, 0xE2, 0x8D, 0xA2, 0x29,
0x62, 0x9A, 0xA6, 0x0C, 0x6F, 0xC8, 0xE2, 0xB8, 0x35, 0x26, 0x7F, 0x27, 0x35,
0xCE, 0xEF, 0x21, 0x43, 0xED, 0xF2, 0x8F, 0x34, 0x22, 0x0E, 0x2A, 0x0D, 0x63,
0x2B, 0x01, 0x75, 0xB0, 0x95, 0xD2, 0x74, 0x3F, 0x21, 0x84, 0xE5, 0x23, 0x06,
0x62, 0x47, 0x8E, 0x0B, 0x40, 0xEA, 0xB8, 0x2F, 0x9C, 0x07, 0xF4, 0xCC, 0xA2,
0xA7, 0x8D, 0x78, 0x17, 0x40, 0x38, 0x0E, 0xA6, 0x1F, 0x81, 0xB1, 0x21, 0xF6,
0x10, 0x18, 0x4A, 0xD3, 0x7B, 0x46, 0x8F, 0x69, 0xE2, 0x78, 0x1B, 0x2E, 0xCF,
0x96, 0xBF, 0x56, 0xA9, 0x17, 0x8D, 0x97, 0xB5, 0x69, 0x1D, 0xFE, 0xD4, 0x7E,
0xB6, 0x0D, 0xC1, 0xEA, 0xAC, 0x12, 0xB3, 0xAD, 0xE0, 0xC6, 0xB5, 0xF2, 0x96,
0xE0, 0x12, 0xD6, 0xF5, 0xB8, 0xF4, 0x86, 0xCC, 0xE4, 0x55, 0xA7, 0x05, 0x6F,
0xF9, 0x88, 0xD5, 0x36, 0x8D, 0xD6, 0x75, 0x18, 0xCA, 0xD5, 0x28, 0x21, 0x64,
0x41, 0x1D, 0xC6, 0x38, 0x56, 0x50, 0x96, 0x8E, 0x1A, 0x32, 0xD8, 0x4A, 0x47,
0x82, 0xFC, 0x67, 0xB2, 0xB5, 0xED, 0xC2, 0x54, 0x46, 0x87, 0xE3, 0x1F, 0xBB,
0x18, 0xCD, 0xB0, 0x59, 0xA0, 0xBE, 0xA6, 0x4D, 0x4E, 0x1E, 0x7A, 0x46, 0xE5,
0x77, 0xB2, 0x59, 0xCE, 0x61, 0xEF, 0xA2, 0x0A, 0xEC, 0x55, 0x8E, 0xB0, 0xD4,
0x3E, 0x1B, 0x25, 0x37, 0x8E, 0xA7, 0xB2, 0x27, 0xED, 0x00, 0x8C, 0x38, 0x26,
0x5E, 0x9D, 0x20, 0x38, 0x6A, 0xAF, 0xD2, 0x24, 0x94, 0x31, 0xF5, 0x6E, 0x66,
0x41, 0x2C, 0xFD, 0x77, 0x9C, 0x2D, 0x73, 0xE5, 0x8E, 0x64, 0xF7, 0x3D, 0xDF,
0x42, 0x37, 0xFE, 0x07, 0xB6, 0xBC, 0x29, 0x02, 0xD4, 0x90, 0xDA, 0x3F, 0x5E,
0x7F, 0xEC, 0x39, 0xC7, 0x4D, 0x11, 0x09, 0xBE, 0xA6, 0xF4, 0xBE, 0x4F, 0x14,
0x2C, 0x59, 0xD5, 0x07, 0xD3, 0x49, 0x81, 0x5D, 0x3B, 0xF9, 0x90, 0xD1, 0x8E,
0xB1, 0x83, 0xE3, 0x39, 0xDF, 0x04, 0x62, 0x56, 0x44, 0x12, 0xA2, 0x36, 0x28,
0xAA, 0xBC, 0x46, 0xDF, 0x78, 0xFF, 0x27, 0xC5, 0x3A, 0x16, 0xA5, 0x59, 0x63,
0xBF, 0x25, 0x0C, 0x31, 0xAD, 0x90, 0xF5, 0xBB, 0xAA, 0x9C, 0x56, 0x7D, 0x4A,
0xA5, 0x8C, 0x25, 0xAA, 0x9D, 0xB3, 0x44, 0xDB, 0x82, 0xCF, 0x46, 0x10, 0x1F,
0x4E, 0x24, 0xC1, 0x85, 0x6B, 0x6E, 0xD0, 0xC0, 0x66, 0x79, 0x58, 0xB1, 0x86,
0x86, 0xD0, 0xEF, 0xDA, 0xE0, 0xE0, 0x40, 0x61, 0x53, 0xFB, 0x02, 0xB4, 0x57,
0xFD, 0x47, 0xC0, 0xE0, 0x01, 0x9F, 0x4B, 0x51, 0xB1, 0x0B, 0x8C, 0x58, 0x7F,
0x92, 0xA9, 0xFA, 0x9D, 0x74, 0x12, 0x1B, 0xCC, 0x23, 0xF1, 0x21, 0xAE, 0x21,
0x16, 0xEF, 0xE1, 0xF9, 0x78, 0x67, 0xED, 0xDD, 0x31, 0xC1, 0xE0, 0xE6, 0x53,
0xD8, 0x55, 0xCE, 0x04, 0x99, 0x50, 0xB9, 0x11, 0x05, 0xDE, 0xD1, 0xD3, 0x2B,
0x9E, 0xF4, 0xB9, 0x8A, 0x95, 0x20, 0x69, 0x5A, 0x96, 0xD2, 0x82, 0x9C, 0x26,
0x60, 0xE0, 0x51, 0x95, 0xA3, 0x74, 0x4F, 0x22, 0x7F, 0x01, 0xCC, 0x80, 0xAB,
0xD5, 0x92, 0xB3, 0xF0, 0x3F, 0xE8, 0x0F, 0xD8, 0x7C, 0x4D, 0xB0, 0x37, 0x55,
0xE7, 0xE2, 0x9A, 0xDC, 0x09, 0x80, 0x01, 0x43, 0x54, 0xDF, 0x57, 0x6D, 0x92,
0x21, 0x81, 0x92, 0xA4, 0x33, 0xEF, 0xDD, 0x59, 0xC6, 0xD3, 0x17, 0x3A, 0xBD,
0x75, 0x7A, 0x91, 0x50, 0xCF, 0x69, 0x97, 0x07, 0x38, 0xFB, 0x9E, 0xCE, 0x3A,
0x78, 0x25, 0xCF, 0x11, 0x5C, 0xD6, 0xC8, 0x53, 0xCF, 0xA6, 0x0E, 0x06, 0xF5,
0xD5, 0x5C, 0x16, 0x26, 0x4F, 0x0E, 0x12, 0x37, 0xEF, 0xD8, 0x7A, 0xFF, 0xCE,
0xA8, 0x8D, 0x44, 0x05, 0x4F, 0x35, 0xC1, 0x87, 0xBB, 0xF1, 0xF8, 0x91, 0x8B,
0x91, 0xD4, 0x96, 0x70, 0x7C, 0x4B, 0x89, 0xA8, 0x07, 0x66, 0x63, 0x7C, 0xD0,
0x1D, 0xBE, 0x4D, 0x03, 0x41, 0x19, 0x8B, 0x67, 0x66, 0xFD, 0xCE, 0xF5, 0xD8,
0x46, 0x13, 0x45, 0x72, 0xA7, 0x47, 0xF0, 0x67, 0xB4, 0x30, 0x58, 0xCE, 0x5B,
0xEA, 0x02, 0x7C, 0xF3, 0xC2, 0xF7, 0xAE, 0x3A, 0x4C, 0x5C, 0x11, 0xAF, 0xC3,
0xB2, 0xA8, 0x1F, 0x2F, 0xD2, 0x1E, 0x8F, 0xF1, 0x70, 0x1B, 0x9D, 0xF0, 0x61,
0x28, 0xF0, 0xBB, 0x64, 0x9C, 0x07, 0x2E, 0xD6, 0xFB, 0xA0, 0xD3, 0x14, 0x16,
0x7E, 0x73, 0x00, 0xD0, 0x28, 0xF5, 0x96, 0x83, 0x18, 0x2F, 0xBC, 0x7E, 0x4D,
0xE1, 0xA4, 0xC2, 0x91, 0x6C, 0xDA, 0xAB, 0xDD, 0xE0, 0xC1, 0x89, 0xD3, 0xE3,
0x5D, 0x17, 0x64, 0x48, 0x23, 0x4F, 0x8C, 0xB4, 0x17, 0x38, 0x6C, 0x25, 0xCF,
0x89, 0x84, 0x56, 0x3E, 0x92, 0x6F, 0xCA, 0xCB, 0xD7, 0xC0, 0x89, 0x05, 0xB0,
0x39, 0x66, 0x16, 0x98, 0x6C, 0xD5, 0xD2, 0x14, 0x7D, 0x85, 0xF5, 0xD0, 0x3A,
0x02, 0x42, 0x25, 0x6B, 0xDB, 0x40, 0xF3, 0xA5, 0x5C, 0x03, 0x6F, 0xA9, 0x6A,
0x98, 0x4F, 0xC4, 0x77, 0x83, 0xED, 0x40, 0x4E, 0x32, 0xB6, 0xE4, 0x6F, 0x5B,
0x13, 0x88, 0x04, 0x3B, 0x0D, 0x6E, 0xC1, 0x67, 0x20, 0xEA, 0x3B, 0x3C, 0xC4,
0x4A, 0xA9, 0x23, 0xE0, 0x41, 0x8A, 0xA8, 0x13, 0x00, 0xB5, 0x8C, 0x37, 0x71,
0x57, 0xD3, 0xED, 0x9F, 0x9A, 0x6C, 0xB7, 0x6C, 0x5B, 0x46, 0xBD, 0x8A, 0x98,
0x30, 0xA3, 0x34, 0x1F, 0xCA, 0x19, 0x81, 0xE0, 0xFF, 0x4C, 0x08, 0x09, 0x82,
0xBC, 0x0D, 0xDF, 0xB2, 0x57, 0x68, 0x0B, 0x0A, 0xE7, 0xE2, 0x83, 0xD4, 0xD1,
0xA4, 0x62, 0x8F, 0x88, 0xCF, 0x04, 0xDC, 0x11, 0xE9, 0x9B, 0xCD, 0xEC, 0x0B,
0x88, 0x2B, 0x57, 0x9A, 0xF9, 0x71, 0xB8, 0xC3, 0x05, 0x59, 0x35, 0xF2, 0xA9,
0x80, 0xE0, 0x16, 0x22, 0xCA, 0xE0, 0xAE, 0x1B, 0xB5, 0x54, 0x76, 0xC1, 0xBA,
0x32, 0x9B, 0x67, 0x18, 0x86, 0x7C, 0x15, 0xD6, 0x81, 0x1A, 0xDF, 0x83, 0xD0,
0xDD, 0x6B, 0x2F, 0x98, 0x56, 0xB2, 0xBA, 0xFC, 0xA7, 0xD3, 0xE7, 0xAA, 0xE7,
0x3A, 0xC2, 0x50, 0x74, 0x63, 0xE6, 0x72, 0xC3, 0x40, 0x00, 0xF2, 0xDC, 0x06,
0x86, 0x1F, 0xF5, 0xE2, 0xD5, 0x77, 0xF5, 0xFF, 0x87, 0x32, 0x30, 0x61, 0x94,
0xE7, 0x04, 0x68, 0x0E, 0xC4, 0xF9, 0xDA, 0x54, 0x93, 0x32, 0xCE, 0x7D, 0x82,
0x05, 0x9A, 0x25, 0xF2, 0x88, 0x32, 0x64, 0x1A, 0x71, 0x94, 0x50, 0xBC, 0xD0,
0x31, 0xE2, 0x53, 0x61, 0x4A, 0xFF, 0xD4, 0x2E, 0xCE, 0xE0, 0x5B, 0xC4, 0x24,
0xCA, 0x95, 0xE2, 0x75, 0x54, 0xB6, 0xCF, 0x5C, 0xD6, 0x96, 0x0F, 0x1F, 0x60,
0xA2, 0x20, 0x1F, 0x00, 0x3C, 0x2D, 0x0D, 0x89, 0x90, 0xBD, 0x3A, 0xD3, 0xDC,
0x64, 0xB1, 0x61, 0xFB, 0xAA, 0x67, 0x15, 0xB0, 0xCE, 0x18, 0x1B, 0x09, 0xA2,
0x38, 0x31, 0x95, 0x0F, 0x2C, 0x25, 0x80, 0x4B, 0x13, 0xCB, 0xA0, 0xC7, 0xC7,
0xFA, 0xCC, 0x2C, 0x98, 0x66, 0xBE, 0xDC, 0x7B, 0xBB, 0x53, 0x12, 0x33, 0xDF,
0x92, 0x0C, 0x5F, 0x9E, 0xCC, 0x8E, 0x18, 0x23, 0x03, 0x2D, 0x7A, 0x2B, 0x90,
0x71, 0x07, 0x24, 0x95, 0xFE, 0x50, 0x95, 0x6E, 0x95, 0xFF, 0x29, 0x85, 0x7B,
0x44, 0x1C, 0x0A, 0x86, 0x48, 0x9B, 0x6B, 0xEA, 0xA7, 0xF9, 0xBF, 0xE8, 0x84,
0x10, 0xDC, 0x45, 0xC7, 0xFB, 0x2A, 0x39, 0x99, 0x0D, 0xCF, 0x23, 0x88, 0x35,
0x9C, 0x3D, 0xBA, 0x77, 0x7E, 0x8D, 0x4C, 0xA7, 0xB6, 0x41, 0x25, 0x46, 0x9A,
0x8E, 0xFF, 0x74, 0x5E, 0x9E, 0xDB, 0x8F, 0x20, 0xE9, 0xE3, 0x83, 0x84, 0x28,
0x0E, 0x14, 0xFC, 0x52, 0x1A, 0x69, 0xEC, 0x95, 0x5E, 0xBD, 0xFA, 0x05, 0xE4,
0xE5, 0xC7, 0xEB, 0x5F, 0x90, 0x21, 0x9C, 0xD5, 0x6B, 0xF7, 0x31, 0x35, 0xDA,
0x30, 0x41, 0xB2, 0x7E, 0xAB, 0x43, 0x36, 0x4E, 0x0B, 0x84, 0xDE, 0x43, 0x62,
0x96, 0x81, 0xF8, 0x9B, 0x81, 0x20, 0x06, 0x3B, 0xCA, 0x8E, 0x09, 0xE7, 0x2A,
0x6B, 0x41, 0x0C, 0x42, 0x02, 0x27, 0x41, 0x95, 0x8C, 0x86, 0x91, 0x40, 0xB1,
0xE8, 0x0C, 0x65, 0x6F, 0x23, 0xA5, 0x4A, 0xA9, 0x14, 0x8F, 0x32, 0x36, 0x3A,
0xDC, 0xAE, 0x54, 0x29, 0x13, 0x6B, 0xC0, 0x0D, 0x76, 0x6F, 0x79, 0xC4, 0x0A,
0x87, 0x89, 0xF2, 0xDD, 0xB0, 0xE3, 0xC0, 0x65, 0xC7, 0xE3, 0xBD, 0x17, 0xC4,
0x66, 0x3F, 0x84, 0x0B, 0x3F, 0x7A, 0x50, 0x08, 0x5F, 0x68, 0xE6, 0xC6, 0x37,
0xA7, 0x73, 0xF4, 0x4F, 0x37, 0x05, 0x28, 0x64, 0x0E, 0x36, 0xF8, 0xC2, 0x2F,
0xEA, 0x1D, 0x98, 0xBB, 0xB2, 0xFB, 0xE5, 0x98, 0xAE, 0x5D, 0xF8, 0xE8, 0xDA,
0xA1, 0xB6, 0x43, 0x0C, 0x6D, 0x1C, 0x39, 0x59, 0xE1, 0xBF, 0xEB, 0xA6, 0x4D,
0xBF, 0x12, 0x0E, 0x6E, 0xC4, 0x93, 0x8B, 0x72, 0x54, 0x47, 0xBE, 0xFC, 0x3A,
0x00, 0x7F, 0xD3, 0x57, 0x32, 0xE7, 0x86, 0xF0, 0x96, 0xCC, 0x06, 0x8F, 0x73,
0x9C, 0xE6, 0x8D, 0xD8, 0xB8, 0x24, 0xF9, 0xC0, 0x51, 0x99, 0xB8, 0x35, 0x98,
0x37, 0x32, 0x35, 0x03, 0x5C, 0xDA, 0x91, 0xC9, 0x6A, 0x50, 0xE5, 0xE1, 0xF0,
0xEF, 0xBB, 0x66, 0x27, 0x91, 0x51, 0x57, 0x09, 0xBB, 0x5B, 0xE9, 0x26, 0x8E,
0xB9, 0x75, 0xD9, 0x2E, 0x80, 0xE2, 0xDD, 0x27, 0xDD, 0x5A, 0x1B, 0x4E, 0xCF,
0x17, 0x11, 0x2B, 0x7B, 0xCB, 0xF9, 0xB3, 0xED, 0x07, 0xF3, 0x5A, 0xEE, 0xBF,
0x4B, 0x07, 0x43, 0x73, 0xF8, 0x24, 0x16, 0x67, 0x41, 0xE9, 0x64, 0xB4, 0xE7,
0x05, 0x72, 0x91, 0xF7, 0xCE, 0x38, 0x7D, 0x38, 0xA5, 0x60, 0x95, 0xC1, 0xC7,
0x64, 0x1B, 0xCC, 0xC4, 0x12, 0x32, 0xC3, 0x49, 0x7E, 0xAB, 0x96, 0x1D, 0x2A,
0x3C, 0x60, 0x51, 0xAA, 0x62, 0x86, 0xF3, 0x9F, 0xC6, 0x7F, 0xAB, 0x0F, 0xBB,
0x15, 0x7B, 0xBA, 0x43, 0x26, 0xAE, 0x37, 0x45, 0x5F, 0x39, 0x70, 0xB7, 0x19,
0x2F, 0x02, 0x33, 0xF1, 0x11, 0x4E, 0x78, 0x7D, 0x17, 0x8F, 0xBF, 0xEB, 0x92,
0xCC, 0x2F, 0xCA, 0x87, 0x01, 0xA8, 0xE3, 0xAD, 0x7B, 0x4A, 0x44, 0x0C, 0x75,
0x5A, 0x31, 0xCA, 0xE1, 0xE6, 0x18, 0xD7, 0xC4, 0xA3, 0xBA, 0x7F, 0xB5, 0xBC,
0xFD, 0xA6, 0x9C, 0xDC, 0x2A, 0xEB, 0x18, 0xDC, 0x88, 0x08, 0x6E, 0x7D, 0x6A,
0x97, 0xB6, 0xCD, 0x53, 0x41, 0x1D, 0xB4, 0xA8, 0xBD, 0xE3, 0x85, 0x29, 0x5F,
0x12, 0x03, 0xB8, 0x09, 0x13, 0x20, 0x6D, 0x68, 0x4F, 0x80, 0x1E, 0xBB, 0x6C,
0xD6, 0x51, 0x8C, 0x46, 0x19, 0x00, 0xBB, 0x90, 0xF9, 0xEA, 0xB0, 0x33, 0xF4,
0x52, 0xCA, 0x19, 0xD6, 0x68, 0xAE, 0x79, 0xE2, 0xC1, 0x39, 0xA9, 0x18, 0xF2,
0x26, 0x71, 0x69, 0xFF, 0xBA, 0x97, 0x28, 0x34, 0x4D, 0x10, 0x01, 0xFB, 0xD7,
0xBA, 0x37, 0x0F, 0xC8, 0xFC, 0x07, 0x7A, 0xCD, 0x1A, 0xDD, 0x92, 0x0D, 0x45,
0x8A, 0x7B, 0x6F, 0x94, 0x00, 0x53, 0x7E, 0xAF, 0xA5, 0x99, 0xB9, 0x7F, 0x00,
0xCD, 0xC7, 0x7C, 0x35, 0xCE, 0x53, 0x64, 0x15, 0xC2, 0x47, 0x7C, 0xD1, 0x12,
0x40, 0xBD, 0xF9, 0x8B, 0xBA, 0x3B, 0x5A, 0x3D, 0xFF, 0x5C, 0x48, 0x3A, 0x7F,
0xEF, 0x5B, 0xA8, 0xFC, 0xD6, 0xEA, 0xFB, 0x49, 0x0B, 0x29, 0x98, 0x5F, 0xCA,
0xBC, 0xC1, 0xD5, 0xA8, 0x15, 0x5B, 0x09, 0xEF, 0xB3, 0x0E, 0x41, 0xDC, 0x4D,
0x22, 0x30, 0xEE, 0xAA, 0xD9, 0xBA, 0x37, 0x43, 0xDE, 0x34, 0xF8, 0xB9, 0x42,
0xE7, 0x65, 0xEC, 0xE6, 0xA3, 0xE1, 0xED, 0x46, 0x46, 0xB4, 0x9F, 0x1C, 0xA0,
0x61, 0x50, 0x8E, 0x8A, 0x61, 0xBC, 0xF1, 0x3A, 0x55, 0xF8, 0xAB, 0xBA, 0x09,
0x5A, 0x4F, 0xB1, 0x38, 0x99, 0x77, 0x0A, 0xF5, 0x5D, 0xF7, 0xA0, 0x29, 0xA5,
0x00, 0x1D, 0x92, 0xC1, 0xA8, 0x4A, 0x73, 0x13, 0xCB, 0x1F, 0x14, 0xB0, 0xDB,
0x64, 0x53, 0xA8, 0x77, 0xB1, 0x80, 0xDF, 0xA7, 0x20, 0x9A, 0xA3, 0xD1, 0x79,
0x4B, 0x75, 0x45, 0x6D, 0xB0, 0xF5, 0xD8, 0x09, 0xE3, 0xB7, 0x7C, 0xC8, 0x1B,
0x56, 0xA2, 0x04, 0x11, 0xFB, 0xAC, 0x2D, 0x55, 0xF3, 0x95, 0x36, 0xF2, 0xAE,
0x6E, 0x9F, 0x10, 0xFE, 0xC0, 0xD5, 0x62, 0x36, 0xA7, 0xA0, 0xC5, 0x05, 0x2F,
0x55, 0x79, 0x59, 0x1B, 0xF4, 0xF6, 0xC3, 0xD2, 0x77, 0x96, 0x35, 0xBF, 0x89,
0x33, 0x45, 0xE9, 0xAB, 0x0A, 0x4B, 0xE1, 0x42, 0x31, 0xAF, 0x38, 0xA2, 0xA9,
0x45, 0xCF, 0x7D, 0x02, 0x88, 0x77, 0x4B, 0xD0, 0x2D, 0x9B, 0x56, 0x6E, 0xC3,
0xB3, 0x61, 0xA8, 0x1F, 0x8B, 0x9C, 0x3F, 0x63, 0xD4, 0x3C, 0x88, 0xA0, 0x7B,
0x90, 0xDB, 0x02, 0x30, 0xC5, 0xE8, 0x68, 0x82, 0x28, 0x58, 0x40, 0x31, 0xA3,
0x5C, 0xE9, 0xFB, 0x2A, 0xE6, 0x6E, 0x8F, 0x49, 0x5B, 0xF6, 0xAC, 0xB5, 0xBF,
0x30, 0xA8, 0x68, 0x83, 0x5E, 0xB4, 0x26, 0xBF, 0x6D, 0x1F, 0xEC, 0xEB, 0x00,
0xBD, 0x12, 0x0D, 0xB9, 0x80, 0xF1, 0xE7, 0x13, 0x3B, 0xCA, 0x81, 0x98, 0x5C,
0xE8, 0xA1, 0x98, 0xA1, 0x82, 0x26, 0x5F, 0xDD, 0xE0, 0xAE, 0xF8, 0x0C, 0x63,
0x78, 0xA8, 0xC1, 0xF7, 0x20, 0x62, 0x0B, 0xC8, 0xF9, 0xE5, 0x89, 0x43, 0x44,
0x05, 0x56, 0x98, 0xDE, 0xFD, 0x99, 0x25, 0xC0, 0x33, 0xCA, 0x1C, 0xDD, 0xAE,
0x2F, 0xDF, 0x14, 0x7E, 0xE2, 0x75, 0x75, 0xBC, 0x1C, 0x81, 0xF7, 0x21, 0x07,
0x0E, 0x21, 0x4A, 0x41, 0x4F, 0x33, 0xBD, 0x00, 0x5D, 0xBD, 0xF1, 0x79, 0x0C,
0x15, 0x8C, 0x98, 0x06, 0x72, 0xB8, 0xC2, 0xC1, 0x29, 0xFB, 0x7E, 0xE5, 0xF4,
0x04, 0x49, 0x17, 0xFD, 0x4B, 0xE5, 0xC7, 0x03, 0xFA, 0x88, 0x81, 0xBF, 0xDB,
0x10, 0xE2, 0x37, 0x12, 0x9E, 0x63, 0x7D, 0xFA, 0xBC, 0xF6, 0x98, 0x12, 0x23,
0x99, 0x59, 0xE3, 0x30, 0xD0, 0xA8, 0x21, 0x6D, 0x80, 0x2A, 0xF4, 0xB9, 0x6D,
0x71, 0x62, 0x0B, 0xA7, 0x99, 0xB2, 0xA1, 0x60, 0x34, 0xC5, 0x7F, 0xC3, 0x59,
0x78, 0xED, 0xB4, 0xA6, 0x5E, 0xF8, 0xC8, 0x5E, 0xF6, 0x69, 0xCE, 0xA0, 0x98,
0x87, 0x79, 0xDB, 0xB8, 0xA2, 0x3C, 0x94, 0xAC, 0xD1, 0x4C, 0x6C, 0x72, 0x39,
0x17, 0x32, 0x78, 0xA1, 0xDC, 0x1D, 0x03, 0xB2, 0xA1, 0x57, 0x0D, 0x2F, 0xA7,
0xF4, 0x8D, 0xE8, 0x4C, 0x67, 0x95, 0x19, 0x95, 0x55, 0xB9, 0xDE, 0x38, 0xD0,
0x85, 0xDB, 0x15, 0xB8, 0x8C, 0x0F, 0x6A, 0x69, 0x38, 0xF6, 0x8B, 0x75, 0x81,
0x89, 0x7E, 0xF8, 0x3A, 0xF3, 0x27, 0x08, 0xC0, 0x7B, 0x78, 0x3A, 0x73, 0xA5,
0xCB, 0xB0, 0x67, 0xD7, 0xDF, 0x88, 0x84, 0x4A, 0x52, 0xBD, 0x91, 0x74, 0x2C,
0xD1, 0x16, 0x3A, 0xCB, 0x0D, 0x3D, 0x08, 0x3D, 0x4F, 0x58, 0xE6, 0xCB, 0x32,
0x8A, 0x52, 0x86, 0x82, 0x61, 0x00, 0xDE, 0xCA, 0xF3, 0xDE, 0x05, 0xAB, 0x15,
0xAE, 0x13, 0x35, 0x4A, 0xE2, 0x45, 0xD5, 0xC1, 0xB0, 0x1B, 0xFA, 0xD8, 0xAD,
0xF7, 0xD2, 0x9A, 0x53, 0x06, 0x79, 0x15, 0xA6, 0x95, 0xE0, 0x6C, 0xC7, 0xFA,
0x94, 0x81, 0xB4, 0x91, 0x9D, 0x53, 0x89, 0x2D, 0x59, 0x74, 0x9F, 0x0F, 0xD5,
0x4E, 0xE6, 0xF6, 0x07, 0x62, 0x3B, 0x2C, 0x59, 0xA0, 0x47, 0x52, 0xDF, 0xF4,
0x10, 0xC2, 0xEB, 0x38, 0x86, 0x2F, 0x42, 0x01, 0xC2, 0x8A, 0xCB, 0x20, 0x7B,
0xFC, 0xB8, 0xEA, 0x20, 0x14, 0x69, 0x8B, 0x63, 0x52, 0xA8, 0x13, 0x1D, 0xD4,
0x60, 0x32, 0xF6, 0xDE, 0x75, 0x4D, 0x41, 0xC2, 0xC7, 0xA2, 0x62, 0x6F, 0x04,
0xAF, 0xF9, 0x9E, 0x3D, 0x1C, 0xCB, 0xBB, 0xEC, 0x7A, 0xFD, 0x9C, 0x97, 0x87,
0x40, 0xF1, 0xE7, 0x91, 0xCD, 0x36, 0xD2, 0x64, 0xB1, 0x2B, 0x43, 0xBA, 0x6E,
0xBD, 0x0E, 0x7D, 0xB1, 0x45, 0xA4, 0x0B, 0x84, 0xEB, 0x18, 0x5C, 0x25, 0x8B,
0x9B, 0x62, 0xB3, 0x8C, 0x95, 0xEF, 0x6F, 0x09, 0xE9, 0xF8, 0xE8, 0x18, 0x1A,
0x8A, 0xE2, 0xCC, 0x48, 0xDC, 0xC6, 0xDC, 0x94, 0xB1, 0x24, 0x55, 0x13, 0xB6,
0xD8, 0x16, 0xAB, 0x5F, 0x20, 0x7F, 0x5E, 0x35, 0x1F, 0x5A, 0x56, 0x2C, 0xFF,
0x02, 0x9C, 0xAF, 0x18, 0xF8, 0xBB, 0x60, 0xE1, 0xD4, 0xEF, 0x5E, 0x03, 0x08,
0x07, 0xCD, 0x29, 0x35, 0x7B, 0x9F, 0xEC, 0x35, 0xDB, 0x1D, 0xE1, 0xFD, 0x85,
0xC3, 0xDB, 0xE0, 0x58, 0x1F, 0x39, 0xE9, 0x38, 0xAE, 0x37, 0x18, 0xAF, 0x9C,
0x11, 0x97, 0x97, 0x6B, 0x67, 0x46, 0xC8, 0x68, 0xB7, 0x65, 0x05, 0x20, 0x02,
0x70, 0xDA, 0x6B, 0xC7, 0x34};

// mldsa87kPublicKeySPKI is the above example ML-DSA-87 public key encoded
static const uint8_t mldsa87kPublicKeySPKI[] = {
0x30, 0x82, 0x0A, 0x32, 0x30, 0x0B, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
0x03, 0x04, 0x03, 0x13, 0x03, 0x82, 0x0A, 0x21, 0x00, 0xE4, 0x36, 0x63, 0x53,
0xA7, 0xE7, 0xDF, 0x51, 0x06, 0x19, 0x34, 0x9F, 0xB5, 0x95, 0x53, 0x9D, 0xC0,
0x59, 0x21, 0x38, 0x0F, 0x8E, 0x2A, 0xEC, 0x43, 0x5C, 0x9B, 0x4B, 0xD0, 0xDC,
0x7E, 0xE1, 0x89, 0x77, 0x51, 0xD4, 0x26, 0x46, 0x8F, 0x25, 0x76, 0xAB, 0x5E,
0x68, 0xFE, 0x45, 0xC6, 0x35, 0xF5, 0xF0, 0xD0, 0x2D, 0xD2, 0x11, 0xCB, 0x2D,
0x3B, 0x6B, 0xF3, 0x2F, 0x68, 0xD1, 0xF2, 0xCC, 0x51, 0x9E, 0xE0, 0xC5, 0x1D,
0xFA, 0x2C, 0x55, 0x02, 0xE5, 0xAB, 0xC6, 0xA2, 0xA9, 0x2C, 0x35, 0xC1, 0x22,
0xDC, 0xFB, 0x9D, 0xDC, 0x9E, 0x17, 0xCB, 0x7C, 0xEC, 0xB4, 0x7D, 0x1C, 0x40,
0xA6, 0x40, 0x3C, 0x2B, 0x1C, 0x5B, 0x85, 0x97, 0x31, 0x5D, 0x9E, 0xAD, 0x7C,
0xC9, 0xF1, 0xBC, 0x99, 0x59, 0x2B, 0xE0, 0x10, 0x30, 0x58, 0xC6, 0x63, 0xBD,
0xD7, 0xF1, 0x27, 0x2B, 0x1E, 0xB2, 0xA8, 0x31, 0xD7, 0xD3, 0x2B, 0x85, 0xA7,
0x59, 0xAF, 0x70, 0x15, 0x66, 0x9E, 0xD2, 0x13, 0xB0, 0x50, 0xBF, 0x59, 0x08,
0x92, 0x32, 0x07, 0x9C, 0x81, 0xD7, 0x06, 0x55, 0x76, 0xEE, 0x15, 0x8A, 0xFE,
0xCB, 0x62, 0x58, 0xF7, 0xDF, 0x0F, 0xEB, 0x0A, 0x11, 0x98, 0xF8, 0x93, 0xD8,
0x96, 0xF5, 0x14, 0x87, 0x40, 0x4F, 0xEC, 0x9A, 0x45, 0xE2, 0x7A, 0x54, 0x91,
0x0B, 0xDB, 0x39, 0x90, 0x48, 0x5D, 0x1B, 0xE6, 0x63, 0x2C, 0x47, 0xC2, 0x2C,
0x45, 0x91, 0xDA, 0x52, 0x65, 0x15, 0x54, 0x35, 0x1A, 0xFF, 0x3E, 0xC9, 0x64,
0xED, 0x48, 0xE6, 0x7C, 0xDB, 0x2C, 0x72, 0x7B, 0x14, 0xC0, 0x35, 0x5C, 0x14,
0xE8, 0xBB, 0x92, 0xEA, 0xB6, 0x29, 0x29, 0x8B, 0x8A, 0x4D, 0x95, 0x1F, 0xAE,
0x54, 0x64, 0x07, 0x2D, 0xAD, 0x3D, 0xA4, 0x20, 0x20, 0xA0, 0x7A, 0x7C, 0xAE,
0x9E, 0xFE, 0x5C, 0xE8, 0x88, 0x63, 0x41, 0x2C, 0x3A, 0xCB, 0xF0, 0xA0, 0x33,
0x5B, 0x34, 0xE1, 0xD2, 0x85, 0x31, 0xB7, 0xB9, 0x4A, 0xD3, 0x29, 0x8A, 0x9B,
0x7E, 0x2E, 0x8E, 0x32, 0x72, 0xEB, 0x85, 0x8C, 0xA6, 0x61, 0x86, 0x36, 0x4A,
0x23, 0x22, 0xE2, 0xB4, 0x21, 0xF6, 0xD7, 0xCD, 0x40, 0xDB, 0xE1, 0x6E, 0x37,
0x0B, 0xB7, 0x08, 0x01, 0x17, 0x12, 0xB2, 0x56, 0x9E, 0x6B, 0x17, 0x2C, 0x31,
0x69, 0x14, 0x33, 0x0D, 0x49, 0x96, 0x44, 0x86, 0x42, 0x0B, 0xA7, 0x51, 0x67,
0x53, 0x2C, 0x86, 0x39, 0x49, 0xC2, 0x5F, 0x3C, 0xE9, 0xDF, 0x5F, 0x9C, 0x1F,
0x93, 0xC8, 0x28, 0x5F, 0x41, 0x83, 0xD9, 0x34, 0x80, 0x77, 0xE3, 0x6C, 0xE9,
0x81, 0xBE, 0x16, 0xC2, 0x6F, 0x85, 0x75, 0x93, 0x28, 0x15, 0xDB, 0xE1, 0x67,
0xC1, 0x75, 0xDA, 0x9C, 0x80, 0xE2, 0x8D, 0xA2, 0x29, 0x62, 0x9A, 0xA6, 0x0C,
0x6F, 0xC8, 0xE2, 0xB8, 0x35, 0x26, 0x7F, 0x27, 0x35, 0xCE, 0xEF, 0x21, 0x43,
0xED, 0xF2, 0x8F, 0x34, 0x22, 0x0E, 0x2A, 0x0D, 0x63, 0x2B, 0x01, 0x75, 0xB0,
0x95, 0xD2, 0x74, 0x3F, 0x21, 0x84, 0xE5, 0x23, 0x06, 0x62, 0x47, 0x8E, 0x0B,
0x40, 0xEA, 0xB8, 0x2F, 0x9C, 0x07, 0xF4, 0xCC, 0xA2, 0xA7, 0x8D, 0x78, 0x17,
0x40, 0x38, 0x0E, 0xA6, 0x1F, 0x81, 0xB1, 0x21, 0xF6, 0x10, 0x18, 0x4A, 0xD3,
0x7B, 0x46, 0x8F, 0x69, 0xE2, 0x78, 0x1B, 0x2E, 0xCF, 0x96, 0xBF, 0x56, 0xA9,
0x17, 0x8D, 0x97, 0xB5, 0x69, 0x1D, 0xFE, 0xD4, 0x7E, 0xB6, 0x0D, 0xC1, 0xEA,
0xAC, 0x12, 0xB3, 0xAD, 0xE0, 0xC6, 0xB5, 0xF2, 0x96, 0xE0, 0x12, 0xD6, 0xF5,
0xB8, 0xF4, 0x86, 0xCC, 0xE4, 0x55, 0xA7, 0x05, 0x6F, 0xF9, 0x88, 0xD5, 0x36,
0x8D, 0xD6, 0x75, 0x18, 0xCA, 0xD5, 0x28, 0x21, 0x64, 0x41, 0x1D, 0xC6, 0x38,
0x56, 0x50, 0x96, 0x8E, 0x1A, 0x32, 0xD8, 0x4A, 0x47, 0x82, 0xFC, 0x67, 0xB2,
0xB5, 0xED, 0xC2, 0x54, 0x46, 0x87, 0xE3, 0x1F, 0xBB, 0x18, 0xCD, 0xB0, 0x59,
0xA0, 0xBE, 0xA6, 0x4D, 0x4E, 0x1E, 0x7A, 0x46, 0xE5, 0x77, 0xB2, 0x59, 0xCE,
0x61, 0xEF, 0xA2, 0x0A, 0xEC, 0x55, 0x8E, 0xB0, 0xD4, 0x3E, 0x1B, 0x25, 0x37,
0x8E, 0xA7, 0xB2, 0x27, 0xED, 0x00, 0x8C, 0x38, 0x26, 0x5E, 0x9D, 0x20, 0x38,
0x6A, 0xAF, 0xD2, 0x24, 0x94, 0x31, 0xF5, 0x6E, 0x66, 0x41, 0x2C, 0xFD, 0x77,
0x9C, 0x2D, 0x73, 0xE5, 0x8E, 0x64, 0xF7, 0x3D, 0xDF, 0x42, 0x37, 0xFE, 0x07,
0xB6, 0xBC, 0x29, 0x02, 0xD4, 0x90, 0xDA, 0x3F, 0x5E, 0x7F, 0xEC, 0x39, 0xC7,
0x4D, 0x11, 0x09, 0xBE, 0xA6, 0xF4, 0xBE, 0x4F, 0x14, 0x2C, 0x59, 0xD5, 0x07,
0xD3, 0x49, 0x81, 0x5D, 0x3B, 0xF9, 0x90, 0xD1, 0x8E, 0xB1, 0x83, 0xE3, 0x39,
0xDF, 0x04, 0x62, 0x56, 0x44, 0x12, 0xA2, 0x36, 0x28, 0xAA, 0xBC, 0x46, 0xDF,
0x78, 0xFF, 0x27, 0xC5, 0x3A, 0x16, 0xA5, 0x59, 0x63, 0xBF, 0x25, 0x0C, 0x31,
0xAD, 0x90, 0xF5, 0xBB, 0xAA, 0x9C, 0x56, 0x7D, 0x4A, 0xA5, 0x8C, 0x25, 0xAA,
0x9D, 0xB3, 0x44, 0xDB, 0x82, 0xCF, 0x46, 0x10, 0x1F, 0x4E, 0x24, 0xC1, 0x85,
0x6B, 0x6E, 0xD0, 0xC0, 0x66, 0x79, 0x58, 0xB1, 0x86, 0x86, 0xD0, 0xEF, 0xDA,
0xE0, 0xE0, 0x40, 0x61, 0x53, 0xFB, 0x02, 0xB4, 0x57, 0xFD, 0x47, 0xC0, 0xE0,
0x01, 0x9F, 0x4B, 0x51, 0xB1, 0x0B, 0x8C, 0x58, 0x7F, 0x92, 0xA9, 0xFA, 0x9D,
0x74, 0x12, 0x1B, 0xCC, 0x23, 0xF1, 0x21, 0xAE, 0x21, 0x16, 0xEF, 0xE1, 0xF9,
0x78, 0x67, 0xED, 0xDD, 0x31, 0xC1, 0xE0, 0xE6, 0x53, 0xD8, 0x55, 0xCE, 0x04,
0x99, 0x50, 0xB9, 0x11, 0x05, 0xDE, 0xD1, 0xD3, 0x2B, 0x9E, 0xF4, 0xB9, 0x8A,
0x95, 0x20, 0x69, 0x5A, 0x96, 0xD2, 0x82, 0x9C, 0x26, 0x60, 0xE0, 0x51, 0x95,
0xA3, 0x74, 0x4F, 0x22, 0x7F, 0x01, 0xCC, 0x80, 0xAB, 0xD5, 0x92, 0xB3, 0xF0,
0x3F, 0xE8, 0x0F, 0xD8, 0x7C, 0x4D, 0xB0, 0x37, 0x55, 0xE7, 0xE2, 0x9A, 0xDC,
0x09, 0x80, 0x01, 0x43, 0x54, 0xDF, 0x57, 0x6D, 0x92, 0x21, 0x81, 0x92, 0xA4,
0x33, 0xEF, 0xDD, 0x59, 0xC6, 0xD3, 0x17, 0x3A, 0xBD, 0x75, 0x7A, 0x91, 0x50,
0xCF, 0x69, 0x97, 0x07, 0x38, 0xFB, 0x9E, 0xCE, 0x3A, 0x78, 0x25, 0xCF, 0x11,
0x5C, 0xD6, 0xC8, 0x53, 0xCF, 0xA6, 0x0E, 0x06, 0xF5, 0xD5, 0x5C, 0x16, 0x26,
0x4F, 0x0E, 0x12, 0x37, 0xEF, 0xD8, 0x7A, 0xFF, 0xCE, 0xA8, 0x8D, 0x44, 0x05,
0x4F, 0x35, 0xC1, 0x87, 0xBB, 0xF1, 0xF8, 0x91, 0x8B, 0x91, 0xD4, 0x96, 0x70,
0x7C, 0x4B, 0x89, 0xA8, 0x07, 0x66, 0x63, 0x7C, 0xD0, 0x1D, 0xBE, 0x4D, 0x03,
0x41, 0x19, 0x8B, 0x67, 0x66, 0xFD, 0xCE, 0xF5, 0xD8, 0x46, 0x13, 0x45, 0x72,
0xA7, 0x47, 0xF0, 0x67, 0xB4, 0x30, 0x58, 0xCE, 0x5B, 0xEA, 0x02, 0x7C, 0xF3,
0xC2, 0xF7, 0xAE, 0x3A, 0x4C, 0x5C, 0x11, 0xAF, 0xC3, 0xB2, 0xA8, 0x1F, 0x2F,
0xD2, 0x1E, 0x8F, 0xF1, 0x70, 0x1B, 0x9D, 0xF0, 0x61, 0x28, 0xF0, 0xBB, 0x64,
0x9C, 0x07, 0x2E, 0xD6, 0xFB, 0xA0, 0xD3, 0x14, 0x16, 0x7E, 0x73, 0x00, 0xD0,
0x28, 0xF5, 0x96, 0x83, 0x18, 0x2F, 0xBC, 0x7E, 0x4D, 0xE1, 0xA4, 0xC2, 0x91,
0x6C, 0xDA, 0xAB, 0xDD, 0xE0, 0xC1, 0x89, 0xD3, 0xE3, 0x5D, 0x17, 0x64, 0x48,
0x23, 0x4F, 0x8C, 0xB4, 0x17, 0x38, 0x6C, 0x25, 0xCF, 0x89, 0x84, 0x56, 0x3E,
0x92, 0x6F, 0xCA, 0xCB, 0xD7, 0xC0, 0x89, 0x05, 0xB0, 0x39, 0x66, 0x16, 0x98,
0x6C, 0xD5, 0xD2, 0x14, 0x7D, 0x85, 0xF5, 0xD0, 0x3A, 0x02, 0x42, 0x25, 0x6B,
0xDB, 0x40, 0xF3, 0xA5, 0x5C, 0x03, 0x6F, 0xA9, 0x6A, 0x98, 0x4F, 0xC4, 0x77,
0x83, 0xED, 0x40, 0x4E, 0x32, 0xB6, 0xE4, 0x6F, 0x5B, 0x13, 0x88, 0x04, 0x3B,
0x0D, 0x6E, 0xC1, 0x67, 0x20, 0xEA, 0x3B, 0x3C, 0xC4, 0x4A, 0xA9, 0x23, 0xE0,
0x41, 0x8A, 0xA8, 0x13, 0x00, 0xB5, 0x8C, 0x37, 0x71, 0x57, 0xD3, 0xED, 0x9F,
0x9A, 0x6C, 0xB7, 0x6C, 0x5B, 0x46, 0xBD, 0x8A, 0x98, 0x30, 0xA3, 0x34, 0x1F,
0xCA, 0x19, 0x81, 0xE0, 0xFF, 0x4C, 0x08, 0x09, 0x82, 0xBC, 0x0D, 0xDF, 0xB2,
0x57, 0x68, 0x0B, 0x0A, 0xE7, 0xE2, 0x83, 0xD4, 0xD1, 0xA4, 0x62, 0x8F, 0x88,
0xCF, 0x04, 0xDC, 0x11, 0xE9, 0x9B, 0xCD, 0xEC, 0x0B, 0x88, 0x2B, 0x57, 0x9A,
0xF9, 0x71, 0xB8, 0xC3, 0x05, 0x59, 0x35, 0xF2, 0xA9, 0x80, 0xE0, 0x16, 0x22,
0xCA, 0xE0, 0xAE, 0x1B, 0xB5, 0x54, 0x76, 0xC1, 0xBA, 0x32, 0x9B, 0x67, 0x18,
0x86, 0x7C, 0x15, 0xD6, 0x81, 0x1A, 0xDF, 0x83, 0xD0, 0xDD, 0x6B, 0x2F, 0x98,
0x56, 0xB2, 0xBA, 0xFC, 0xA7, 0xD3, 0xE7, 0xAA, 0xE7, 0x3A, 0xC2, 0x50, 0x74,
0x63, 0xE6, 0x72, 0xC3, 0x40, 0x00, 0xF2, 0xDC, 0x06, 0x86, 0x1F, 0xF5, 0xE2,
0xD5, 0x77, 0xF5, 0xFF, 0x87, 0x32, 0x30, 0x61, 0x94, 0xE7, 0x04, 0x68, 0x0E,
0xC4, 0xF9, 0xDA, 0x54, 0x93, 0x32, 0xCE, 0x7D, 0x82, 0x05, 0x9A, 0x25, 0xF2,
0x88, 0x32, 0x64, 0x1A, 0x71, 0x94, 0x50, 0xBC, 0xD0, 0x31, 0xE2, 0x53, 0x61,
0x4A, 0xFF, 0xD4, 0x2E, 0xCE, 0xE0, 0x5B, 0xC4, 0x24, 0xCA, 0x95, 0xE2, 0x75,
0x54, 0xB6, 0xCF, 0x5C, 0xD6, 0x96, 0x0F, 0x1F, 0x60, 0xA2, 0x20, 0x1F, 0x00,
0x3C, 0x2D, 0x0D, 0x89, 0x90, 0xBD, 0x3A, 0xD3, 0xDC, 0x64, 0xB1, 0x61, 0xFB,
0xAA, 0x67, 0x15, 0xB0, 0xCE, 0x18, 0x1B, 0x09, 0xA2, 0x38, 0x31, 0x95, 0x0F,
0x2C, 0x25, 0x80, 0x4B, 0x13, 0xCB, 0xA0, 0xC7, 0xC7, 0xFA, 0xCC, 0x2C, 0x98,
0x66, 0xBE, 0xDC, 0x7B, 0xBB, 0x53, 0x12, 0x33, 0xDF, 0x92, 0x0C, 0x5F, 0x9E,
0xCC, 0x8E, 0x18, 0x23, 0x03, 0x2D, 0x7A, 0x2B, 0x90, 0x71, 0x07, 0x24, 0x95,
0xFE, 0x50, 0x95, 0x6E, 0x95, 0xFF, 0x29, 0x85, 0x7B, 0x44, 0x1C, 0x0A, 0x86,
0x48, 0x9B, 0x6B, 0xEA, 0xA7, 0xF9, 0xBF, 0xE8, 0x84, 0x10, 0xDC, 0x45, 0xC7,
0xFB, 0x2A, 0x39, 0x99, 0x0D, 0xCF, 0x23, 0x88, 0x35, 0x9C, 0x3D, 0xBA, 0x77,
0x7E, 0x8D, 0x4C, 0xA7, 0xB6, 0x41, 0x25, 0x46, 0x9A, 0x8E, 0xFF, 0x74, 0x5E,
0x9E, 0xDB, 0x8F, 0x20, 0xE9, 0xE3, 0x83, 0x84, 0x28, 0x0E, 0x14, 0xFC, 0x52,
0x1A, 0x69, 0xEC, 0x95, 0x5E, 0xBD, 0xFA, 0x05, 0xE4, 0xE5, 0xC7, 0xEB, 0x5F,
0x90, 0x21, 0x9C, 0xD5, 0x6B, 0xF7, 0x31, 0x35, 0xDA, 0x30, 0x41, 0xB2, 0x7E,
0xAB, 0x43, 0x36, 0x4E, 0x0B, 0x84, 0xDE, 0x43, 0x62, 0x96, 0x81, 0xF8, 0x9B,
0x81, 0x20, 0x06, 0x3B, 0xCA, 0x8E, 0x09, 0xE7, 0x2A, 0x6B, 0x41, 0x0C, 0x42,
0x02, 0x27, 0x41, 0x95, 0x8C, 0x86, 0x91, 0x40, 0xB1, 0xE8, 0x0C, 0x65, 0x6F,
0x23, 0xA5, 0x4A, 0xA9, 0x14, 0x8F, 0x32, 0x36, 0x3A, 0xDC, 0xAE, 0x54, 0x29,
0x13, 0x6B, 0xC0, 0x0D, 0x76, 0x6F, 0x79, 0xC4, 0x0A, 0x87, 0x89, 0xF2, 0xDD,
0xB0, 0xE3, 0xC0, 0x65, 0xC7, 0xE3, 0xBD, 0x17, 0xC4, 0x66, 0x3F, 0x84, 0x0B,
0x3F, 0x7A, 0x50, 0x08, 0x5F, 0x68, 0xE6, 0xC6, 0x37, 0xA7, 0x73, 0xF4, 0x4F,
0x37, 0x05, 0x28, 0x64, 0x0E, 0x36, 0xF8, 0xC2, 0x2F, 0xEA, 0x1D, 0x98, 0xBB,
0xB2, 0xFB, 0xE5, 0x98, 0xAE, 0x5D, 0xF8, 0xE8, 0xDA, 0xA1, 0xB6, 0x43, 0x0C,
0x6D, 0x1C, 0x39, 0x59, 0xE1, 0xBF, 0xEB, 0xA6, 0x4D, 0xBF, 0x12, 0x0E, 0x6E,
0xC4, 0x93, 0x8B, 0x72, 0x54, 0x47, 0xBE, 0xFC, 0x3A, 0x00, 0x7F, 0xD3, 0x57,
0x32, 0xE7, 0x86, 0xF0, 0x96, 0xCC, 0x06, 0x8F, 0x73, 0x9C, 0xE6, 0x8D, 0xD8,
0xB8, 0x24, 0xF9, 0xC0, 0x51, 0x99, 0xB8, 0x35, 0x98, 0x37, 0x32, 0x35, 0x03,
0x5C, 0xDA, 0x91, 0xC9, 0x6A, 0x50, 0xE5, 0xE1, 0xF0, 0xEF, 0xBB, 0x66, 0x27,
0x91, 0x51, 0x57, 0x09, 0xBB, 0x5B, 0xE9, 0x26, 0x8E, 0xB9, 0x75, 0xD9, 0x2E,
0x80, 0xE2, 0xDD, 0x27, 0xDD, 0x5A, 0x1B, 0x4E, 0xCF, 0x17, 0x11, 0x2B, 0x7B,
0xCB, 0xF9, 0xB3, 0xED, 0x07, 0xF3, 0x5A, 0xEE, 0xBF, 0x4B, 0x07, 0x43, 0x73,
0xF8, 0x24, 0x16, 0x67, 0x41, 0xE9, 0x64, 0xB4, 0xE7, 0x05, 0x72, 0x91, 0xF7,
0xCE, 0x38, 0x7D, 0x38, 0xA5, 0x60, 0x95, 0xC1, 0xC7, 0x64, 0x1B, 0xCC, 0xC4,
0x12, 0x32, 0xC3, 0x49, 0x7E, 0xAB, 0x96, 0x1D, 0x2A, 0x3C, 0x60, 0x51, 0xAA,
0x62, 0x86, 0xF3, 0x9F, 0xC6, 0x7F, 0xAB, 0x0F, 0xBB, 0x15, 0x7B, 0xBA, 0x43,
0x26, 0xAE, 0x37, 0x45, 0x5F, 0x39, 0x70, 0xB7, 0x19, 0x2F, 0x02, 0x33, 0xF1,
0x11, 0x4E, 0x78, 0x7D, 0x17, 0x8F, 0xBF, 0xEB, 0x92, 0xCC, 0x2F, 0xCA, 0x87,
0x01, 0xA8, 0xE3, 0xAD, 0x7B, 0x4A, 0x44, 0x0C, 0x75, 0x5A, 0x31, 0xCA, 0xE1,
0xE6, 0x18, 0xD7, 0xC4, 0xA3, 0xBA, 0x7F, 0xB5, 0xBC, 0xFD, 0xA6, 0x9C, 0xDC,
0x2A, 0xEB, 0x18, 0xDC, 0x88, 0x08, 0x6E, 0x7D, 0x6A, 0x97, 0xB6, 0xCD, 0x53,
0x41, 0x1D, 0xB4, 0xA8, 0xBD, 0xE3, 0x85, 0x29, 0x5F, 0x12, 0x03, 0xB8, 0x09,
0x13, 0x20, 0x6D, 0x68, 0x4F, 0x80, 0x1E, 0xBB, 0x6C, 0xD6, 0x51, 0x8C, 0x46,
0x19, 0x00, 0xBB, 0x90, 0xF9, 0xEA, 0xB0, 0x33, 0xF4, 0x52, 0xCA, 0x19, 0xD6,
0x68, 0xAE, 0x79, 0xE2, 0xC1, 0x39, 0xA9, 0x18, 0xF2, 0x26, 0x71, 0x69, 0xFF,
0xBA, 0x97, 0x28, 0x34, 0x4D, 0x10, 0x01, 0xFB, 0xD7, 0xBA, 0x37, 0x0F, 0xC8,
0xFC, 0x07, 0x7A, 0xCD, 0x1A, 0xDD, 0x92, 0x0D, 0x45, 0x8A, 0x7B, 0x6F, 0x94,
0x00, 0x53, 0x7E, 0xAF, 0xA5, 0x99, 0xB9, 0x7F, 0x00, 0xCD, 0xC7, 0x7C, 0x35,
0xCE, 0x53, 0x64, 0x15, 0xC2, 0x47, 0x7C, 0xD1, 0x12, 0x40, 0xBD, 0xF9, 0x8B,
0xBA, 0x3B, 0x5A, 0x3D, 0xFF, 0x5C, 0x48, 0x3A, 0x7F, 0xEF, 0x5B, 0xA8, 0xFC,
0xD6, 0xEA, 0xFB, 0x49, 0x0B, 0x29, 0x98, 0x5F, 0xCA, 0xBC, 0xC1, 0xD5, 0xA8,
0x15, 0x5B, 0x09, 0xEF, 0xB3, 0x0E, 0x41, 0xDC, 0x4D, 0x22, 0x30, 0xEE, 0xAA,
0xD9, 0xBA, 0x37, 0x43, 0xDE, 0x34, 0xF8, 0xB9, 0x42, 0xE7, 0x65, 0xEC, 0xE6,
0xA3, 0xE1, 0xED, 0x46, 0x46, 0xB4, 0x9F, 0x1C, 0xA0, 0x61, 0x50, 0x8E, 0x8A,
0x61, 0xBC, 0xF1, 0x3A, 0x55, 0xF8, 0xAB, 0xBA, 0x09, 0x5A, 0x4F, 0xB1, 0x38,
0x99, 0x77, 0x0A, 0xF5, 0x5D, 0xF7, 0xA0, 0x29, 0xA5, 0x00, 0x1D, 0x92, 0xC1,
0xA8, 0x4A, 0x73, 0x13, 0xCB, 0x1F, 0x14, 0xB0, 0xDB, 0x64, 0x53, 0xA8, 0x77,
0xB1, 0x80, 0xDF, 0xA7, 0x20, 0x9A, 0xA3, 0xD1, 0x79, 0x4B, 0x75, 0x45, 0x6D,
0xB0, 0xF5, 0xD8, 0x09, 0xE3, 0xB7, 0x7C, 0xC8, 0x1B, 0x56, 0xA2, 0x04, 0x11,
0xFB, 0xAC, 0x2D, 0x55, 0xF3, 0x95, 0x36, 0xF2, 0xAE, 0x6E, 0x9F, 0x10, 0xFE,
0xC0, 0xD5, 0x62, 0x36, 0xA7, 0xA0, 0xC5, 0x05, 0x2F, 0x55, 0x79, 0x59, 0x1B,
0xF4, 0xF6, 0xC3, 0xD2, 0x77, 0x96, 0x35, 0xBF, 0x89, 0x33, 0x45, 0xE9, 0xAB,
0x0A, 0x4B, 0xE1, 0x42, 0x31, 0xAF, 0x38, 0xA2, 0xA9, 0x45, 0xCF, 0x7D, 0x02,
0x88, 0x77, 0x4B, 0xD0, 0x2D, 0x9B, 0x56, 0x6E, 0xC3, 0xB3, 0x61, 0xA8, 0x1F,
0x8B, 0x9C, 0x3F, 0x63, 0xD4, 0x3C, 0x88, 0xA0, 0x7B, 0x90, 0xDB, 0x02, 0x30,
0xC5, 0xE8, 0x68, 0x82, 0x28, 0x58, 0x40, 0x31, 0xA3, 0x5C, 0xE9, 0xFB, 0x2A,
0xE6, 0x6E, 0x8F, 0x49, 0x5B, 0xF6, 0xAC, 0xB5, 0xBF, 0x30, 0xA8, 0x68, 0x83,
0x5E, 0xB4, 0x26, 0xBF, 0x6D, 0x1F, 0xEC, 0xEB, 0x00, 0xBD, 0x12, 0x0D, 0xB9,
0x80, 0xF1, 0xE7, 0x13, 0x3B, 0xCA, 0x81, 0x98, 0x5C, 0xE8, 0xA1, 0x98, 0xA1,
0x82, 0x26, 0x5F, 0xDD, 0xE0, 0xAE, 0xF8, 0x0C, 0x63, 0x78, 0xA8, 0xC1, 0xF7,
0x20, 0x62, 0x0B, 0xC8, 0xF9, 0xE5, 0x89, 0x43, 0x44, 0x05, 0x56, 0x98, 0xDE,
0xFD, 0x99, 0x25, 0xC0, 0x33, 0xCA, 0x1C, 0xDD, 0xAE, 0x2F, 0xDF, 0x14, 0x7E,
0xE2, 0x75, 0x75, 0xBC, 0x1C, 0x81, 0xF7, 0x21, 0x07, 0x0E, 0x21, 0x4A, 0x41,
0x4F, 0x33, 0xBD, 0x00, 0x5D, 0xBD, 0xF1, 0x79, 0x0C, 0x15, 0x8C, 0x98, 0x06,
0x72, 0xB8, 0xC2, 0xC1, 0x29, 0xFB, 0x7E, 0xE5, 0xF4, 0x04, 0x49, 0x17, 0xFD,
0x4B, 0xE5, 0xC7, 0x03, 0xFA, 0x88, 0x81, 0xBF, 0xDB, 0x10, 0xE2, 0x37, 0x12,
0x9E, 0x63, 0x7D, 0xFA, 0xBC, 0xF6, 0x98, 0x12, 0x23, 0x99, 0x59, 0xE3, 0x30,
0xD0, 0xA8, 0x21, 0x6D, 0x80, 0x2A, 0xF4, 0xB9, 0x6D, 0x71, 0x62, 0x0B, 0xA7,
0x99, 0xB2, 0xA1, 0x60, 0x34, 0xC5, 0x7F, 0xC3, 0x59, 0x78, 0xED, 0xB4, 0xA6,
0x5E, 0xF8, 0xC8, 0x5E, 0xF6, 0x69, 0xCE, 0xA0, 0x98, 0x87, 0x79, 0xDB, 0xB8,
0xA2, 0x3C, 0x94, 0xAC, 0xD1, 0x4C, 0x6C, 0x72, 0x39, 0x17, 0x32, 0x78, 0xA1,
0xDC, 0x1D, 0x03, 0xB2, 0xA1, 0x57, 0x0D, 0x2F, 0xA7, 0xF4, 0x8D, 0xE8, 0x4C,
0x67, 0x95, 0x19, 0x95, 0x55, 0xB9, 0xDE, 0x38, 0xD0, 0x85, 0xDB, 0x15, 0xB8,
0x8C, 0x0F, 0x6A, 0x69, 0x38, 0xF6, 0x8B, 0x75, 0x81, 0x89, 0x7E, 0xF8, 0x3A,
0xF3, 0x27, 0x08, 0xC0, 0x7B, 0x78, 0x3A, 0x73, 0xA5, 0xCB, 0xB0, 0x67, 0xD7,
0xDF, 0x88, 0x84, 0x4A, 0x52, 0xBD, 0x91, 0x74, 0x2C, 0xD1, 0x16, 0x3A, 0xCB,
0x0D, 0x3D, 0x08, 0x3D, 0x4F, 0x58, 0xE6, 0xCB, 0x32, 0x8A, 0x52, 0x86, 0x82,
0x61, 0x00, 0xDE, 0xCA, 0xF3, 0xDE, 0x05, 0xAB, 0x15, 0xAE, 0x13, 0x35, 0x4A,
0xE2, 0x45, 0xD5, 0xC1, 0xB0, 0x1B, 0xFA, 0xD8, 0xAD, 0xF7, 0xD2, 0x9A, 0x53,
0x06, 0x79, 0x15, 0xA6, 0x95, 0xE0, 0x6C, 0xC7, 0xFA, 0x94, 0x81, 0xB4, 0x91,
0x9D, 0x53, 0x89, 0x2D, 0x59, 0x74, 0x9F, 0x0F, 0xD5, 0x4E, 0xE6, 0xF6, 0x07,
0x62, 0x3B, 0x2C, 0x59, 0xA0, 0x47, 0x52, 0xDF, 0xF4, 0x10, 0xC2, 0xEB, 0x38,
0x86, 0x2F, 0x42, 0x01, 0xC2, 0x8A, 0xCB, 0x20, 0x7B, 0xFC, 0xB8, 0xEA, 0x20,
0x14, 0x69, 0x8B, 0x63, 0x52, 0xA8, 0x13, 0x1D, 0xD4, 0x60, 0x32, 0xF6, 0xDE,
0x75, 0x4D, 0x41, 0xC2, 0xC7, 0xA2, 0x62, 0x6F, 0x04, 0xAF, 0xF9, 0x9E, 0x3D,
0x1C, 0xCB, 0xBB, 0xEC, 0x7A, 0xFD, 0x9C, 0x97, 0x87, 0x40, 0xF1, 0xE7, 0x91,
0xCD, 0x36, 0xD2, 0x64, 0xB1, 0x2B, 0x43, 0xBA, 0x6E, 0xBD, 0x0E, 0x7D, 0xB1,
0x45, 0xA4, 0x0B, 0x84, 0xEB, 0x18, 0x5C, 0x25, 0x8B, 0x9B, 0x62, 0xB3, 0x8C,
0x95, 0xEF, 0x6F, 0x09, 0xE9, 0xF8, 0xE8, 0x18, 0x1A, 0x8A, 0xE2, 0xCC, 0x48,
0xDC, 0xC6, 0xDC, 0x94, 0xB1, 0x24, 0x55, 0x13, 0xB6, 0xD8, 0x16, 0xAB, 0x5F,
0x20, 0x7F, 0x5E, 0x35, 0x1F, 0x5A, 0x56, 0x2C, 0xFF, 0x02, 0x9C, 0xAF, 0x18,
0xF8, 0xBB, 0x60, 0xE1, 0xD4, 0xEF, 0x5E, 0x03, 0x08, 0x07, 0xCD, 0x29, 0x35,
0x7B, 0x9F, 0xEC, 0x35, 0xDB, 0x1D, 0xE1, 0xFD, 0x85, 0xC3, 0xDB, 0xE0, 0x58,
0x1F, 0x39, 0xE9, 0x38, 0xAE, 0x37, 0x18, 0xAF, 0x9C, 0x11, 0x97, 0x97, 0x6B,
0x67, 0x46, 0xC8, 0x68, 0xB7, 0x65, 0x05, 0x20, 0x02, 0x70, 0xDA, 0x6B, 0xC7,
0x34};

// https://datatracker.ietf.org/doc/draft-ietf-lamps-dilithium-certificates/06/
// C.2.  Example Public Key
const char *mldsa_44_pub_pem_str =
"-----BEGIN PUBLIC KEY-----\n"
"MIIFMjALBglghkgBZQMEAxEDggUhANeytHJUquDbReeTDUqY0sl9jxOX0Xidr6Fw\n"
"JLMW6b7JT8mUbULxm3mnQTu6oz5xSctC7VEVaTrAQfrLmIretf4OHYYxGEmVtZLD\n"
"l9IpTi4U+QqkFLo4JomaxD9MzKy8JumoMrlRGNXLQzy++WYLABOOCBf2HnYsonTD\n"
"atVU6yKqwRYuSrAay6HjjE79j4C2WzM9D3LlXf5xzpweu5iJ58VhBsD9c4A6Kuz+\n"
"r97XqjyyztpU0SvYzTanjPl1lDtHq9JeiArEUuV0LtHo0agq+oblkMdYwVrk0oQN\n"
"kryhpQkPQElll/yn2LlRPxob2m6VCqqY3kZ1B9Sk9aTwWZIWWCw1cvYu2okFqzWB\n"
"ZwxKAnd6M+DKcpX9j0/20aCjp2g9ZfX19/xg2gI+gmxfkhRMAvfRuhB1mHVT6pNn\n"
"/NdtmQt/qZzUWv24g21D5Fn1GH3wWEeXCaAepoNZNfpwRgmQzT3BukAbqUurHd5B\n"
"rGerMxncrKBgSNTE7vJ+4TqcF9BTj0MPLWQtwkFWYN54h32NirxyUjl4wELkKF9D\n"
"GYRsRBJiQpdoRMEOVWuiFbWnGeWdDGsqltOYWQcf3MLN51JKe+2uVOhbMY6FTo/i\n"
"svPt+slxkSgnCq/R5QRMOk/a/Z/zH5B4S46ORZYUSg2vWGUR09mWK56pWvGXtOX8\n"
"YPKx7RXeOlvvX4m9x52RBR2bKBbnT6VFMe/cHL501EiFf0drzVjyHAtlOzt2pOB2\n"
"plWaMCcYVVzGP3SFmqurkl8COGHKjND3utsocfZ9VTJtdFETWtRfShumkRj7ssij\n"
"DuyTku8/l3Bmya3VxxDMZHsVFNIX2VjHAXw+kP0gwE5nS5BIbpNwoxoAHTL0c5ee\n"
"SQZ0nn5Hf6C3RQj4pfI3gxK4PCW9OIygsP/3R4uvQrcWZ+2qyXxGsSlkPlhuWwVa\n"
"DCEZRtTzbmdb7Vhg+gQqMV2YJhZNapI3w1pfv0lUkKW9TfJIuVxKrneEtgVnMWas\n"
"QkW1tLCCoJ6TI+YvIHjFt2eDRG3v1zatOjcC1JsImESQCmGDM5e8RBmzDXqXoLOH\n"
"wZEUdMTUG1PjKpd6y28Op122W7OeWecB52lX3vby1EVZwxp3EitSBOO1whnxaIsU\n"
"7QvAuAGz5ugtzUPpwOn0F0TNmBW9G8iCDYuxI/BPrNGxtoXdWisbjbvz7ZM2cPCV\n"
"oYC08ZLQixC4+rvfzCskUY4y7qCl4MkEyoRHgAg/OwzS0Li2r2e8NVuUlAJdx7Cn\n"
"j6gOOi2/61EyiFHWB4GY6Uk2Ua54fsAlH5Irow6fUd9iptcnhM890gU5MXbfoySl\n"
"Er2Ulwo23TSlFKhnkfDrNvAUWwmrZGUbSgMTsplhGiocSIkWJ1mHaKMRQGC6RENI\n"
"bfUVIqHOiLMJhcIW+ObtF43VZ7MEoNTK+6iCooNC8XqaomrljbYwCD0sNY/fVmw/\n"
"XWKkKFZ7yeqM6VyqDzVHSwv6jzOaJQq0388gg76O77wQVeGP4VNw7ssmBWbYP/Br\n"
"IRquxDyim1TM0A+IFaJGXvC0ZRXMfkHzEk8J7/9zkwmrWLKaFFmgC85QOOk4yWeP\n"
"cusOTuX9quZtn4Vz/Jf8QrSVn0v4th14Qz6GsDNdbpGRxNi/SHs5BcEIz9asJLDO\n"
"t9y3z1H4TQ7Wh7lerrHFM8BvDZcCPZKnCCWDe1m6bLfU5WsKh8IDhiro8xW6WSXo\n"
"7e+meTaaIgJ2YVHxapZfn4Hs52zAcLVYaeTbl4TPBcgwsyQsgxI=\n"
"-----END PUBLIC KEY-----\n";

const char *mldsa_65_pub_pem_str =
"-----BEGIN PUBLIC KEY-----\n"
"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\n"
"HgLy6ERP\n"
"-----END PUBLIC KEY-----\n";

const char *mldsa_87_pub_pem_str =
"-----BEGIN PUBLIC KEY-----\n"
"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\n"
"5VvgYiIvi6kKl0BzMmsxISrs4KNKYA==\n"
"-----END PUBLIC KEY-----\n";

// https://datatracker.ietf.org/doc/draft-ietf-lamps-dilithium-certificates/06/
// C.1.  Example Private Key
const char *mldsa_44_priv_pem_str =
"-----BEGIN PRIVATE KEY-----\n"
"MDQCAQAwCwYJYIZIAWUDBAMRBCKAIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ\n"
"GhscHR4f\n"
"-----END PRIVATE KEY-----\n";

const char *mldsa_65_priv_pem_str =
"-----BEGIN PRIVATE KEY-----\n"
"MDQCAQAwCwYJYIZIAWUDBAMSBCKAIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ\n"
"GhscHR4f\n"
"-----END PRIVATE KEY-----\n";

const char *mldsa_87_priv_pem_str =
"-----BEGIN PRIVATE KEY-----\n"
"MDQCAQAwCwYJYIZIAWUDBAMTBCKAIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ\n"
"GhscHR4f\n"
"-----END PRIVATE KEY-----\n";

struct PQDSATestVector {
  const char name[20];
  const int nid;
  const size_t public_key_len;
  const size_t private_key_len;
  const size_t signature_len;
  const char *kat_filename;
  const uint8_t *kPublicKey;
  const uint8_t *kPublicKeySPKI;
  const size_t kPublicKeySPKI_len;
  const char *public_pem_str;
  const char *private_pem_str;

  int (*keygen)(uint8_t *public_key, uint8_t *private_key, const uint8_t *seed);

  int (*sign)(const uint8_t *private_key,
              uint8_t *sig, size_t *sig_len,
              const uint8_t *message, size_t message_len,
              const uint8_t *pre, size_t pre_len,
              const uint8_t *rnd);

  int (*verify)(const uint8_t *public_key,
                const uint8_t *sig, size_t sig_len,
                const uint8_t *message, size_t message_len,
                const uint8_t *pre, size_t pre_len);

  int (*pack_key)(uint8_t *public_key, const uint8_t *private_key);
};


#define CMP_VEC_AND_PTR(vec, ptr, len)         \
          {                                    \
            std::vector<uint8_t> tmp(len);     \
            tmp.assign(ptr, ptr + len);        \
            EXPECT_EQ(Bytes(vec), Bytes(tmp)); \
          }

#define CMP_VEC_AND_PKEY_PUBLIC(vec, pkey, len) \
CMP_VEC_AND_PTR(vec, pkey->pkey.pqdsa_key->public_key, len)

#define CMP_VEC_AND_PKEY_SECRET(vec, pkey, len) \
CMP_VEC_AND_PTR(vec, pkey->pkey.pqdsa_key->private_key, len)

#define GET_ERR_AND_CHECK_REASON(reason)              \
          {                                           \
            uint32_t err = ERR_get_error();           \
            EXPECT_EQ(ERR_LIB_EVP, ERR_GET_LIB(err)); \
            EXPECT_EQ(reason, ERR_GET_REASON(err));   \
          }


static const struct PQDSATestVector parameterSet[] = {
  {
    "MLDSA44",
    NID_MLDSA44,
    1312,
    2560,
    2420,
    "ml_dsa/kat/MLDSA_44_hedged_pure.txt",
    mldsa44kPublicKey,
    mldsa44kPublicKeySPKI,
    1334,
    mldsa_44_pub_pem_str,
    mldsa_44_priv_pem_str,
    ml_dsa_44_keypair_internal,
    ml_dsa_44_sign_internal,
    ml_dsa_44_verify_internal,
    ml_dsa_44_pack_pk_from_sk,
  },
  {
    "MLDSA65",
    NID_MLDSA65,
    1952,
    4032,
    3309,
    "ml_dsa/kat/MLDSA_65_hedged_pure.txt",
    mldsa65kPublicKey,
    mldsa65kPublicKeySPKI,
    1974,
    mldsa_65_pub_pem_str,
    mldsa_65_priv_pem_str,
    ml_dsa_65_keypair_internal,
    ml_dsa_65_sign_internal,
    ml_dsa_65_verify_internal,
    ml_dsa_65_pack_pk_from_sk
  },
  {
    "MLDSA87",
    NID_MLDSA87,
    2592,
    4896,
    4627,
    "ml_dsa/kat/MLDSA_87_hedged_pure.txt",
    mldsa87kPublicKey,
    mldsa87kPublicKeySPKI,
    2614,
    mldsa_87_pub_pem_str,
    mldsa_87_priv_pem_str,
    ml_dsa_87_keypair_internal,
    ml_dsa_87_sign_internal,
    ml_dsa_87_verify_internal,
    ml_dsa_87_pack_pk_from_sk
  },
};

class PQDSAParameterTest : public testing::TestWithParam<PQDSATestVector> {};

INSTANTIATE_TEST_SUITE_P(All, PQDSAParameterTest, testing::ValuesIn(parameterSet),
                         [](const testing::TestParamInfo<PQDSATestVector> &params)
                             -> std::string { return params.param.name; });

TEST_P(PQDSAParameterTest, KAT) {
  std::string kat_filepath = "crypto/fipsmodule/";
  kat_filepath += GetParam().kat_filename;

  FileTestGTest(kat_filepath.c_str(), [&](FileTest *t) {
    std::string count, mlen, smlen;
    std::vector<uint8_t> xi, rng, seed, msg, pk, sk, sm, ctxstr;

    ASSERT_TRUE(t->GetAttribute(&count, "count"));
    ASSERT_TRUE(t->GetBytes(&xi, "xi"));
    ASSERT_TRUE(t->GetBytes(&rng, "rng"));
    ASSERT_TRUE(t->GetBytes(&seed, "seed"));
    ASSERT_TRUE(t->GetBytes(&pk, "pk"));
    ASSERT_TRUE(t->GetBytes(&sk, "sk"));
    ASSERT_TRUE(t->GetBytes(&msg, "msg"));
    ASSERT_TRUE(t->GetAttribute(&mlen, "mlen"));
    ASSERT_TRUE(t->GetBytes(&sm, "sm"));
    ASSERT_TRUE(t->GetAttribute(&smlen, "smlen"));
    ASSERT_TRUE(t->GetBytes(&ctxstr, "ctx"));

    size_t pk_len = GetParam().public_key_len;
    size_t sk_len = GetParam().private_key_len;
    size_t sig_len = GetParam().signature_len;

    std::vector<uint8_t> pub(pk_len);
    std::vector<uint8_t> priv(sk_len);
    std::vector<uint8_t> signature(sig_len);

    std::string name = GetParam().name;
    size_t mlen_int = std::stoi(mlen);

    // The KATs provide the signed message, which is the signature appended with
    // the message that was signed. We use the ML-DSA APIs for sign_signature
    // and not sign_message, which return the signature without the appended
    // message, so we truncate the signed messaged to |sig_len|.
    sm.resize(sig_len);

    // Generate key pair from seed xi and assert that public and private keys
    // are equal to expected values from KAT
    ASSERT_TRUE(GetParam().keygen(pub.data(), priv.data(), xi.data()));
    EXPECT_EQ(Bytes(pub), Bytes(pk));
    EXPECT_EQ(Bytes(priv), Bytes(sk));

    // Prepare m_prime = (0 || ctxlen || ctx)
    // See both FIPS 204: Algorithm 2 line 10 and FIPS 205: Algorithm 22 line 8
    uint8_t m_prime[257];
    size_t m_prime_len = ctxstr.size() + 2;
    m_prime[0] = 0;
    m_prime[1] = ctxstr.size();
    ASSERT_TRUE(ctxstr.size() <= 255);
    OPENSSL_memcpy(m_prime + 2 , ctxstr.data(), ctxstr.size());

    // Generate signature by signing |msg|.
    ASSERT_TRUE(GetParam().sign(priv.data(),
                                signature.data(), &sig_len,
                                msg.data(), mlen_int,
                                m_prime, m_prime_len,
                                rng.data()));

    // Assert that signature is equal to expected signature
    ASSERT_EQ(Bytes(signature), Bytes(sm));

    // Assert that the signature verifies correctly.
    ASSERT_TRUE(GetParam().verify(pub.data(),
                                  signature.data(), sig_len,
                                  msg.data(), mlen_int,
                                  m_prime, m_prime_len));
  });
}

TEST_P(PQDSAParameterTest, KeyGen) {
  // ---- 1. Test basic key generation flow ----
  // Create context of PQDSA type and a key pair
  bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new_id(EVP_PKEY_PQDSA, nullptr));
  ASSERT_TRUE(ctx);

  // Setup the context with specific PQDSA parameters.
  int nid = GetParam().nid;
  ASSERT_TRUE(EVP_PKEY_CTX_pqdsa_set_params(ctx.get(),nid));

  // Generate a key pair.
  EVP_PKEY *raw = nullptr;
  ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
  ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));
  ASSERT_TRUE(raw);
  bssl::UniquePtr<EVP_PKEY> pkey(raw);

  // ---- 2. Test key generation with PKEY as a template ----
  ctx.reset(EVP_PKEY_CTX_new(pkey.get(), nullptr));
  ASSERT_TRUE(ctx);

  // Generate a key pair.
  raw = nullptr;
  ASSERT_TRUE(EVP_PKEY_keygen_init(ctx.get()));
  ASSERT_TRUE(EVP_PKEY_keygen(ctx.get(), &raw));
  ASSERT_TRUE(raw);
  pkey.reset(raw);

  // ---- 3. Test getting raw keys and their size ----
  size_t pk_len, sk_len;

  // First getting the sizes only.
  ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), nullptr, &pk_len));
  ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), nullptr, &sk_len));
  EXPECT_EQ(pk_len, GetParam().public_key_len);
  EXPECT_EQ(sk_len, GetParam().private_key_len);

  // Then getting the keys and the sizes.
  std::vector<uint8_t> pk_raw(pk_len);
  std::vector<uint8_t> sk_raw(sk_len);
  ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), pk_raw.data(), &pk_len));
  ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), sk_raw.data(), &sk_len));
  EXPECT_EQ(pk_len, GetParam().public_key_len);
  EXPECT_EQ(sk_len, GetParam().private_key_len);

  // ---- 4. Test failure modes for EVP_PKEY_CTX_pqdsa_set_params. ----
  // ctx is NULL.
  ASSERT_FALSE(EVP_PKEY_CTX_pqdsa_set_params(nullptr, nid));
  GET_ERR_AND_CHECK_REASON(ERR_R_PASSED_NULL_PARAMETER);

  // ctx->data is NULL
  void *tmp = ctx.get()->data;
  ctx.get()->data = nullptr;
  ASSERT_FALSE(EVP_PKEY_CTX_pqdsa_set_params(ctx.get(), nid));
  GET_ERR_AND_CHECK_REASON(ERR_R_PASSED_NULL_PARAMETER);
  ctx.get()->data = tmp;

  // ctx->pkey is not NULL.
  ASSERT_FALSE(EVP_PKEY_CTX_pqdsa_set_params(ctx.get(), nid));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_OPERATION);

  // nid is not a PQDSA.
  tmp = (void*) ctx.get()->pkey;
  ctx.get()->pkey = nullptr;
  ASSERT_FALSE(EVP_PKEY_CTX_pqdsa_set_params(ctx.get(), NID_MLKEM768));
  GET_ERR_AND_CHECK_REASON(EVP_R_UNSUPPORTED_ALGORITHM);
  ctx.get()->pkey = (EVP_PKEY*) tmp;
}

// Helper function that:
// 1. Creates a |EVP_PKEY_CTX| object of type: EVP_PKEY_PQDSA.
// 2. Sets the specific PQDSA parameters according to the |pqdsa_nid| provided.
// 3. Generates a key pair.
// 4. Creates an EVP_PKEY object from the generated key (as a bssl::UniquePtr).
// 5. returns the PKEY.
static bssl::UniquePtr<EVP_PKEY> generate_key_pair(int pqdsa_nid) {

  EVP_PKEY_CTX *ctx = nullptr;
  EVP_PKEY *raw = nullptr;

  // Create the PQDSA contex.
  ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_PQDSA, nullptr);
  EXPECT_TRUE(ctx);

  // Set specific PQDSA params for this NID
  EXPECT_TRUE(EVP_PKEY_CTX_pqdsa_set_params(ctx, pqdsa_nid));

  // Generate a keypair
  EXPECT_TRUE(EVP_PKEY_keygen_init(ctx));
  EXPECT_TRUE(EVP_PKEY_keygen(ctx, &raw));

  // Create a new PKEY from the generated raw key
  bssl::UniquePtr<EVP_PKEY> pkey(raw);
  EVP_PKEY_CTX_free(ctx);
  return pkey;
}

TEST_P(PQDSAParameterTest, KeyCmp) {
  // Generate two PQDSA keys and check that they are not equal.
  const int nid = GetParam().nid;

  // Generate first keypair
  bssl::UniquePtr<EVP_PKEY> pkey1(generate_key_pair(nid));

  // Generate second keypair
  bssl::UniquePtr<EVP_PKEY> pkey2(generate_key_pair(nid));

  // Compare keys
  EXPECT_EQ(0, EVP_PKEY_cmp(pkey1.get(), pkey2.get()));
}

TEST_P(PQDSAParameterTest, KeySize) {
  // Test the key size of PQDSA key is as expected
  int nid = GetParam().nid;
  int pk_len = GetParam().public_key_len;
  int sig_len = GetParam().signature_len;

  bssl::UniquePtr<EVP_PKEY> pkey(generate_key_pair(nid));
  EXPECT_EQ(sig_len, EVP_PKEY_size(pkey.get()));
  EXPECT_EQ(8*(pk_len), EVP_PKEY_bits(pkey.get()));
}

TEST_P(PQDSAParameterTest, RawFunctions) {
  // ---- 1. Setup phase: generate PQDSA EVP KEY ----
  int nid = GetParam().nid;
  bssl::UniquePtr<EVP_PKEY> pkey(generate_key_pair(GetParam().nid));

  // ---- 2. Test the extraction of public and private key from a PKEY ----
  size_t pk_len = GetParam().public_key_len;
  size_t sk_len = GetParam().private_key_len;
  std::vector<uint8_t> pk(pk_len);
  std::vector<uint8_t> sk(sk_len);

  ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), pk.data(), &pk_len));
  ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), sk.data(), &sk_len));
  EXPECT_EQ(pk_len, GetParam().public_key_len);
  EXPECT_EQ(sk_len, GetParam().private_key_len);
  CMP_VEC_AND_PKEY_PUBLIC(pk, pkey, pk_len);
  CMP_VEC_AND_PKEY_SECRET(sk, pkey, sk_len);

  // Passing too large of a buffer is okay. The function will still only read
  // the correct number of bytes (defined by pqdsa->public_key_len and
  // pqdsa->private_key_len)
  pk_len = GetParam().public_key_len + 1;
  ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), pk.data(), &pk_len));
  CMP_VEC_AND_PKEY_PUBLIC(pk, pkey, pk_len);

  sk_len = GetParam().private_key_len + 1;
  ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), sk.data(), &sk_len));
  CMP_VEC_AND_PKEY_SECRET(sk, pkey, sk_len);

  // ---- 3. Test getting public/private key sizes ----
  pk_len = 0;
  sk_len = 0;
  ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), nullptr, &pk_len));
  ASSERT_TRUE(EVP_PKEY_get_raw_private_key(pkey.get(), nullptr, &sk_len));
  EXPECT_EQ(pk_len, GetParam().public_key_len);
  EXPECT_EQ(sk_len, GetParam().private_key_len);

  // ---- 4. Test creating PKEYs from raw data ----
  bssl::UniquePtr<EVP_PKEY>public_pkey(
    EVP_PKEY_pqdsa_new_raw_public_key(nid, pkey->pkey.pqdsa_key->public_key, pk_len));
  bssl::UniquePtr<EVP_PKEY> private_pkey(
    EVP_PKEY_pqdsa_new_raw_private_key(nid, pkey->pkey.pqdsa_key->private_key, sk_len));

  // check that public key is present and private key is not present in public_key
  ASSERT_NE(public_pkey, nullptr);
  EXPECT_NE(public_pkey->pkey.pqdsa_key->public_key, nullptr);
  EXPECT_EQ(public_pkey->pkey.pqdsa_key->private_key, nullptr);

  // check that calling EVP_PKEY_pqdsa_new_raw_private_key populates both the
  // public and private key
  ASSERT_NE(private_pkey, nullptr);
  EXPECT_NE(private_pkey->pkey.pqdsa_key->public_key, nullptr);
  EXPECT_NE(private_pkey->pkey.pqdsa_key->private_key, nullptr);

  // ---- 5. Test get_raw public/private failure modes ----
  std::vector<uint8_t> get_sk(sk_len);

  // Attempting to get a private key that is not present must fail correctly
  EXPECT_FALSE(EVP_PKEY_get_raw_private_key(public_pkey.get(), get_sk.data(), &sk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_NOT_A_PRIVATE_KEY);

  // Null PKEY must fail correctly.
  ASSERT_FALSE(EVP_PKEY_get_raw_public_key(nullptr, pk.data(), &pk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);

  ASSERT_FALSE(EVP_PKEY_get_raw_private_key(nullptr, sk.data(), &sk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);

  // Invalid PKEY (missing ameth) must fail correctly.
  void *tmp = (void*) pkey.get()->ameth;
  pkey.get()->ameth = nullptr;
  ASSERT_FALSE(EVP_PKEY_get_raw_public_key(pkey.get(), pk.data(), &pk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);

  ASSERT_FALSE(EVP_PKEY_get_raw_private_key(pkey.get(), sk.data(), &sk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
  pkey.get()->ameth = (const EVP_PKEY_ASN1_METHOD*)(tmp);

  // Invalid lengths
  pk_len = GetParam().public_key_len - 1;
  ASSERT_FALSE(EVP_PKEY_get_raw_public_key(pkey.get(), pk.data(), &pk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_BUFFER_TOO_SMALL);

  sk_len = GetParam().private_key_len - 1;
  ASSERT_FALSE(EVP_PKEY_get_raw_private_key(pkey.get(), sk.data(), &sk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_BUFFER_TOO_SMALL);

  // ---- 6. Test new_raw public/private failure modes  ----
  // Invalid lengths
  pk_len = GetParam().public_key_len - 1;
  ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_public_key(nid, pk.data(), pk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_BUFFER_SIZE);

  pk_len = GetParam().public_key_len + 1;
  ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_public_key(nid, pk.data(), pk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_BUFFER_SIZE);

  sk_len = GetParam().private_key_len - 1;
  ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_private_key(nid, sk.data(), sk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_BUFFER_SIZE);

  sk_len = GetParam().private_key_len + 1;
  ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_private_key(nid, sk.data(), sk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_BUFFER_SIZE);

  // Invalid nid
  ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_public_key(0, pk.data(), pk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_UNSUPPORTED_ALGORITHM);

  ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_private_key(0, pk.data(), pk_len));
  GET_ERR_AND_CHECK_REASON(EVP_R_UNSUPPORTED_ALGORITHM);

  // Invalid input buffer
  ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_public_key(nid, nullptr, pk_len));
  GET_ERR_AND_CHECK_REASON(ERR_R_PASSED_NULL_PARAMETER);

  ASSERT_FALSE(EVP_PKEY_pqdsa_new_raw_private_key(nid, nullptr, sk_len));
  GET_ERR_AND_CHECK_REASON(ERR_R_PASSED_NULL_PARAMETER);
}

TEST_P(PQDSAParameterTest, MarshalParse) {
  // ---- 1. Setup phase: generate a key ----
  int nid = GetParam().nid;
  bssl::UniquePtr<EVP_PKEY> pkey(generate_key_pair(nid));

  // ---- 2. Test encode (marshal) and decode (parse) of public key ----
  // The public key must encode properly.
  bssl::ScopedCBB cbb;
  uint8_t *der;
  size_t der_len;
  ASSERT_TRUE(CBB_init(cbb.get(), 0));
  ASSERT_TRUE(EVP_marshal_public_key(cbb.get(), pkey.get()));
  ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len));
  bssl::UniquePtr<uint8_t> free_der(der);

  // The public key must parse properly.
  CBS cbs;
  CBS_init(&cbs, der, der_len);
  bssl::UniquePtr<EVP_PKEY> pub_pkey_from_der(EVP_parse_public_key(&cbs));
  ASSERT_TRUE(pub_pkey_from_der.get());
  EXPECT_EQ(1, EVP_PKEY_cmp(pkey.get(), pub_pkey_from_der.get()));

  // ---- 3. Test encode (marshal) and decode (parse) of private key ----
  // The private key must encode properly.
  ASSERT_TRUE(CBB_init(cbb.get(), 0));
  ASSERT_TRUE(EVP_marshal_private_key(cbb.get(), pkey.get()));
  ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len));
  free_der.reset(der);

  // The private key must parse properly.
  CBS_init(&cbs, der, der_len);
  bssl::UniquePtr<EVP_PKEY> priv_pkey_from_der(EVP_parse_private_key(&cbs));
  ASSERT_TRUE(priv_pkey_from_der);
  EXPECT_EQ(Bytes(priv_pkey_from_der->pkey.pqdsa_key->private_key, GetParam().private_key_len),
            Bytes(pkey->pkey.pqdsa_key->private_key, GetParam().private_key_len));

  // When importing a PQDSA private key, the public key will be calculated and
  // used to populate the public key. To test the calculated key is correct,
  // we first check that the public key has been populated, then test for equality
  // with the expected public key:
  ASSERT_NE(priv_pkey_from_der, nullptr);
  EXPECT_NE(priv_pkey_from_der->pkey.pqdsa_key->public_key, nullptr);
  EXPECT_NE(priv_pkey_from_der->pkey.pqdsa_key->private_key, nullptr);

  EXPECT_EQ(Bytes(priv_pkey_from_der->pkey.pqdsa_key->public_key, GetParam().public_key_len),
            Bytes(pkey->pkey.pqdsa_key->public_key, GetParam().public_key_len));
}

TEST_P(PQDSAParameterTest, SIGOperations) {
  // ---- 1. Setup phase: generate PQDSA EVP KEY and sign/verify contexts ----
  bssl::UniquePtr<EVP_PKEY> pkey(generate_key_pair(GetParam().nid));
  bssl::ScopedEVP_MD_CTX md_ctx, md_ctx_verify;

 // msg2 differs from msg1 by one byte
  std::vector<uint8_t> msg1 = {
      0x4a, 0x41, 0x4b, 0x45, 0x20, 0x4d, 0x41, 0x53, 0x53, 0x49,
      0x4d, 0x4f, 0x20, 0x41, 0x57, 0x53, 0x32, 0x30, 0x32, 0x32, 0x2e};
  std::vector<uint8_t> msg2 = {
      0x4a, 0x41, 0x4b, 0x45, 0x20, 0x4d, 0x41, 0x53, 0x53, 0x49,
      0x4d, 0x4f, 0x20, 0x41, 0x57, 0x53, 0x32, 0x30, 0x32, 0x31, 0x2e};

  // ---- 2. Test signature round trip (sign + verify) ----

  // Initalize the signing context |md_ctx| with the |pkey| we generated
  ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, nullptr, nullptr, pkey.get()));

  // To sign, we first need to allocate memory for the signature. We call
  // EVP_DigestSign with sig = nullptr to indicate that we are doing a size check
  // on the signature size. The variable |sig_len| will be returned with the
  // correct signature size, so we can allocate memory.
  size_t sig_len = 0;
  ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), nullptr, &sig_len, msg1.data(), msg1.size()));

  // Verify that the returned signature size is as expected
  ASSERT_EQ(sig_len, GetParam().signature_len);

  // Allocate memory for the signature and sign first message; msg1
  std::vector<uint8_t> sig1(sig_len);
  ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), sig1.data(), &sig_len, msg1.data(), msg1.size()));

  // Verify the correct signed message
  ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx_verify.get(), nullptr, nullptr, nullptr, pkey.get()));
  ASSERT_TRUE(EVP_DigestVerify(md_ctx_verify.get(), sig1.data(), sig_len, msg1.data(), msg1.size()));

  // ---- 3. Test signature failure modes: incompatible messages/signatures ----
  // Check that the verification of signature1 fails for a different message; msg2
  ASSERT_FALSE(EVP_DigestVerify(md_ctx_verify.get(), sig1.data(), sig_len, msg2.data(), msg2.size()));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE);

  // reset the contexts between tests
  md_ctx.Reset();
  md_ctx_verify.Reset();

  // PQDSA signature schemes can be either in randomized (every signature on a
  // fixed message is different) or in deterministic mode (every signature is
  // the same). We currently support randomized signatures (as they are preferable),
  // thus, signing the same message twice should result in unique signatures.
  std::vector<uint8_t> sig3(sig_len);
  ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, nullptr, nullptr, pkey.get()));
  ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), sig3.data(), &sig_len, msg1.data(), msg1.size()));
  EXPECT_NE(0, OPENSSL_memcmp(sig1.data(), sig3.data(), sig_len));

  // Sign a different message, msg2 and verify that  the signature for
  // msg1 is not the same as the signature for msg2.
  std::vector<uint8_t> sig2(sig_len);
  ASSERT_TRUE(EVP_DigestSignInit(md_ctx.get(), nullptr, nullptr, nullptr, pkey.get()));
  ASSERT_TRUE(EVP_DigestSign(md_ctx.get(), sig2.data(), &sig_len, msg2.data(), msg2.size()));
  EXPECT_NE(0, OPENSSL_memcmp(sig1.data(), sig2.data(), sig_len));

  // Check that the signature for msg2 fails to verify with msg1
  ASSERT_FALSE(EVP_DigestVerify(md_ctx.get(), sig2.data(), sig_len, msg1.data(), msg1.size()));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE);

  md_ctx.Reset();
  md_ctx_verify.Reset();

  // ---- 4. Test signature failure modes: invalid keys and signatures ----
  // Check that verification fails upon providing a different public key
  // than the one that was used to sign.
  bssl::UniquePtr<EVP_PKEY> new_pkey(generate_key_pair(GetParam().nid));
  ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx_verify.get(), nullptr, nullptr, nullptr, new_pkey.get()));
  ASSERT_FALSE(EVP_DigestVerify(md_ctx_verify.get(), sig1.data(), sig_len, msg1.data(), msg1.size()));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE);

  // Check that verification fails upon providing a signature of invalid length
  sig_len = GetParam().signature_len - 1;
  ASSERT_FALSE(EVP_DigestVerify(md_ctx_verify.get(), sig1.data(), sig_len, msg1.data(), msg1.size()));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE);

  sig_len = GetParam().signature_len + 1;
  ASSERT_FALSE(EVP_DigestVerify(md_ctx_verify.get(), sig1.data(), sig_len, msg1.data(), msg1.size()));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE);

  md_ctx.Reset();
  md_ctx_verify.Reset();
}

TEST_P(PQDSAParameterTest, ParsePublicKey) {
  // Test the example public key kPublicKey encodes correctly as kPublicKeySPKI
  // Public key version of d2i_PrivateKey as part of the EVPExtraTest Gtest

  // ---- 1. Setup phase: generate PQDSA key from raw ----
  int nid = GetParam().nid;
  size_t pk_len = GetParam().public_key_len;
  const uint8_t * kPublicKey = GetParam().kPublicKey;
  const uint8_t * kPublicKeySPKI = GetParam().kPublicKeySPKI;
  size_t kPublicKeySPKI_len = GetParam().kPublicKeySPKI_len;

  bssl::UniquePtr<EVP_PKEY> pkey_pk_new(EVP_PKEY_pqdsa_new_raw_public_key(nid, kPublicKey, pk_len));
  ASSERT_TRUE(pkey_pk_new);

  // ---- 2. Encode the public key as DER ----
  bssl::ScopedCBB cbb;
  uint8_t *der;
  size_t der_len;
  ASSERT_TRUE(CBB_init(cbb.get(), 0));
  ASSERT_TRUE(EVP_marshal_public_key(cbb.get(), pkey_pk_new.get()));
  ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len));
  bssl::UniquePtr<uint8_t> free_der(der);

  // ---- 3. Verify that the public key encodes as expected ----
  EXPECT_EQ(Bytes(kPublicKeySPKI, kPublicKeySPKI_len), Bytes(der, der_len));

  // ---- 4. Decode the DER structure, then parse as a PKEY ----
  CBS cbs;
  CBS_init(&cbs, der, der_len);
  bssl::UniquePtr<EVP_PKEY> pkey_from_der(EVP_parse_public_key(&cbs));
  ASSERT_TRUE(pkey_from_der);
}

// Helper function that:
// 1. Creates a BIO
// 2. Reads the provided |pem_string| into bio
// 3. Reads the PEM into DER encoding
// 4. Returns the DER data and length
static bool PEM_to_DER(const char* pem_str, uint8_t** out_der, long* out_der_len) {
  char *name = nullptr;
  char *header = nullptr;

  // Create BIO from memory
  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem_str, strlen(pem_str)));
  if (!bio) {
    return false;
  }

  // Read PEM into DER
  if (PEM_read_bio(bio.get(), &name, &header, out_der, out_der_len) <= 0) {
    OPENSSL_free(name);
    OPENSSL_free(header);
    OPENSSL_free(*out_der);
    *out_der = nullptr;
    return false;
  }

  OPENSSL_free(name);
  OPENSSL_free(header);
  return true;
}

TEST_P(PQDSAParameterTest, ParsePrivateKey) {
  // ---- 1. Setup phase: parse provided public/private from PEM strings ----
  CBS cbs_pub, cbs_priv;
  uint8_t *der_pub = nullptr, *der_priv = nullptr;
  long der_pub_len = 0, der_priv_len = 0;

  ASSERT_TRUE(PEM_to_DER(GetParam().public_pem_str, &der_pub, &der_pub_len));
  ASSERT_TRUE(PEM_to_DER(GetParam().private_pem_str, &der_priv, &der_priv_len));

  CBS_init(&cbs_pub, der_pub, der_pub_len);
  CBS_init(&cbs_priv, der_priv, der_priv_len);

  // ---- 2. Attempt to parse private key ----
  bssl::UniquePtr<EVP_PKEY> pkey1(EVP_parse_private_key(&cbs_priv));
  ASSERT_TRUE(pkey1);

  // ---- 3. Attempt to parse public key ----
  bssl::UniquePtr<EVP_PKEY> pkey2(EVP_parse_public_key(&cbs_pub));
  ASSERT_TRUE(pkey2);

  // ---- 4. Compare public keys ----
  // EVP_parse_private_key will populate both public and private key, we verify
  // that the public key calculated by EVP_parse_private_key is equivalent to
  // the public key that was parsed from PEM.
  ASSERT_EQ(1, EVP_PKEY_cmp(pkey1.get(), pkey2.get()));

  // ---- 5. test failure modes ----
  // Test case in which a parsed key does not contain a seed
  bssl::ScopedCBB cbb;
  void *tmp = (void*) pkey1.get()->pkey.pqdsa_key->seed;
  pkey1.get()->pkey.pqdsa_key->seed =nullptr;
  ASSERT_TRUE(CBB_init(cbb.get(), 0));
  ASSERT_FALSE(EVP_marshal_private_key(cbb.get(), pkey1.get()));
  pkey1.get()->pkey.pqdsa_key->seed = (uint8_t *)tmp;

  // Clean up
  OPENSSL_free(der_pub);
  OPENSSL_free(der_priv);
}

TEST_P(PQDSAParameterTest, KeyConsistencyTest) {
  // This test: generates a random PQDSA key pair extracts the private key, and
  // runs the public key calculator function to populate the coresponding public key.
  // The test is sucessful when the calculated public key is equal to the original
  // public key generated.

  // ---- 1. Setup phase: generate a key and key buffers ----
  int nid = GetParam().nid;
  size_t pk_len = GetParam().public_key_len;
  size_t sk_len = GetParam().private_key_len;

  std::vector<uint8_t> pk(pk_len);
  std::vector<uint8_t> sk(sk_len);
  bssl::UniquePtr<EVP_PKEY> pkey(generate_key_pair(nid));

  // ---- 2. Extract raw private key from the generated PKEY ----
  EVP_PKEY_get_raw_private_key(pkey.get(), sk.data(), &sk_len);

  // ---- 3. Generate a raw public key from the raw private key ----
  ASSERT_TRUE(GetParam().pack_key(pk.data(), sk.data()));

  // ---- 4. Test that the calculated pk is equal to original pkey ----
  CMP_VEC_AND_PKEY_PUBLIC(pk, pkey, pk_len);
}

// ML-DSA specific test framework to test pre-hash modes only applicable to ML-DSA
struct KnownMLDSA {
  const char name[20];
  const int nid;
  const size_t public_key_len;
  const size_t private_key_len;
  const size_t signature_len;
  const char *ACVP_keyGen;
  const char *ACVP_sigGen;
  const char *ACVP_sigVer;

  int (*keygen)(uint8_t *public_key, uint8_t *private_key, const uint8_t *seed);

  int (*sign)(const uint8_t *private_key,
              uint8_t *sig, size_t *sig_len,
              const uint8_t *message, size_t message_len,
              const uint8_t *pre, size_t pre_len,
              const uint8_t *rnd);

  int (*verify)(const uint8_t *public_key,
                const uint8_t *sig, size_t sig_len,
                const uint8_t *message, size_t message_len,
                const uint8_t *pre, size_t pre_len);
};

static const struct KnownMLDSA kMLDSAs[] = {
  {
    "MLDSA44",
    NID_MLDSA44,
    1312,
    2560,
    2420,
    "ml_dsa/kat/MLDSA_44_ACVP_keyGen.txt",
    "ml_dsa/kat/MLDSA_44_ACVP_sigGen.txt",
    "ml_dsa/kat/MLDSA_44_ACVP_sigVer.txt",
    ml_dsa_44_keypair_internal,
    ml_dsa_44_sign_internal,
    ml_dsa_44_verify_internal
  },
  {
    "MLDSA65",
    NID_MLDSA65,
    1952,
    4032,
    3309,
    "ml_dsa/kat/MLDSA_65_ACVP_keyGen.txt",
    "ml_dsa/kat/MLDSA_65_ACVP_sigGen.txt",
    "ml_dsa/kat/MLDSA_65_ACVP_sigVer.txt",
    ml_dsa_65_keypair_internal,
    ml_dsa_65_sign_internal,
    ml_dsa_65_verify_internal
  },
  {
    "MLDSA87",
    NID_MLDSA87,
    2592,
    4896,
    4627,
    "ml_dsa/kat/MLDSA_87_ACVP_keyGen.txt",
    "ml_dsa/kat/MLDSA_87_ACVP_sigGen.txt",
    "ml_dsa/kat/MLDSA_87_ACVP_sigVer.txt",
    ml_dsa_87_keypair_internal,
    ml_dsa_87_sign_internal,
    ml_dsa_87_verify_internal
  },
  {
    "MLDSAEXTMU44",
    NID_MLDSA44,
    1312,
    2560,
    2420,
    "ml_dsa/kat/MLDSA_44_ACVP_keyGen.txt",
    "ml_dsa/kat/MLDSA_EXTMU_44_ACVP_sigGen.txt",
    "ml_dsa/kat/MLDSA_EXTMU_44_ACVP_sigVer.txt",
    ml_dsa_44_keypair_internal,
    ml_dsa_extmu_44_sign_internal,
    ml_dsa_extmu_44_verify_internal
  },
  {
    "MLDSAEXTMU65",
    NID_MLDSA65,
    1952,
    4032,
    3309,
    "ml_dsa/kat/MLDSA_65_ACVP_keyGen.txt",
    "ml_dsa/kat/MLDSA_EXTMU_65_ACVP_sigGen.txt",
    "ml_dsa/kat/MLDSA_EXTMU_65_ACVP_sigVer.txt",
    ml_dsa_65_keypair_internal,
    ml_dsa_extmu_65_sign_internal,
    ml_dsa_extmu_65_verify_internal
  },
  {
    "MLDSAEXTMU87",
    NID_MLDSA87,
    2592,
    4896,
    4627,
    "ml_dsa/kat/MLDSA_87_ACVP_keyGen.txt",
    "ml_dsa/kat/MLDSA_EXTMU_87_ACVP_sigGen.txt",
    "ml_dsa/kat/MLDSA_EXTMU_87_ACVP_sigVer.txt",
    ml_dsa_87_keypair_internal,
    ml_dsa_extmu_87_sign_internal,
    ml_dsa_extmu_87_verify_internal
  },
};

class PerMLDSATest : public testing::TestWithParam<KnownMLDSA> {};

INSTANTIATE_TEST_SUITE_P(All, PerMLDSATest, testing::ValuesIn(kMLDSAs),
                         [](const testing::TestParamInfo<KnownMLDSA> &params)
                             -> std::string { return params.param.name; });

TEST_P(PerMLDSATest, ExternalMu) {
  // ---- 1. Setup phase: generate PQDSA EVP KEY and sign/verify contexts ----
  bssl::UniquePtr<EVP_PKEY> pkey(generate_key_pair(GetParam().nid));
  bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
  bssl::UniquePtr<EVP_MD_CTX> md_ctx_mu(EVP_MD_CTX_new()), md_ctx_pk(EVP_MD_CTX_new());
  bssl::ScopedEVP_MD_CTX md_ctx_verify;

  std::vector<uint8_t> msg1 = {
    0x4a, 0x41, 0x4b, 0x45, 0x20, 0x4d, 0x41, 0x53, 0x53, 0x49,
    0x4d, 0x4f, 0x20, 0x41, 0x57, 0x53, 0x32, 0x30, 0x32, 0x32, 0x2e};

  // ---- 2. Pre-hash setup phase: compute tr, mu ----
  size_t TRBYTES = 64;
  size_t CRHBYTES = 64;
  size_t pk_len = GetParam().public_key_len;

  std::vector<uint8_t> pk(pk_len);
  std::vector<uint8_t> tr(TRBYTES);
  std::vector<uint8_t> mu(TRBYTES);

  uint8_t pre[2];
  pre[0] = 0;
  pre[1] = 0;

  //get public key and hash it
  ASSERT_TRUE(EVP_PKEY_get_raw_public_key(pkey.get(), pk.data(), &pk_len));
  ASSERT_TRUE(EVP_DigestInit_ex(md_ctx_pk.get(), EVP_shake256(), nullptr));
  ASSERT_TRUE(EVP_DigestUpdate(md_ctx_pk.get(), pk.data(), pk_len));
  ASSERT_TRUE(EVP_DigestFinalXOF(md_ctx_pk.get(), tr.data(), TRBYTES));

  // compute mu
  ASSERT_TRUE(EVP_DigestInit_ex(md_ctx_mu.get(), EVP_shake256(), nullptr));
  ASSERT_TRUE(EVP_DigestUpdate(md_ctx_mu.get(), tr.data(), TRBYTES));
  ASSERT_TRUE(EVP_DigestUpdate(md_ctx_mu.get(), pre, 2));
  ASSERT_TRUE(EVP_DigestUpdate(md_ctx_mu.get(), msg1.data(), msg1.size()));
  ASSERT_TRUE(EVP_DigestFinalXOF(md_ctx_mu.get(), mu.data(), CRHBYTES));

  // ---- 2. Init signing, get signature size and allocate signature buffer ----
  size_t sig_len = GetParam().signature_len;
  std::vector<uint8_t> sig1(sig_len);

  // ---- 3. Sign mu ----
  ASSERT_TRUE(EVP_PKEY_sign_init(ctx.get()));
  ASSERT_TRUE(EVP_PKEY_sign(ctx.get(), sig1.data(), &sig_len, mu.data(), mu.size()));

  // ---- 4. Verify mu (pre-hash) ----
  ASSERT_TRUE(EVP_PKEY_verify_init(ctx.get()));
  ASSERT_TRUE(EVP_PKEY_verify(ctx.get(), sig1.data(), sig_len, mu.data(), mu.size()));

  // ---- 5. Bonus: Verify raw message with digest verify (no pre-hash) ----
  ASSERT_TRUE(EVP_DigestVerifyInit(md_ctx_verify.get(), nullptr, nullptr, nullptr, pkey.get()));
  ASSERT_TRUE(EVP_DigestVerify(md_ctx_verify.get(), sig1.data(), sig_len, msg1.data(), msg1.size()));

  // reset the contexts between tests
  md_ctx_verify.Reset();

  // ---- 6. Test signature failure modes: invalid keys and signatures  ----
  // Check that verification fails upon providing a signature of invalid length
  sig_len = GetParam().signature_len - 1;
  ASSERT_FALSE(EVP_PKEY_verify(ctx.get(), sig1.data(), sig_len, mu.data(), mu.size()));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE);

  sig_len = GetParam().signature_len + 1;
  ASSERT_FALSE(EVP_PKEY_verify(ctx.get(), sig1.data(), sig_len, mu.data(), mu.size()));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE);

  // Check that verification fails upon providing a different public key
  // than the one that was used to sign.
  bssl::UniquePtr<EVP_PKEY> new_pkey(generate_key_pair(GetParam().nid));
  bssl::UniquePtr<EVP_PKEY_CTX> new_ctx(EVP_PKEY_CTX_new(new_pkey.get(), nullptr));

  ASSERT_TRUE(EVP_PKEY_verify_init(new_ctx.get()));
  ASSERT_FALSE(EVP_PKEY_verify(new_ctx.get(), sig1.data(), sig_len, mu.data(), mu.size()));
  GET_ERR_AND_CHECK_REASON(EVP_R_INVALID_SIGNATURE);
  md_ctx_verify.Reset();
}

TEST_P(PerMLDSATest, ACVPKeyGen) {
  std::string kat_filepath = "crypto/fipsmodule/";
  kat_filepath += GetParam().ACVP_keyGen;

  FileTestGTest(kat_filepath.c_str(), [&](FileTest *t) {
    std::string count;
    std::vector<uint8_t> seed, pk, sk;

    ASSERT_TRUE(t->GetAttribute(&count, "count"));
    ASSERT_TRUE(t->GetBytes(&seed, "keygen_seed"));
    ASSERT_TRUE(t->GetBytes(&pk, "keygen_pk"));
    ASSERT_TRUE(t->GetBytes(&sk, "keygen_sk"));

    size_t pk_len = GetParam().public_key_len;
    size_t sk_len = GetParam().private_key_len;
    std::vector<uint8_t> generated_pk(pk_len);
    std::vector<uint8_t> generated_sk(sk_len);

    //generate key pair from provided seed
    ASSERT_TRUE(GetParam().keygen(generated_pk.data(), generated_sk.data(), seed.data()));

    // Assert that key pair is as expected
    ASSERT_EQ(Bytes(pk), Bytes(generated_pk));
    ASSERT_EQ(Bytes(sk), Bytes(generated_sk));
  });
}

TEST_P(PerMLDSATest, ACVPSigGen) {
  std::string kat_filepath = "crypto/fipsmodule/";
  kat_filepath += GetParam().ACVP_sigGen;

  FileTestGTest(kat_filepath.c_str(), [&](FileTest *t) {
    std::string count;
    std::vector<uint8_t> rnd, msg, pk, sk, mu, sig, data;

    ASSERT_TRUE(t->GetAttribute(&count, "count"));
    ASSERT_TRUE(t->GetBytes(&mu, "siggen_mu"));
    ASSERT_TRUE(t->GetBytes(&msg, "siggen_msg"));
    ASSERT_TRUE(t->GetBytes(&rnd, "siggen_rnd"));
    ASSERT_TRUE(t->GetBytes(&pk, "siggen_pk"));
    ASSERT_TRUE(t->GetBytes(&sk, "siggen_sk"));
    ASSERT_TRUE(t->GetBytes(&sig, "siggen_sig"));

    // Choose which data to use for signing, the KAT can either have mu or msg
    if (mu.empty()) {
      data = msg;
    } else {
      data = mu;
    }

    size_t sig_len = GetParam().signature_len;
    std::vector<uint8_t> signature(sig_len);

    // Generate signature by signing |data|.
    ASSERT_TRUE(GetParam().sign(sk.data(),
                                signature.data(), &sig_len,
                                data.data(), data.size(),
                                nullptr, 0,
                                rnd.data()));

    // Assert that signature is equal to expected signature
    ASSERT_EQ(Bytes(signature), Bytes(sig));

    // Assert that the signature verifies correctly.
    ASSERT_TRUE(GetParam().verify(pk.data(),
                                  signature.data(), sig_len,
                                  data.data(), data.size(),
                                  nullptr, 0));
  });
}

TEST_P(PerMLDSATest, ACVPSigVer) {
  std::string kat_filepath = "crypto/fipsmodule/";
  kat_filepath += GetParam().ACVP_sigVer;

  FileTestGTest(kat_filepath.c_str(), [&](FileTest *t) {
    std::string count, result;
    std::vector<uint8_t> msg, pk, mu, sig, data;

    ASSERT_TRUE(t->GetAttribute(&count, "count"));
    ASSERT_TRUE(t->GetBytes(&mu, "sigver_mu"));
    ASSERT_TRUE(t->GetBytes(&msg, "sigver_msg"));
    ASSERT_TRUE(t->GetBytes(&pk, "sigver_pk"));
    ASSERT_TRUE(t->GetBytes(&sig, "sigver_sig"));
    ASSERT_TRUE(t->GetAttribute(&result, "sigver_result"));

    // Choose which data to use for signing, the KAT can either have mu or msg
    if (mu.empty()) {
      data = msg;
    } else {
      data = mu;
    }

    int res = GetParam().verify(pk.data(),
                                sig.data(), sig.size(),
                                data.data(), data.size(),
                                nullptr, 0);

    // ACVP test both positive and negative results we read the intended result
    // from the KAT and attest that the same result is in |res|.
    if(!res) {
      ASSERT_TRUE(strcmp(result.data(), "False") == 0);
    }
    else {
      ASSERT_TRUE(strcmp(result.data(), "True") == 0);
    }
  });
}

static const uint8_t mldsa87kPublicKeyInvalidLength[] = {
    0x30, 0x11, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
    0x65, 0x03, 0x04, 0x03, 0x13, 0x03, 0x02, 0x00, 0xe4};

TEST(PQDSAParameterTest, ParsePublicKeyInvalidLength) {
  CBS cbs;
  CBS_init(&cbs, mldsa87kPublicKeyInvalidLength,
           sizeof(mldsa87kPublicKeyInvalidLength));
  bssl::UniquePtr<EVP_PKEY> pub_pkey_from_der(EVP_parse_public_key(&cbs));
  ASSERT_FALSE(pub_pkey_from_der.get());
}

static const uint8_t mldsa44kPrivateKeyInvalidLength[] = {
    0x30, 0x16, 0x02, 0x01, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48,
    0x01, 0x65, 0x03, 0x04, 0x03, 0x11, 0x04, 0x04, 0x82, 0x45, 0x52, 0xd8};

TEST(PQDSAParameterTest, ParsePrivateKeyInvalidLength) {
  CBS cbs;
  CBS_init(&cbs, mldsa44kPrivateKeyInvalidLength,
           sizeof(mldsa44kPrivateKeyInvalidLength));
  bssl::UniquePtr<EVP_PKEY> private_pkey_from_der(EVP_parse_private_key(&cbs));
  ASSERT_FALSE(private_pkey_from_der.get());
}
