From db90b836a29f8691f01b0ed64d1aefd5f93d70d3 Mon Sep 17 00:00:00 2001 From: Koji Takeda Date: Fri, 21 Feb 2025 15:38:41 +0900 Subject: [PATCH 1/2] Support ML-KEM --- docs/asymmetric.rst | 32 +++ scripts/build_ffi.py | 35 ++- tests/test_mlkem.py | 651 +++++++++++++++++++++++++++++++++++++++++++ wolfcrypt/ciphers.py | 287 ++++++++++++++++++- 4 files changed, 1003 insertions(+), 2 deletions(-) create mode 100644 tests/test_mlkem.py diff --git a/docs/asymmetric.rst b/docs/asymmetric.rst index bc1d21c..2e9009b 100644 --- a/docs/asymmetric.rst +++ b/docs/asymmetric.rst @@ -81,3 +81,35 @@ ECC .. autoclass:: EccPrivate :members: :inherited-members: + +ML-KEM +------ + +.. autoclass:: MlKemType + :show-inheritance: + +.. autoclass:: MlKemPublic + :private-members: + :members: + :inherited-members: + +.. autoclass:: MlKemPrivate + :members: + :inherited-members: + +**Example:** + +>>> from wolfcrypt.ciphers import MlKemType, MlKemPrivate, MlKemPublic +>>> +>>> mlkem_type = MlKemType.ML_KEM_512 +>>> +>>> mlkem_priv = MlKemPrivate.make_key(mlkem_type) +>>> pub_key = mlkem_priv.encode_pub_key() +>>> +>>> mlkem_pub = MlKemPublic(mlkem_type) +>>> mlkem_pub.decode_key(pub_key) +>>> ss_send, ct = mlkem_pub.encapsulate() +>>> +>>> ss_recv = mlkem_priv.decapsulate(ct) +>>> ss_send == ss_recv +True \ No newline at end of file diff --git a/scripts/build_ffi.py b/scripts/build_ffi.py index 7a6779d..d7aaf9f 100644 --- a/scripts/build_ffi.py +++ b/scripts/build_ffi.py @@ -232,6 +232,10 @@ def make_flags(prefix, fips): flags.append("--enable-pwdbased") flags.append("--enable-pkcs7") + # ML-KEM + flags.append("--enable-experimental") + flags.append("--enable-kyber") + # disabling other configs enabled by default flags.append("--disable-oldtls") flags.append("--disable-oldnames") @@ -442,6 +446,8 @@ def build_ffi(local_wolfssl, features): #include #include #include + #include + #include """ init_source_string = """ @@ -478,6 +484,7 @@ def build_ffi(local_wolfssl, features): int AESGCM_STREAM_ENABLED = """ + str(features["AESGCM_STREAM"]) + """; int RSA_PSS_ENABLED = """ + str(features["RSA_PSS"]) + """; int CHACHA20_POLY1305_ENABLED = """ + str(features["CHACHA20_POLY1305"]) + """; + int ML_KEM_ENABLED = """ + str(features["ML_KEM"]) + """; """ ffibuilder.set_source( "wolfcrypt._ffi", init_source_string, @@ -513,6 +520,7 @@ def build_ffi(local_wolfssl, features): extern int AESGCM_STREAM_ENABLED; extern int RSA_PSS_ENABLED; extern int CHACHA20_POLY1305_ENABLED; + extern int ML_KEM_ENABLED; typedef unsigned char byte; typedef unsigned int word32; @@ -922,6 +930,30 @@ def build_ffi(local_wolfssl, features): int wolfCrypt_GetPrivateKeyReadEnable_fips(enum wc_KeyType); """ + if features["ML_KEM"]: + cdef += """ + static const int WC_ML_KEM_512; + static const int WC_ML_KEM_768; + static const int WC_ML_KEM_1024; + static const int INVALID_DEVID; + typedef struct {...; } KyberKey; + int wc_KyberKey_CipherTextSize(KyberKey* key, word32* len); + int wc_KyberKey_SharedSecretSize(KyberKey* key, word32* len); + int wc_KyberKey_PrivateKeySize(KyberKey* key, word32* len); + int wc_KyberKey_PublicKeySize(KyberKey* key, word32* len); + int wc_KyberKey_Init(int type, KyberKey* key, void* heap, int devId); + void wc_KyberKey_Free(KyberKey* key); + int wc_KyberKey_MakeKey(KyberKey* key, WC_RNG* rng); + int wc_KyberKey_MakeKeyWithRandom(KyberKey* key, const unsigned char* rand, int len); + int wc_KyberKey_EncodePublicKey(KyberKey* key, unsigned char* out, word32 len); + int wc_KyberKey_DecodePublicKey(KyberKey* key, const unsigned char* in, word32 len); + int wc_KyberKey_Encapsulate(KyberKey* key, unsigned char* ct, unsigned char* ss, WC_RNG* rng); + int wc_KyberKey_EncapsulateWithRandom(KyberKey* key, unsigned char* ct, unsigned char* ss, const unsigned char* rand, int len); + int wc_KyberKey_Decapsulate(KyberKey* key, unsigned char* ss, const unsigned char* ct, word32 len); + int wc_KyberKey_EncodePrivateKey(KyberKey* key, unsigned char* out, word32 len); + int wc_KyberKey_DecodePrivateKey(KyberKey* key, const unsigned char* in, word32 len); + """ + ffibuilder.cdef(cdef) def main(ffibuilder): @@ -951,7 +983,8 @@ def main(ffibuilder): "WC_RNG_SEED_CB": 0, "AESGCM_STREAM": 1, "RSA_PSS": 1, - "CHACHA20_POLY1305": 1 + "CHACHA20_POLY1305": 1, + "ML_KEM": 1 } # Ed448 requires SHAKE256, which isn't part of the Windows build, yet. diff --git a/tests/test_mlkem.py b/tests/test_mlkem.py new file mode 100644 index 0000000..c84af8d --- /dev/null +++ b/tests/test_mlkem.py @@ -0,0 +1,651 @@ +# test_mlkem.py +# +# Copyright (C) 2025 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=redefined-outer-name + +from wolfcrypt._ffi import lib as _lib + +if _lib.ML_KEM_ENABLED: + from binascii import unhexlify as h2b + + import pytest + + from wolfcrypt.ciphers import MlKemPrivate, MlKemPublic, MlKemType + + ref_priv_key_512 = h2b( + "7a9789b11b5871249ab5fac64e19599150960daa8872898ac55a580c906d7872" + "a8ec16b43791a30a821c6770a1aab98837548e39a37e30674e5efbced0e38a85" + "a920ef5aa07fa5c9ad219cd4e198709a4c949bc8104b946de343f6f4b1ff3155" + "6c681a8db66da3b308d09b08c421611a3743fa82c760f35b94727fb70058d866" + "bd5b05ca12c8a1eef4a9360640b576457174a827b402904b559b839fe9fa3a6f" + "01c340019530657967354f9ae8aa96a7709697a4e1947d52393c8f8a40cad310" + "5ef84559e8b0b2244fdb769d28f854afe6cde616c9cfc5cfc5b8170199bbd384" + "b365dbc2fd651f3042ce8c625ae4410be3a96fcce09c0122bd8d68203345778d" + "7b5a1454cccaa7b6b26b8b97a290e3e3a577d5b0deb56adee45c9be5c5984340" + "21f38afcf9aee9625a4caac44d2199e27ac324b3153830bd3791ab654a61d0f9" + "03f902a3f06a42e1241dd262791c242fe13516abb3b51bf46c22d77b6cea44a4" + "e962ebd42dcde5851028a57b86a880278c8dc6acf05b17185a3186a097edb56c" + "0265577646ce47411c1fba8e83418e0d2c5176dac5951a6fbdd619fb48045339" + "3fa4d21dada8b073e961f7ccade8035997171b3f63959eb087ae6732e7c049f2" + "11c024a054cd4607dc417847a48e107b80b72117883bcc8b272c138c64bc6bbb" + "46904b6fd2b249d49255608ec3ea30d79b6cec09a92b49244c90cca559995ec9" + "013ac0825c502a4c33cc5b094ac20477332b28b092bd83558a791536a0013026" + "2a73a2e3a78688238162237dd3a0c4d22fec2a30b9f19c58fb39cd1ac4944030" + "1cfa54b566736e6b7600b3b650a42d3afaa57a0c1e451a3243b2367945958f38" + "32e5ebba28e365fd35377069c3e75ac5f7175cc341437302350e837b30f90a13" + "0b7efa7614a614b96cf071ec2cb886854ad5e19cc5a4306bb8173a47670a9748" + "1a92b2d8e66688690445b8b2a87482fb638f3d88b6e6378d6ff9150f8a753db7" + "11b5d2a571788e686b2688b2b10db0310690c8039ba664f6634260afd88730a6" + "34471a510662f17431560d2b0811587c004e209af9215e2bfb493fb9ad36699f" + "181bc699c2b59d5176bcf59005729ea7a4011d050d5cf28633c3761b6879e959" + "7c83d005a8b67bab274e10ec9617533190eb8c7cf98da995b68331b0637862d4" + "90119126576c419aa328c53c097efea7118dc9b8aa68c1727c679e62611efa13" + "4031c0ec5041594a3c15ea14b1a03bc1d70f11404b8bc128ab126261f362b014" + "2e3d7c4cb0448141fc9909a07819c3208efc0c0df6bc9593a53ae500e0152987" + "a5bd51e45e351358b850b5f2304c1515ae6a8b151ad7ab4ba0abf9f9bd981311" + "51f9b57c35a6cba16a65726e67fca904c02a97a75be6f875c38ab35f35bf0e22" + "23d65a5be9ccc329e2becbf2963d858a40e37d3392cc71d612f3c06ca2f0215a" + "3949d7d40f34e97c18521e562066512347a913314a46ccf0a5bf9c081c50f666" + "d3119a05956edfd89c800a0dfe263b47e20e9488b8c1170171d0213640252496" + "b5aa7431e56a290d564ce8f58e7a57ad3076974d271096f79a5be069d0836673" + "ec85b732801991c5e2847052279829180543b17e8946aea5fb7c8ed8c19f19cf" + "5e4c9f57e70999d550c8946e22a6287452ae05a55cc0617147791f0ad581a097" + "a9c3d97434a5485a0a5aed7bc255913ce83cacc7478e4658597a3093640809ff" + "6b4005984bc6868f2ec42610f477b55a34d1053682613ce0cab5ff78ae8baa1c" + "213b9d774aac2c43ca065a441287b368010a9256059bf069b4abcd555b04ff69" + "cb0a7078091c69d188c83d919019671ea3e759ebfcbe90413691babb81c80b45" + "54a7e2b717bdc2c3c18cc1ca42634f515239118e2718709651b9b3f50fb6064d" + "8dd58ece0380a167424b367091c7c29805c3942a9fb67a5494db2acee6518feb" + "727ba97fb6dab15a10be51241991f32b9ceb28d4a28d19e5b915e02e024277d3" + "2985a516be2d7331a005699ca0c3723b9e2dd953987774904c9cdfbb3835b1a9" + "bab2524f845e3e27c58b34b56634a4f6f79be751842cbb382759624e0c62c5b3" + "1669a1020f83889b386918d8b3c866adf979b923273946969c8b04c7b7fa68b4" + "30433e4ca9792124f9515bc39b795a32058e3289a75b5aeb9bcbdd825777992c" + "c30b502c96db43f97ff3c365407aad0c6be42358909d6d873a93b48edb9f7948" + "582991075b0f2d4a52981d3dabe8d517aa9cb8a9436ed40ec0bef3af37967faa" + "7e385f73630001f67fa091f49a35284c088f1727f3818a78e174248229641389" + ) + + ref_pub_key_512 = h2b( + "181bc699c2b59d5176bcf59005729ea7a4011d050d5cf28633c3761b6879e959" + "7c83d005a8b67bab274e10ec9617533190eb8c7cf98da995b68331b0637862d4" + "90119126576c419aa328c53c097efea7118dc9b8aa68c1727c679e62611efa13" + "4031c0ec5041594a3c15ea14b1a03bc1d70f11404b8bc128ab126261f362b014" + "2e3d7c4cb0448141fc9909a07819c3208efc0c0df6bc9593a53ae500e0152987" + "a5bd51e45e351358b850b5f2304c1515ae6a8b151ad7ab4ba0abf9f9bd981311" + "51f9b57c35a6cba16a65726e67fca904c02a97a75be6f875c38ab35f35bf0e22" + "23d65a5be9ccc329e2becbf2963d858a40e37d3392cc71d612f3c06ca2f0215a" + "3949d7d40f34e97c18521e562066512347a913314a46ccf0a5bf9c081c50f666" + "d3119a05956edfd89c800a0dfe263b47e20e9488b8c1170171d0213640252496" + "b5aa7431e56a290d564ce8f58e7a57ad3076974d271096f79a5be069d0836673" + "ec85b732801991c5e2847052279829180543b17e8946aea5fb7c8ed8c19f19cf" + "5e4c9f57e70999d550c8946e22a6287452ae05a55cc0617147791f0ad581a097" + "a9c3d97434a5485a0a5aed7bc255913ce83cacc7478e4658597a3093640809ff" + "6b4005984bc6868f2ec42610f477b55a34d1053682613ce0cab5ff78ae8baa1c" + "213b9d774aac2c43ca065a441287b368010a9256059bf069b4abcd555b04ff69" + "cb0a7078091c69d188c83d919019671ea3e759ebfcbe90413691babb81c80b45" + "54a7e2b717bdc2c3c18cc1ca42634f515239118e2718709651b9b3f50fb6064d" + "8dd58ece0380a167424b367091c7c29805c3942a9fb67a5494db2acee6518feb" + "727ba97fb6dab15a10be51241991f32b9ceb28d4a28d19e5b915e02e024277d3" + "2985a516be2d7331a005699ca0c3723b9e2dd953987774904c9cdfbb3835b1a9" + "bab2524f845e3e27c58b34b56634a4f6f79be751842cbb382759624e0c62c5b3" + "1669a1020f83889b386918d8b3c866adf979b923273946969c8b04c7b7fa68b4" + "30433e4ca9792124f9515bc39b795a32058e3289a75b5aeb9bcbdd825777992c" + "c30b502c96db43f97ff3c365407aad0c6be42358909d6d873a93b48edb9f7948" + ) + + ref_ss_512 = h2b("d1cef1d861b7a7d3a2bc8b5a0faa70c4bf6b0b4394df7a7330debe0c2a8326c1") + + ref_ct_512 = h2b( + "8a883c621214524d47fa60da21f46aa62e0ba24771e1195772b2aecc10883422" + "cc68fb29a50782548c06fb6550660ea38035c871818eebc7129134e4d8de7c0f" + "d34a4d32985c830f56a0cb057eb5422fdd94a58c68ada859614ff410a4ecb660" + "8813138ef0f26634f81e69802f1b9415c65b1e47f1e84e52b24255ac91496a03" + "8d86c01b827057868a1749fa7590fee6442793909ca954bc986ae624cdf2fb57" + "d9c534cbc1c235b74e44f3eb23ee136a57815343b148fe4c055257ae490d85e7" + "1c0ddc954d5a6447ce6eed26a9bd149cd21044c38ab1bda703d478b15f74ac75" + "c4aaaf60657990162c0d6d1f891ea2de4e5d7ddf56dddc0e2dbeabf2fdf6e26b" + "dc850ca53ae773c16b7b9132eef7723f77fc5776965e49866b01b66758b598ab" + "868118ee21a25a61eaa391d84903a3cdaafcc3fae2106b4ff32f506e18b0ee6e" + "7caea426240ac8d2c07aea738f67c4951aa6d352849147b97486d97cc9695e40" + "b8eedb8f95e44463cf90f67b6cec23e3cdc91f7cab07b75dae60413ec9126850" + "318852df87d1d5ed042f749c5534edeab52e32d61ab6d851403bdd72ab0ea771" + "34a08bbc1e76c961b97b6eeae1d29e892dee6f601d1f8e9eb0bc41c961d35d1c" + "92e6ec043a61d790f42fb454f64bc95cdeb2792a0f971b33b92fc58176f96026" + "8550bf4e8e40c4c61e84cf4e1b113ccc367cfc2171b31b86fa0e3fc0c48b0db9" + "f05fe2f7a0e6735f6ab94c29bc3f63630407ccc1e61f3e6446bb55511ea03684" + "af609b327e6b0ea96badfe84674e4d5da9b37cd78ccf82f61b83b7baabaaec62" + "60e73e7f1319c7573772733d50cd3856f1fbde2e37e526be056af94c4e96efa2" + "803890416726d21b880c278540d698eb6deb80b85282005e4b3c8393ceacb3e5" + "092405d7253f5d35b83c6bbfba0fd287db0e522d74dfa9038da332d50ef4df72" + "c6ce351ffa410c594121ca24cd9a319baf1b85980e8ed9f54ea2936d545c854a" + "a3428ca0ac909175d76be70686ea4429dd069020ce299b53d2bf34c85e78c739" + "a15e23d98ae42712bee5a07d73db464dda59cc422344d2cd8fe7b36eef2e05ad" + ) + + ref_priv_key_768 = h2b( + "be3a79da6370a170cabec9212e2930b9fb425703b49925882fc2b66a38c56c46" + "c3bfd7803156b43de132bdd9a24d064763357460135b1f32a9aba48413ebcb08" + "d823bdd4ccac3294ee830123bc42ad2412416c126d86b9c953c5c459960ca76c" + "4b42737698b1e78c0c44039c2fe7577534319b01aa6e26962362b733148f3290" + "1a3e38056a7790b51bc08dcbad5e193b6d53803dbb1bc7b81378c54ac994a600" + "7a16c3d3a70f60748d5acb92163c2dd4cf482b28aa773adedc5b8f5b3a8a974a" + "a4ba095e0895033270f51144e90cba6e36aa8e06bc11a5c2dfa746f6eb3af095" + "0f15c5c48b4c4388406568057c6918bb5a37b0db788184b56a09ca61fbab6eff" + "04ba56e53e1b804c583c8850a4a68deb82c8b8124d0a3bdf1c43b875811e009d" + "4e539d3a840f03447896aa41ca221219740b647a82359c9ea972545ab4b0fa8a" + "c50ac47816e6c9bcf61faa306d839c4bae0c40a656c34145a4daac6ceb2801c4" + "844959b75401809c1aab8368993dfc5c08d7d337d1a23eebe23313243e68e8c6" + "b5cbb184c67942b872f0aaa61d61aa9a4a934986c2ff1b643d1bcbcdd554c020" + "9c855a52eb86a7a5b17b53465b68c08e0f174a88ba5f452158e17c8595673d45" + "da3420b3af747b19d6326e631b0c37c008d984b7f18067d7dc894a04c2c7385f" + "526574bd27c4b9c8b9d44985f8c62bdd6118f4dc25f083723596343a806fd052" + "9d8c2563f789b9ddb9c5db56ada8ebc10587bba86c249923916d8a12bd485134" + "078309b772fbb756d5b1480b2438e95502344a77ae145b183b897f712bf006c2" + "da02ba3b11600f8c4af9b755d56ccbbec7af3c6966aaf7578f22c419332ad9d9" + "343e971d10a2c8003783df082f6a6060d3f9b56cd2a022a52e7a334137325d91" + "bbcd05075819ec45b3db30179405652262f1397f0b136cc06aafdb6b461c2b10" + "7bf448e6f68e22650ceff184a3228c3ff0cbbf0bbe562b6b63fba139d4284f17" + "3db6b048e5898363034e7e49566fe5026c239ec63318b7acb90c103d13d89a04" + "3678550274e7025d3858449b01c464d5a9705294bdaccc556454963058789b95" + "96f2562df7c76e50180c33c438f9792ad3128fa0c390202910420ee68658a4d5" + "33a1d70356c2b9b248147d9ac64b1b2ded108595144e46bb7ff2b9a30e991e1f" + "4979b20c4bf9ac2fcab36956692b4a856d6ed8781f2a3ce6700673e4239daa7a" + "4a8186308327a1883666eb13b41cbdc4d413088a3995595a02b260df4ac8d804" + "988e3b1103ec35d3f342c447208109686d80a26d1cb1d1f068cec31c9da06f17" + "440cd4958d7c08badf92bb85f3532a74c4c2c944ec86aa5975ad50f9c31f155c" + "d1e2449b089775dbaf87889de73127b28515f35c2b2a319a37b292193b0d3f89" + "5ac698986f57c4a79940fd42133c190ab6b611f8988a9009c512c60275b721db" + "984e37daa1b13c5272a880b120b477953028b3ae30406c313100d78ccb24e566" + "453b566c32b7c3e237088771a941385713bc05885592853bc5600fc152c46252" + "5f1de95f2c1b0cf1111bf40b391acc608421c577f35e06fc037330395aac5dcf" + "822f91f18eac3b2c4e39b12de27a1926a3d2f8a3ed047b648042c2a78200f5bb" + "72480a6256a076339b826c99e6866ef9e3519f10616558a13549878626cecb5b" + "c4f4e9695b5baea55a9a9c3b6226e90ad56a418b865006b188b0aa0f54555f93" + "b62809689b456854f2924b0936392abb862e896355739c9ccb843769775c3746" + "7526ae7636489591ca7ba50f37c72b23b12f139357469242f060793ce9c90b49" + "260116c117c04d80f609775472d7064dd7726311060678a0737e66aae9513710" + "acce5931c6c32379444ab4d1340332b271c363a4a08502d4c398f4f839c01910" + "313583748326d1f1a01d8cc99ab09faed03e80664044c62a97ec64c78b93bbfb" + "59e6929d175c51918026fe923388425612926c24728eb9266725d1a0b6ba07a3" + "5667602b61552533910c7e0edc8193f243f3a5bacffcbca9078ee0c600576593" + "3359a6ca2133f86a4321946285d62c22489c74d3af723574b8e647a0183ffe05" + "0a08331750f16c8032668a3a89be0458f89604001223667a2b8f825f892a222e" + "aa8c8826a5903533571469088b5bbba8cf1947c43ebc9ba29cb308862e954ac9" + "4a2170ef0b319a676c184022271c67e65404f86a2a3d607312e51e8e29bf70c1" + "c78eb5000686b6578517f5f1162f0c558960c3de3a0a65885d246bcb8e8528b0" + "7b18cf3485809cbe539113e33690f9132081a1115159845afa780f90ce09a0ab" + "39fa8378d7c2313a1e4dec367d0401194352e5f638d06a09ce478dcfc4995a8a" + "50aad1571b2607c251666b1375be98cca190af25893534e1bf0ff0b9152393b4" + "b97c7fca4753a29c176831b91163fdd47cf833289ec98358608c3bc2321081ca" + "5d4b962dd7ce91382fd82380e84c761d660d87bb1299a7196671105fa25c7cd6" + "535935b69e036c09ea5fdc69ba198a92a3368a11469440b4cae7a9374123ac1c" + "d958ed8bc2258aa9a8ac0d9c9296836c11e260900a23cd87f7b997c029d21c48" + "570134987323fba507ddc40c7361bde775966628a8f5354db2cb44ba044cb287" + "8162f32a82517036fa8ba38b0a9239caf393ce894cb51ae2038919614f315f21" + "501af45b882630b606c6b701973ed76a7fd3070b5845b9f661bafef30beab81a" + "3333609835030f4bc81c91cc8958996d098560063744b38cec1cc612b4c1b983" + "3f2a7c3d2c67786b363788509dd9f0284a09150232a8f3a0ca0f190b0b0bbc56" + "930fb8a6acb5d40a1f033fb2ab14791339d1fb98abcb51fc2a8b5d79c98a5a59" + "7dfa07844c989e7015d2349b903068962498d7006ac17795c7f77ac8f97bcf44" + "4e12e17936fa312ea27f22eb5ffc776a6f61681c37496b6cc437b54183c625b7" + "8271e476b8f4377cf457369900cb78f911ab4a6f3868a2cf956f8a233277a492" + "5f775e4127441794255ab0a7caec4484c374d9e57adbd24a97f81a482c77c9b0" + "60f235bc63900bcf4b435edc66541696199c1bac788aa3796d7064822e411dea" + "9433a18c991a0744b881076361cc740243763b3f4b2a672f0a36497241ae1cb7" + "d2766f6bd68339f4230eb8bcb3743d5e71c217864e690929c1cba031402246ec" + "ab7a452c19fc9511fc0f82581971975ed00772c789443aca822980629a6366cd" + "b29728860bdcd24fd2eb8fe0b81f3c84b7fc53676863291ba0cf5e569230410e" + "cb9a0cf3e65cae67bf7c3d6b1b726dc7a6bd4a437931ec6a9302629bca24276c" + "536401d4a638430b27f9a343055a9fe5b109ad8897b993c2e66df5b07ae8f4a8" + "7e385f73630001f67fa091f49a35284c088f1727f3818a78e174248229641389" + ) + + ref_pub_key_768 = h2b( + "72480a6256a076339b826c99e6866ef9e3519f10616558a13549878626cecb5b" + "c4f4e9695b5baea55a9a9c3b6226e90ad56a418b865006b188b0aa0f54555f93" + "b62809689b456854f2924b0936392abb862e896355739c9ccb843769775c3746" + "7526ae7636489591ca7ba50f37c72b23b12f139357469242f060793ce9c90b49" + "260116c117c04d80f609775472d7064dd7726311060678a0737e66aae9513710" + "acce5931c6c32379444ab4d1340332b271c363a4a08502d4c398f4f839c01910" + "313583748326d1f1a01d8cc99ab09faed03e80664044c62a97ec64c78b93bbfb" + "59e6929d175c51918026fe923388425612926c24728eb9266725d1a0b6ba07a3" + "5667602b61552533910c7e0edc8193f243f3a5bacffcbca9078ee0c600576593" + "3359a6ca2133f86a4321946285d62c22489c74d3af723574b8e647a0183ffe05" + "0a08331750f16c8032668a3a89be0458f89604001223667a2b8f825f892a222e" + "aa8c8826a5903533571469088b5bbba8cf1947c43ebc9ba29cb308862e954ac9" + "4a2170ef0b319a676c184022271c67e65404f86a2a3d607312e51e8e29bf70c1" + "c78eb5000686b6578517f5f1162f0c558960c3de3a0a65885d246bcb8e8528b0" + "7b18cf3485809cbe539113e33690f9132081a1115159845afa780f90ce09a0ab" + "39fa8378d7c2313a1e4dec367d0401194352e5f638d06a09ce478dcfc4995a8a" + "50aad1571b2607c251666b1375be98cca190af25893534e1bf0ff0b9152393b4" + "b97c7fca4753a29c176831b91163fdd47cf833289ec98358608c3bc2321081ca" + "5d4b962dd7ce91382fd82380e84c761d660d87bb1299a7196671105fa25c7cd6" + "535935b69e036c09ea5fdc69ba198a92a3368a11469440b4cae7a9374123ac1c" + "d958ed8bc2258aa9a8ac0d9c9296836c11e260900a23cd87f7b997c029d21c48" + "570134987323fba507ddc40c7361bde775966628a8f5354db2cb44ba044cb287" + "8162f32a82517036fa8ba38b0a9239caf393ce894cb51ae2038919614f315f21" + "501af45b882630b606c6b701973ed76a7fd3070b5845b9f661bafef30beab81a" + "3333609835030f4bc81c91cc8958996d098560063744b38cec1cc612b4c1b983" + "3f2a7c3d2c67786b363788509dd9f0284a09150232a8f3a0ca0f190b0b0bbc56" + "930fb8a6acb5d40a1f033fb2ab14791339d1fb98abcb51fc2a8b5d79c98a5a59" + "7dfa07844c989e7015d2349b903068962498d7006ac17795c7f77ac8f97bcf44" + "4e12e17936fa312ea27f22eb5ffc776a6f61681c37496b6cc437b54183c625b7" + "8271e476b8f4377cf457369900cb78f911ab4a6f3868a2cf956f8a233277a492" + "5f775e4127441794255ab0a7caec4484c374d9e57adbd24a97f81a482c77c9b0" + "60f235bc63900bcf4b435edc66541696199c1bac788aa3796d7064822e411dea" + "9433a18c991a0744b881076361cc740243763b3f4b2a672f0a36497241ae1cb7" + "d2766f6bd68339f4230eb8bcb3743d5e71c217864e690929c1cba031402246ec" + "ab7a452c19fc9511fc0f82581971975ed00772c789443aca822980629a6366cd" + "b29728860bdcd24fd2eb8fe0b81f3c84b7fc53676863291ba0cf5e569230410e" + "cb9a0cf3e65cae67bf7c3d6b1b726dc7a6bd4a437931ec6a9302629bca24276c" + ) + + ref_ss_768 = h2b("8202089e59a4e5db7c979c49228804535fd5009ad4308edbbde843a38e1a9f56") + + ref_ct_768 = h2b( + "3f520ff455db289ee0140e0b59dcf8792c819d48f487b4cca2ac5b04cb450248" + "d269d9fcae46154c06fefbd465d2019c3b090148b1b02a9a3854cb137f98ff51" + "db8ed422c940a14891e297ec192fe5755d486f9a0306f80fa88ebee8b86d1eb6" + "5e5f6de3ac429c34f3fe1075a977c9d6b057203e7e7ace62ad0af4336cfeeada" + "857c7f0c5e1e275244cc825adff3ab3c9922e3c0d3561667d2f6e23c072ec58e" + "e7cae83760114980234394addbd1eadca155e0b498eb6746d870c7ffab390549" + "d5f76f6579165655383659d88a9237c79c9a5a705bd180bc645b8c6b7eb0eb21" + "c73122457d3532442b36a9b40b8f1c8a534055c39dc2f7e67bb44388310aefbc" + "52747ac3c3111627e73580acc4d602047fde59f1a9df3770b1808b9d391db8c5" + "6bcdc2ffaac52008de46a93aafa99c28e8ec5cc13ef6c3be553e85ed54fd6925" + "4cddcdd2da55cb14c8ae057779336b4b679f480b325b20f894f695da139f57af" + "569872f0849b1dabb8bcdc366d9de63b81c4420faa1b02a87261c58bae34c600" + "41ced1e28a3122f2a89e8134c857f88cb79846ae8a468bdd029bc894a3a6b94c" + "2758a3d0b02a4e36d49b02302c42ad1c63524d147c95e8b06a13a1e25b881120" + "cb54af9e026424307454dacac3677bd28afbd11709587e5e08b06808de22dca4" + "66d5a86b0487cdd0d7dfaaa84d7ed112cb1002c7a2811de6f307c994c5c063bd" + "3c1cff803e5ce4d52d33511d5e17702bf8c21b654408034a00d38531c7a33f83" + "157dcd3bf09308da29d8a32af03b39080b8f4a590b9d40173094c4b97bddcf03" + "c10a5f5f024fbbb3e95ee21711c13b4e45f0da1797fb30b66571d7cecfddfa0f" + "10eca7b3af7b19f1be1fe79abeec05076a34247e95a224f417efbf6863d80087" + "19c536c226166c7a2a241c951bfb9f4535bd2919f6b82e60fc3b4c6f161ce5d7" + "0b4a16cb8558624d4bf3b504f3f3c9cef4134f001c006c5107ec5a5adab557cb" + "5ff79677f7542aa84b1aa89a33db7cc68f88a18323bd371cc6067e29ea1f6fab" + "bd71508aa7ae4cbbf5b4a629d1896a7870ac567d146474759224decc01d86772" + "5ea8c9fb0bc4b960c400db41400297b9e17978ba9cb23d2d01c1ed91651c84ed" + "ab67cd754cb50905462de656c637d5b2d89a4b87cf846cbead8b1a3b03eb1b4b" + "4b7eacaeba03f7d019fa677f9db5dfba3cbdaf0cb5027cc5c8b9854458065404" + "9de07c405f1163970d21c5343f0b6002ed0da581269b80869e212c72d9920edc" + "8360c292d2e5422fddce18b70e45eff0f7785993a3062e6da99a16482e177fc7" + "9d1aef7a20c5bb681ff529e8f492aea21dc09072e81e1f34f7a615d0bf6a36ac" + "63f47d609a2331e0b7973fdf0286aacaf4b12f3ed0a578bf4c6592ba90d4013f" + "3633f66a15115dde3019f7263a94fc527f2a4bbaeae1a978ae3db279c17db178" + "db999ad9665a1bb50e886de6886c4fdea1b4c55b229b9cf075a9eab897433c8d" + "d842a370d9d826861447e0600c25e04564f7973116c57a83e528a440d664347a" + ) + + ref_priv_key_1024 = h2b( + "a454277ee55b9be091c8b1a41ca26db2ab1b888851749cc35f81aedcbc77d849" + "a9a921481a8a636133121b4088795c12a6b84a9ae37591ea29107ca635275023" + "04634d180ec7963e31e69a77ab2ff4b94bbb87501b1cb03024ce11b36016f479" + "152653283551c96aa82801647f70abffb17dbf838fdc72152f215a7a976e0687" + "850abc9b99b9c90bf7383930a3440c9d3328b8ba9a5ec0768fdbb28b6673c0f9" + "e9314a1637064ccd2700608b093c007b23ec615871182216f5cb804ccd3155c9" + "792b4817708c2c5c26b77b93d7c70b31231e7f5c27a6c5825b9939a0f31efd43" + "993f894e9e799a893985987990e2bb9a10741ae56a85c21b51c84900fd3a30a4" + "75af9e65a3df89b07d061738508feff113995348597999901607634386bd3900" + "3f33099f273fa6c4cbaf7aa31e08686ed33a8f5c3792804fc5d4751631986c73" + "1a63974e949cb8b075c81e7241491c87bc17cf78b520256a63a4db1d6d034b62" + "565d8478b7b2eb3229129fdc34c78469c9b555052c66c54f83a7e53b7cb65b65" + "8ec8bcb9d4bbd9288581b6a4f3fcabed34a4714cba14b7cc0f7a49a8c34034e3" + "64b0f2abf061117bd23f65a98630ac259d186812a5a18ca322537b2576691acd" + "c6ac1e13875837cc95291a5a62428908cf01749e86cb017da11fc325cf4135bd" + "1b50828522875fd87cd1ab9ddd10cd303c387f66223c998d62a086631aa26d67" + "214e971f82751f577312cf7a0b30d84844f3581963a4d63214c5f71dc75abc6d" + "d8c2997c1fe22b70f7e579d041bcc6605b6ce740b57b6c3004c507b72f1e166e" + "5e237e5b3830fc77261b9b57c173cba3b1ce429a2c1fc06529a64af99b28c583" + "b731c5c76ecbb8a9e2ab799c11992bc249a929472a3c5f44c1371898ee07a1de" + "b455de759362014082412dc0e7128cd66b5635a57139663d002307766ad81c04" + "ce8a29a1aa2f65d13389226e2b5cce839896b16b4e701bad6ab1712bf601222b" + "8f4bd5acfcf83f7db5760956b8189102bfb3c0962c2c3b1a6b0db54d770997f1" + "d1a22596616b73071c60004c3b1c212b5066ab63ab71ad47262d7e426dcb96cb" + "2a19281cac1af625068ed6a20ec66cd8d63a07dabe1aa1389ba437f0b3638d09" + "23d3e2b078b44d44241f0073720e356f88d1b567b93c82e535abca1378f529d7" + "04373d3bb540443f68d64a9134bd8a954669a725165a40f8aab9df93ce8970cd" + "df5a15819783c2d13dd723b7c1d77d0978ccf896276400604a263d5e7b9b7a9b" + "5392e0648da2852b32626c695dca229657894398b00ee691b07783bf157c040f" + "58ca3cb260ad58a5c45bca73a0c59672a92f8c2c14fa6579cc1afce94f30b5ba" + "431597791c619e32926c621aae6817d0751e672263f2270fc9e7c0f41c964fb9" + "269bc908d62b9a47ca9c629b4ea53b91a4d65a2611b29f287a77dbbce4b3cd07" + "f78f0500c8f3086afff146e3489e2fc8b6a5fabb801a5cf33785d34c6f7aa08c" + "ccc091c3915cf2d882526a91288865e1389354d485b5c338700b7802422a3c90" + "20c118847a7bb62e26288a4a4240010aa4393785d35b38729987c45636748776" + "b373a2e545cff67b4c02225d25bfce75b916009d9aa97b370b444ea19f89bc4f" + "efb6649f0c4a15951ac23198f882a2cae88dac171663391b78382e121933b062" + "b6f895bd32d79ba4fa61d507171b1008dce364ed1c5d61b247415448408698be" + "62024f57a6ccb2cf70108f1f59cc9972a365220636bc978dd994abe82e1cbb39" + "aa37ca9d363f3c735cb26b29327b1e04f37a2919ccffcacea2ec4c7c83b87be0" + "9c6fea1744b043080909d98039c91721a506cf271a5a5c122fb30b8a897c39fa" + "28a60df28443a98ad408271a5538648c0775221db98944859755aca21db06286" + "c553426af0c7a8864411f15af7853f201975b9e9c279ab0787230e514044d734" + "9da8034431d7b199c00fe84a1a7c6693e3f5b5f4fb108305b24ccb1ff9621dfb" + "3619cf5780ef06bc61db788063cae6e02f3aeb362ad4110f5c025e03d0f0e52f" + "ced541865a912b777a8d92a936439155cc3a6543ad8055afa716472017548dfa" + "cac6f305ee85c262d329edbc7fafc8ade4e0190204a43ed9673dfbac40b3ae42" + "e50e10b6c2c05c8aa00776f176c13ed7c0ad5820620447f2ca20e7322cdef745" + "41813a77a5536af20968a654e04c2e7ffb22a702739251b3b4f41f110aa8c3ab" + "cd7798979ae7b204d05495655fc1c8bca0f37c1df96a194628e1aa457d1784a9" + "64c6ce4a6eb8135e8c751b0c127ff4fa3939c23fad3a7e9ba08564e5bdd1862f" + "6de7ca2984c8acfb26080c350b08a8ad01a63d2912f91255f21a95da042bfb72" + "70d5168b41e48c894097ce10cae0a709f8898747a140a9b62616d22b05187a08" + "b6102c88c4d5313d2fa137a13178aa5066f15856b2e68eefa36f867a9f477882" + "21c10a36d508207984e4aa51847bab4966c3acf5b792ab9b0bd65827e172c313" + "8f1e75328f4636dff7c6a4612b93b6940d5a5fcdb698df0b1453e4936d215be3" + "a9c52210437fa7b363eac0edfba01ba29a26f1a82ec8218707b56c33b4c3831c" + "7ddc1203cc57e7ca506b15730c49aeb71846fed8578158c3873a471625953d23" + "9151e4b1aabc4d10e962d7c90c9f409d9cd5a73eecafcd58505387a3d452b62c" + "900483f75924279259e72f8dd516b5377987c9b69a0963222815685070bd7723" + "a48aa3489cc5760a00b35863dd620c96863d25a501744ab1d8a771407170971c" + "53c3f9679cf95f73688cea6bcc04eb48a1e6c2d090ce882016f828432c218f9b" + "a703f726176d9aa7a0f3b14ec617533b5e804a964e099a53301fbfe88c6bb40f" + "a98273984a1dd9481f8a7b6a6d23a2ac1b471a46cb05d484db946551ac6a5e08" + "880a41818c550e6a020c4366a416253ef18c835a185c6125b6367c7e1b1069aa" + "028d56175f9d05048928a558b04e14eb7c6689a76c718288dc7a929c5681658b" + "17f4cdf945632e93627b2611c03a6639115ff5a668fd4ba06994c8c8911bd007" + "092b4496daaab7015165ec92cc4d459fcd811ddc41523d39744a186b3aba26c8" + "1a4bb2c16968b61d1c0c9b6301c7d32411dd8b0dfb47184d5482fc23381043bd" + "a7364a6ea07b0b29631780a5d83b6ec6258c27e4ca8734810ed1269e8982c07a" + "0f27e234802aab8f377a9593597b6cb8c380cff188320fba37d026a7baa8ce61" + "626922f2c6bc25c1284cbad077668ff96553434feb5703dbca92718a32e745a4" + "ead790bf877c857533b3dc2091d11e33147bad00b789d6421a377d14118d6012" + "c10f66678fa32412d243690b3123229f4a268e269c56f65525f4929e42463c81" + "20adf7e0ade7992977166cd3e585a91420682953006a0c0b6caf277a928e1635" + "bee2b07e630bf131711b3c92410c27005556fd68a5a41706ae0cbf595b62bf18" + "42a0934631843570606d14c704c507806065154ad9c9c617138fcc0720f98dd0" + "d0b5591002356a1b47217484857ce8a8ba69f85a72d102b2317ac6964334dc32" + "a4b8699f6bc349a34afa01564df5c2c6a53ed4880ef7ca6408241d43a9c1a5da" + "a529b9c62f0a966279a947d66c20dc185ef6b228909c16c6587a564d7f63a1dd" + "841a32e6564ab22e936693e2c556c1664e59b85b2a4b27b71bb5ece1b36bca14" + "3c4903d1b1cc5c716435e61c8aca0f5c7576147573413894cc8b06191890fbc6" + "1ac8baafbf807586c683229205005c2124d1c54fc07febb79f3e38194bc9bf40" + "039b5c3007ca551c106634fdc906bf43b4fad0425f189fb05a9c209bc953b02a" + "74d4193a580ea86a0aa1f503560074b031c4f9c9c68e98596490c34a34a7e665" + "0e147c714a326c93ba76aea90e8003083bca90e30bbff059a07f87caf9055828" + "11236527cff99bca214565efd17d56721fbb6bce3d17a27a775309ecb78d620d" + "d1d3b5b468790d337ef191af991609f90ba5ff3b3181882ff531635db917f18a" + "0fcb7a2b1a828a14e1333b259126f7943f6a60b6e00c48375edce10c6463a592" + "6308c639906b7770c531307f1a5e65335e64c4bc38dcca31128d06d09433d609" + "9ea72a4d98858c691075a331ffd652d6102481b7063cf5193c192b0cecbe43a1" + "0a574ca386ac89406c7fc405b3e6e873ae1493278095c10ccbb2c2582527a420" + "18881f810fce011f29278cf4c04c6837c6c28589f9276704fb91d1973b042697" + "1443996aeb269306b7b1283f05748e007b739c8521d690a387f908fce98a1527" + "770a3443d345cf342a4f1af53cf23ab0ffc9c5fd26ceee0571bdc661f859a4e8" + "399c86cc5017e51295011a6cc7926cd3136d4b809cb316d404a01892c8957343" + "38f9336360afe8d97709a541b217491066de19c4f320b189f6e0bcb3753f25bc" + "e98de871560bdc365cefcd41589b71be09d91a66e97559cc506745b8f11b78f5" + "7e385f73630001f67fa091f49a35284c088f1727f3818a78e174248229641389" + ) + + ref_pub_key_1024 = h2b( + "41813a77a5536af20968a654e04c2e7ffb22a702739251b3b4f41f110aa8c3ab" + "cd7798979ae7b204d05495655fc1c8bca0f37c1df96a194628e1aa457d1784a9" + "64c6ce4a6eb8135e8c751b0c127ff4fa3939c23fad3a7e9ba08564e5bdd1862f" + "6de7ca2984c8acfb26080c350b08a8ad01a63d2912f91255f21a95da042bfb72" + "70d5168b41e48c894097ce10cae0a709f8898747a140a9b62616d22b05187a08" + "b6102c88c4d5313d2fa137a13178aa5066f15856b2e68eefa36f867a9f477882" + "21c10a36d508207984e4aa51847bab4966c3acf5b792ab9b0bd65827e172c313" + "8f1e75328f4636dff7c6a4612b93b6940d5a5fcdb698df0b1453e4936d215be3" + "a9c52210437fa7b363eac0edfba01ba29a26f1a82ec8218707b56c33b4c3831c" + "7ddc1203cc57e7ca506b15730c49aeb71846fed8578158c3873a471625953d23" + "9151e4b1aabc4d10e962d7c90c9f409d9cd5a73eecafcd58505387a3d452b62c" + "900483f75924279259e72f8dd516b5377987c9b69a0963222815685070bd7723" + "a48aa3489cc5760a00b35863dd620c96863d25a501744ab1d8a771407170971c" + "53c3f9679cf95f73688cea6bcc04eb48a1e6c2d090ce882016f828432c218f9b" + "a703f726176d9aa7a0f3b14ec617533b5e804a964e099a53301fbfe88c6bb40f" + "a98273984a1dd9481f8a7b6a6d23a2ac1b471a46cb05d484db946551ac6a5e08" + "880a41818c550e6a020c4366a416253ef18c835a185c6125b6367c7e1b1069aa" + "028d56175f9d05048928a558b04e14eb7c6689a76c718288dc7a929c5681658b" + "17f4cdf945632e93627b2611c03a6639115ff5a668fd4ba06994c8c8911bd007" + "092b4496daaab7015165ec92cc4d459fcd811ddc41523d39744a186b3aba26c8" + "1a4bb2c16968b61d1c0c9b6301c7d32411dd8b0dfb47184d5482fc23381043bd" + "a7364a6ea07b0b29631780a5d83b6ec6258c27e4ca8734810ed1269e8982c07a" + "0f27e234802aab8f377a9593597b6cb8c380cff188320fba37d026a7baa8ce61" + "626922f2c6bc25c1284cbad077668ff96553434feb5703dbca92718a32e745a4" + "ead790bf877c857533b3dc2091d11e33147bad00b789d6421a377d14118d6012" + "c10f66678fa32412d243690b3123229f4a268e269c56f65525f4929e42463c81" + "20adf7e0ade7992977166cd3e585a91420682953006a0c0b6caf277a928e1635" + "bee2b07e630bf131711b3c92410c27005556fd68a5a41706ae0cbf595b62bf18" + "42a0934631843570606d14c704c507806065154ad9c9c617138fcc0720f98dd0" + "d0b5591002356a1b47217484857ce8a8ba69f85a72d102b2317ac6964334dc32" + "a4b8699f6bc349a34afa01564df5c2c6a53ed4880ef7ca6408241d43a9c1a5da" + "a529b9c62f0a966279a947d66c20dc185ef6b228909c16c6587a564d7f63a1dd" + "841a32e6564ab22e936693e2c556c1664e59b85b2a4b27b71bb5ece1b36bca14" + "3c4903d1b1cc5c716435e61c8aca0f5c7576147573413894cc8b06191890fbc6" + "1ac8baafbf807586c683229205005c2124d1c54fc07febb79f3e38194bc9bf40" + "039b5c3007ca551c106634fdc906bf43b4fad0425f189fb05a9c209bc953b02a" + "74d4193a580ea86a0aa1f503560074b031c4f9c9c68e98596490c34a34a7e665" + "0e147c714a326c93ba76aea90e8003083bca90e30bbff059a07f87caf9055828" + "11236527cff99bca214565efd17d56721fbb6bce3d17a27a775309ecb78d620d" + "d1d3b5b468790d337ef191af991609f90ba5ff3b3181882ff531635db917f18a" + "0fcb7a2b1a828a14e1333b259126f7943f6a60b6e00c48375edce10c6463a592" + "6308c639906b7770c531307f1a5e65335e64c4bc38dcca31128d06d09433d609" + "9ea72a4d98858c691075a331ffd652d6102481b7063cf5193c192b0cecbe43a1" + "0a574ca386ac89406c7fc405b3e6e873ae1493278095c10ccbb2c2582527a420" + "18881f810fce011f29278cf4c04c6837c6c28589f9276704fb91d1973b042697" + "1443996aeb269306b7b1283f05748e007b739c8521d690a387f908fce98a1527" + "770a3443d345cf342a4f1af53cf23ab0ffc9c5fd26ceee0571bdc661f859a4e8" + "399c86cc5017e51295011a6cc7926cd3136d4b809cb316d404a01892c8957343" + "38f9336360afe8d97709a541b217491066de19c4f320b189f6e0bcb3753f25bc" + ) + + ref_ss_1024 = h2b( + "6fd1e1e9b9933ff892a120874aa337b00aa15c78f17685ec6bbb538f3a292444" + ) + + ref_ct_1024 = h2b( + "52d4997fb1cc24a519bd079379d99949dfcb85cb9df2e8ada7adf734c2912e71" + "93ed9d03d1fd9c656be27b493df0dc876c4734ecdefda53e39feaa7b48e496cb" + "a62fd8c9fd646230e373e84312b7aa6617313b515b10e34a5335031ed62e8dcb" + "934644d2d15508c1b06dc7117e20f74c25260695bfabefcbfd4cc2288e11228c" + "8e904ff8dc3599f2ddfe8b977321bf4ab4baec12121a6dce4e1c9f6f07a84c69" + "1dd97ccc681d05641c66bdb7b0129f424a5718e7adf00cef7a3cb276b90d136f" + "b43cfafed8e20b25a4a739bfd0feeb99d1136adf901f04737db09d4cc52383b7" + "e9a90f162e524ea6851712a743ce81f2ccf5957b7ace529c0a9614c258e52952" + "859eeca3028d3c2c4f85f0f3c93a67366ca86c649f6b23343127cee76bd85f7e" + "50de35853e5ca4bf9cdc4dc4a7f77e2fc1e0eb2e1b6bc9ab4e5e67313e165a9d" + "0abffc611a6d0a106181445cc084ae7d5f5f8cd18d1230dab8bb052788c990f9" + "0f533cf9222e9f3db7d0c0e660053419b9d616eb030b9e9dedc2f0f811df2135" + "d8c490f319aed216bff22661cc4ea51ea6ae84f9b0646474d756581cbde17e9f" + "4352d7bed6d19df08900ea6021e94432611bcced4afc24a40c09c979ab0d8eab" + "f848c4323fcb71d04cee30c3280109db6e6c3db04dc82af2bfb62c0b7d478635" + "940c1995e4d3c3e0893d421cf72fa89be0861cd33c2dca4ed1547fd2125a67b4" + "03910ecdc00654c0579f4190e8f52bba14f83acb31160f425903c3db92b937df" + "be1e8f24be9eda5b5a29374e801af2d5dbfc5eac7e16ea8180a7032a4d295d5d" + "d7a1fb6c3f0563daae680d1fefe4cd3504e05599bb1ebb03ab9e8a06ae944c26" + "b8c3677c358234936d5af1bfd5d081445f05979c07e8db65c8106ea0aad87eef" + "33e6b4d1b0164e4a7ae2c7cebbd8b5d50c8e3f28d1b5ffef0f062f13ffc4b05b" + "e4319b1034d3a93b1948923cb5d94c94dd704763241107e588ad8e5e20d9f242" + "7282236682efc4b7c9074b6b4b12484331ea82b950601e6eb535722f7fe47489" + "d87a6d56d61d8a370f4d71ad9e56c7ee3ce0d5eb77c2c8e35a99a6f8b3b6f7d9" + "5a03d1478da1e96277b4861a322b05595bf30243c38664316ec4102a812a1ad1" + "258241f8ca598fcb6b56087b16957ce1c0b46c0eb2109364c344918d12328132" + "164065bef16856beadcb5ac485147e3d94bc75c4006113d523afeca534791b56" + "c43c3085205734d53f19cb1501c53b1fe0c5a53661ea23d2e4f8eee908bbf83d" + "e7dc6b5cd4f3800e88bfe2403b018d5115378131db0cd2d241954922bf2ebda7" + "007b2f8333c76576a5dde36556d195d6495745f729e8f77eeeac76044dead4ac" + "e33f20ed47403a7e91c90bd17bb288afe0bd8baa82246d83118d6ace95f66303" + "90301c30f7e84cd9db647fd5af28664057d7f0cb9a7d72cb365ebd58aab478bd" + "6b56b6135cc2f453c9d10168e0dc7877d888d27e0126798e1ae1d5a2fa76f814" + "8caf37358a9720f3fe8a3b3f0a0a2de800befd550f7fa2b3c5b6ab20faf77103" + "845a49de41c3ada2f30f6fc4dfe85d263ec780e2d23da44d890146ff16355863" + "d22c2696d486bdbe86c8929dec7380f3b944db446928e43f4ac9c0fe91a019b2" + "82786631950873ad8f9a682a194eaedfd03db093d0caacf0a15583d9dae39cc0" + "65bee2c978bce4c63b7487eb9069e7b82153111766dad4fea1f285e23d8c8e69" + "24c6ef27df239d91e0e7b8bf9a6c8756d59145f09be9ec82b4900679ef0b7485" + "b1dbdf2c7a4df6551d07ae634dacf635935e2b5ac7754f1f2214076b043da4f0" + "98279480e876e10a02c02cfd1747aa91ab490dc0fcadf83e34d7226f72808cec" + "baecfb2b13e08e5698f59897c3b1678697403b1b535ed7796b6370162aca7e5e" + "3835ea6155dae0959d1e1799437b197d091833e055fa4a5703bf6b53c35552a2" + "b73da0712207e23f40b818f2d0a7fc57b344c2f5216d230218a9926c83b44ffe" + "532e4f90f736243e6d27edde14deae75d595731519b9ec44f4d48fa6ea79c105" + "06d782ec071300e30a0f0f4cc501a676d4b9a6476d954f0a9b3b7eb01c210e6f" + "cb4f0ba36d042b3f04e37f2aa2737543feb7a133c992ba77f7ab02228c0068d1" + "c926ef22b074b2a90ae0da557bb8fc3248a53e606ee06dd138a512d0ba9e40ab" + "cdac31c7b5404a0a57bd34fd18ebfbac98cc41dc2f6dcc6b561081c877c5e70c" + ) + + # This random number is common among MlKemType.{ML_KEM_512, ML_KEM_768, ML_KEM_1024}. + ref_rand_for_make_key = h2b( + "d0978f5fcb5109d016f199d5d357184e1490fdf772005385d1d22f507d34acf8" + "7e385f73630001f67fa091f49a35284c088f1727f3818a78e174248229641389" + ) + + # This random number is common among MlKemType.{ML_KEM_512, ML_KEM_768, ML_KEM_1024}. + ref_rand_for_encap = h2b( + "91a244f62ab68f42c5b3a6816bd491332f133a69d87e58ce76b26e026d3c0e1e" + ) + + ref_priv_key = { + MlKemType.ML_KEM_512: ref_priv_key_512, + MlKemType.ML_KEM_768: ref_priv_key_768, + MlKemType.ML_KEM_1024: ref_priv_key_1024, + } + + ref_pub_key = { + MlKemType.ML_KEM_512: ref_pub_key_512, + MlKemType.ML_KEM_768: ref_pub_key_768, + MlKemType.ML_KEM_1024: ref_pub_key_1024, + } + + ref_ss = { + MlKemType.ML_KEM_512: ref_ss_512, + MlKemType.ML_KEM_768: ref_ss_768, + MlKemType.ML_KEM_1024: ref_ss_1024, + } + + ref_ct = { + MlKemType.ML_KEM_512: ref_ct_512, + MlKemType.ML_KEM_768: ref_ct_768, + MlKemType.ML_KEM_1024: ref_ct_1024, + } + + mlkem_types = [ + (MlKemType.ML_KEM_512), + (MlKemType.ML_KEM_768), + (MlKemType.ML_KEM_1024), + ] + + @pytest.mark.parametrize("mlkem_type", mlkem_types) + def test_init_pattern_1(mlkem_type): + mlkem_priv = MlKemPrivate(mlkem_type) + assert type(mlkem_priv) is MlKemPrivate + mlkem_priv.decode_key(ref_priv_key[mlkem_type]) + assert mlkem_priv.encode_priv_key() == ref_priv_key[mlkem_type] + pub_key = mlkem_priv.encode_pub_key() + assert pub_key == ref_pub_key[mlkem_type] + + mlkem_pub = MlKemPublic(mlkem_type) + assert type(mlkem_pub) is MlKemPublic + mlkem_pub.decode_key(pub_key) + assert mlkem_pub.encode_key() == ref_pub_key[mlkem_type] + + ss_send, ct = mlkem_pub.encapsulate() + ss_recv = mlkem_priv.decapsulate(ct) + assert ss_send == ss_recv + + ss_send, ct = mlkem_pub.encapsulate_with_random(ref_rand_for_encap) + assert ct == ref_ct[mlkem_type] + ss_recv = mlkem_priv.decapsulate(ct) + assert ss_send == ref_ss[mlkem_type] + assert ss_send == ss_recv + + @pytest.mark.parametrize("mlkem_type", mlkem_types) + def test_init_pattern_2(mlkem_type): + mlkem_priv = MlKemPrivate.make_key_with_random( + mlkem_type, ref_rand_for_make_key + ) + assert type(mlkem_priv) is MlKemPrivate + assert mlkem_priv.encode_priv_key() == ref_priv_key[mlkem_type] + pub_key = mlkem_priv.encode_pub_key() + assert pub_key == ref_pub_key[mlkem_type] + + mlkem_pub = MlKemPublic(mlkem_type) + assert type(mlkem_pub) is MlKemPublic + mlkem_pub.decode_key(pub_key) + assert mlkem_pub.encode_key() == ref_pub_key[mlkem_type] + + ss_send, ct = mlkem_pub.encapsulate() + ss_recv = mlkem_priv.decapsulate(ct) + assert ss_send == ss_recv + + ss_send, ct = mlkem_pub.encapsulate_with_random(ref_rand_for_encap) + assert ct == ref_ct[mlkem_type] + ss_recv = mlkem_priv.decapsulate(ct) + assert ss_send == ref_ss[mlkem_type] + assert ss_send == ss_recv + + @pytest.mark.parametrize("mlkem_type", mlkem_types) + def test_init_pattern_3(mlkem_type): + mlkem_priv = MlKemPrivate.make_key(mlkem_type) + assert type(mlkem_priv) is MlKemPrivate + mlkem_priv.encode_priv_key() + pub_key = mlkem_priv.encode_pub_key() + + mlkem_pub = MlKemPublic(mlkem_type) + assert type(mlkem_pub) is MlKemPublic + mlkem_pub.decode_key(pub_key) + + ss_send, ct = mlkem_pub.encapsulate() + ss_recv = mlkem_priv.decapsulate(ct) + assert ss_send == ss_recv + + ss_send, ct = mlkem_pub.encapsulate_with_random(ref_rand_for_encap) + ss_recv = mlkem_priv.decapsulate(ct) + assert ss_send == ss_recv + + @pytest.mark.parametrize("mlkem_type", mlkem_types) + def test_size_properties(mlkem_type): + refvals = { + MlKemType.ML_KEM_512: { + "pub_key_size": 800, + "priv_key_size": 1632, + "ct_size": 768, + "ss_size": 32, + }, + MlKemType.ML_KEM_768: { + "pub_key_size": 1184, + "priv_key_size": 2400, + "ct_size": 1088, + "ss_size": 32, + }, + MlKemType.ML_KEM_1024: { + "pub_key_size": 1568, + "priv_key_size": 3168, + "ct_size": 1568, + "ss_size": 32, + }, + } + + mlkem_pub = MlKemPublic(mlkem_type) + assert mlkem_pub.key_size == refvals[mlkem_type]["pub_key_size"] + assert mlkem_pub.ct_size == refvals[mlkem_type]["ct_size"] + assert mlkem_pub.ss_size == refvals[mlkem_type]["ss_size"] + + mlkem_priv = MlKemPrivate(mlkem_type) + assert mlkem_priv.pub_key_size == refvals[mlkem_type]["pub_key_size"] + assert mlkem_priv.priv_key_size == refvals[mlkem_type]["priv_key_size"] + assert mlkem_priv.ct_size == refvals[mlkem_type]["ct_size"] + assert mlkem_priv.ss_size == refvals[mlkem_type]["ss_size"] diff --git a/wolfcrypt/ciphers.py b/wolfcrypt/ciphers.py index 58f6c0c..bfc5529 100644 --- a/wolfcrypt/ciphers.py +++ b/wolfcrypt/ciphers.py @@ -1,6 +1,6 @@ # ciphers.py # -# Copyright (C) 2006-2022 wolfSSL Inc. +# Copyright (C) 2006-2025 wolfSSL Inc. # # This file is part of wolfSSL. (formerly known as CyaSSL) # @@ -1668,3 +1668,288 @@ def sign(self, plaintext, ctx=None): raise WolfCryptError("Signature error (%d)" % ret) return _ffi.buffer(signature, signature_size[0])[:] + + +if _lib.ML_KEM_ENABLED: + from enum import IntEnum + + class MlKemType(IntEnum): + """ + `MlKemType` specifies supported ML-KEM types. + + `MlKemType` is arguments for constructors and some initialization functions for `MlKemPublic` and `MlKemPrivate`. + + Followings are all possible values: + + - `ML_KEM_512` + - `ML_KEM_768` + - `ML_KEM_1024` + """ + + ML_KEM_512 = _lib.WC_ML_KEM_512 + ML_KEM_768 = _lib.WC_ML_KEM_768 + ML_KEM_1024 = _lib.WC_ML_KEM_1024 + + class _MlKemBase(object): + INVALID_DEVID = _lib.INVALID_DEVID + + def __init__(self, mlkem_type): + self.init_done = False + self.native_object = _ffi.new("KyberKey *") + ret = _lib.wc_KyberKey_Init( + mlkem_type, self.native_object, _ffi.NULL, self.INVALID_DEVID + ) + + if ret < 0: # pragma: no cover + raise WolfCryptError("wc_KyberKey_Init() error (%d)" % ret) + + self.init_done = True + + def __del__(self): + if self.init_done: + _lib.wc_KyberKey_Free(self.native_object) + + @property + def ct_size(self): + """ + :return: cipher text size in bytes + :rtype: int + """ + len = _ffi.new("word32 *") + ret = _lib.wc_KyberKey_CipherTextSize(self.native_object, len) + + if ret < 0: # pragma: no cover + raise WolfCryptError("wc_KyberKey_CipherTextSize() error (%d)" % ret) + + return len[0] + + @property + def ss_size(self): + """ + :return: shared secret size in bytes + :rtype: int + """ + len = _ffi.new("word32 *") + ret = _lib.wc_KyberKey_SharedSecretSize(self.native_object, len) + + if ret < 0: # pragma: no cover + raise WolfCryptError("wc_KyberKey_SharedSecretSize() error (%d)" % ret) + + return len[0] + + @property + def _pub_key_size(self): + len = _ffi.new("word32 *") + ret = _lib.wc_KyberKey_PublicKeySize(self.native_object, len) + + if ret < 0: # pragma: no cover + raise WolfCryptError("wc_KyberKey_PublicKeySize() error (%d)" % ret) + + return len[0] + + def _encode_pub_key(self): + pub_key_size = self._pub_key_size + pub_key = _ffi.new(f"unsigned char[{pub_key_size}]") + ret = _lib.wc_KyberKey_EncodePublicKey( + self.native_object, pub_key, pub_key_size + ) + + if ret < 0: # pragma: no cover + raise WolfCryptError("wc_KyberKey_EncodePublicKey() error (%d)" % ret) + + return _ffi.buffer(pub_key, pub_key_size)[:] + + class MlKemPublic(_MlKemBase): + @property + def key_size(self): + """ + :return: public key size in bytes + :rtype: int + """ + return self._pub_key_size + + def encode_key(self): + """ + :return: exported public key + :rtype: bytes + """ + return self._encode_pub_key() + + def decode_key(self, pub_key): + """ + :param pub_key: public key to be imported + :type pub_key: bytes or str + """ + pub_key_bytestype = t2b(pub_key) + ret = _lib.wc_KyberKey_DecodePublicKey( + self.native_object, + _ffi.from_buffer(pub_key_bytestype), + len(pub_key_bytestype), + ) + + if ret < 0: # pragma: no cover + raise WolfCryptError("wc_KyberKey_DecodePublicKey() error (%d)" % ret) + + def encapsulate(self, rng=Random()): + """ + :param rng: random number generator for an encupsulation + :type rng: Random + :return: tuple of a shared secret (first element) and the cipher text (second element) + :rtype: tuple[bytes, bytes] + """ + ct_size = self.ct_size + ss_size = self.ss_size + ct = _ffi.new(f"unsigned char[{ct_size}]") + ss = _ffi.new(f"unsigned char[{ss_size}]") + ret = _lib.wc_KyberKey_Encapsulate( + self.native_object, ct, ss, rng.native_object + ) + + if ret < 0: # pragma: no cover + raise WolfCryptError("wc_KyberKey_Encapsulate() error (%d)" % ret) + + return _ffi.buffer(ss, ss_size)[:], _ffi.buffer(ct, ct_size)[:] + + def encapsulate_with_random(self, rand): + """ + :param rand: random number for an encapsulation + :type rand: bytes + :return: tuple of a shared secret (first element) and the cipher text (second element) + :rtype: tuple[bytes, bytes] + """ + ct_size = self.ct_size + ss_size = self.ss_size + ct = _ffi.new(f"unsigned char[{ct_size}]") + ss = _ffi.new(f"unsigned char[{ss_size}]") + ret = _lib.wc_KyberKey_EncapsulateWithRandom( + self.native_object, ct, ss, _ffi.from_buffer(rand), len(rand) + ) + + if ret < 0: # pragma: no cover + raise WolfCryptError( + "wc_KyberKey_EncapsulateWithRandom() error (%d)" % ret + ) + + return _ffi.buffer(ss, ss_size)[:], _ffi.buffer(ct, ct_size)[:] + + class MlKemPrivate(_MlKemBase): + @classmethod + def make_key(cls, mlkem_type, rng=Random()): + """ + :param mlkem_type: ML-KEM type + :type mlkem_type: MlKemType + :param rng: random number generator for a key generation + :type rng: Random + :return: `MlKemPrivate` object + :rtype: MlKemPrivate + """ + mlkem_priv = cls(mlkem_type) + ret = _lib.wc_KyberKey_MakeKey(mlkem_priv.native_object, rng.native_object) + + if ret < 0: # pragma: no cover + raise WolfCryptError("wc_KyberKey_MakeKey() error (%d)" % ret) + + return mlkem_priv + + @classmethod + def make_key_with_random(cls, mlkem_type, rand): + """ + :param mlkem_type: ML-KEM type + :type mlkem_type: MlKemType + :param rand: random number for a key generation + :type rand: bytes + :return: `MlKemPrivate` object + :rtype: MlKemPrivate + """ + mlkem_priv = cls(mlkem_type) + ret = _lib.wc_KyberKey_MakeKeyWithRandom( + mlkem_priv.native_object, _ffi.from_buffer(rand), len(rand) + ) + + if ret < 0: # pragma: no cover + raise WolfCryptError("wc_KyberKey_MakeKeyWithRandom() error (%d)" % ret) + + return mlkem_priv + + @property + def pub_key_size(self): + """ + :return: public key size in bytes + :rtype: int + """ + return self._pub_key_size + + @property + def priv_key_size(self): + """ + :return: private key size in bytes + :rtype: int + """ + len = _ffi.new("word32 *") + ret = _lib.wc_KyberKey_PrivateKeySize(self.native_object, len) + + if ret < 0: # pragma: no cover + raise WolfCryptError("wc_KyberKey_PrivateKeySize() error (%d)" % ret) + + return len[0] + + def encode_pub_key(self): + """ + :return: exported public key + :rtype: bytes + """ + return self._encode_pub_key() + + def encode_priv_key(self): + """ + :return: exported private key + :rtype: bytes + """ + priv_key_size = self.priv_key_size + priv_key = _ffi.new(f"unsigned char[{priv_key_size}]") + ret = _lib.wc_KyberKey_EncodePrivateKey( + self.native_object, priv_key, priv_key_size + ) + + if ret < 0: # pragma: no cover + raise WolfCryptError("wc_KyberKey_EncodePrivateKey() error (%d)" % ret) + + return _ffi.buffer(priv_key, priv_key_size)[:] + + def decode_key(self, priv_key: tuple[bytes, str]): + """ + :param priv_key: private key to be imported + :type priv_key: bytes or str + """ + priv_key_bytestype = t2b(priv_key) + ret = _lib.wc_KyberKey_DecodePrivateKey( + self.native_object, + _ffi.from_buffer(priv_key_bytestype), + len(priv_key_bytestype), + ) + + if ret < 0: # pragma: no cover + raise WolfCryptError("wc_KyberKey_DecodePrivateKey() error (%d)" % ret) + + def decapsulate(self, ct): + """ + :param ct: cipher text + :type ct: bytes or str + :return: shared secret + :rtype: bytes + """ + ss_size = self.ss_size + ss = _ffi.new(f"unsigned char[{ss_size}]") + ct_bytestype = t2b(ct) + ret = _lib.wc_KyberKey_Decapsulate( + self.native_object, + ss, + _ffi.from_buffer(ct_bytestype), + len(ct_bytestype), + ) + + if ret < 0: # pragma: no cover + self.native_object = None + raise WolfCryptError("wc_KyberKey_Decapsulate() error (%d)" % ret) + + return _ffi.buffer(ss, ss_size)[:] From 2e2d9cd338547f0c98a9dc2e15f9e518beba4687 Mon Sep 17 00:00:00 2001 From: Koji Takeda Date: Sat, 22 Feb 2025 07:42:29 +0900 Subject: [PATCH 2/2] Remove the --enable-experimental configure option --- scripts/build_ffi.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/build_ffi.py b/scripts/build_ffi.py index d7aaf9f..ff18a99 100644 --- a/scripts/build_ffi.py +++ b/scripts/build_ffi.py @@ -233,7 +233,6 @@ def make_flags(prefix, fips): flags.append("--enable-pkcs7") # ML-KEM - flags.append("--enable-experimental") flags.append("--enable-kyber") # disabling other configs enabled by default