diff --git a/include/nil/crypto3/block/detail/sm4/sm4_functions.hpp b/include/nil/crypto3/block/detail/sm4/sm4_functions.hpp new file mode 100644 index 0000000..621b5e0 --- /dev/null +++ b/include/nil/crypto3/block/detail/sm4/sm4_functions.hpp @@ -0,0 +1,68 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2020 Mikhail Komarov +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef CRYPTO3_SM4_FUNCTIONS_CPP_HPP +#define CRYPTO3_SM4_FUNCTIONS_CPP_HPP + +#include + +namespace nil { + namespace crypto3 { + namespace block { + namespace detail { + template + struct sm4_functions : public ::nil::crypto3::detail::basic_functions { + typedef ::nil::crypto3::detail::basic_functions policy_type; + typedef typename policy_type::word_type word_type; + + typedef typename policy_type::byte_type byte_type; + + constexpr static const std::size_t constants_size = 256; + typedef std::array constants_type; + typedef std::array transposed_constants_type; + + inline static word_type t_slow(word_type b, const constants_type &constants) { + const word_type t = ::nil::crypto3::detail::make_uint_t( + constants[::nil::crypto3::detail::extract_uint_t(b, 0)], + constants[::nil::crypto3::detail::extract_uint_t(b, 1)], + constants[::nil::crypto3::detail::extract_uint_t(b, 2)], + constants[::nil::crypto3::detail::extract_uint_t(b, 3)]); + + // L linear transform + return t ^ (policy_type::template rotl<2>(t)) ^ policy_type::template rotl<10>(t) ^ + policy_type::template rotl<18>(t) ^ policy_type::template rotl<24>(t); + } + + inline static word_type t(word_type b, const transposed_constants_type &constants) { + return constants[::nil::crypto3::detail::extract_uint_t(b, 0)] ^ + (policy_type::template rotr<8>( + constants[::nil::crypto3::detail::extract_uint_t(b, 1)])) ^ + policy_type::template rotr<16>( + constants[::nil::crypto3::detail::extract_uint_t(b, 2)]) ^ + policy_type::template rotr<24>( + constants[::nil::crypto3::detail::extract_uint_t(b, 3)]); + } + + // Variant of T for key round_constants_words + inline static word_type tp(word_type b, const constants_type &constants) { + const word_type t = ::nil::crypto3::detail::make_uint_t( + constants[::nil::crypto3::detail::extract_uint_t(b, 0)], + constants[::nil::crypto3::detail::extract_uint_t(b, 1)], + constants[::nil::crypto3::detail::extract_uint_t(b, 2)], + constants[::nil::crypto3::detail::extract_uint_t(b, 3)]); + + // L' linear transform + return t ^ (policy_type::template rotl<13>(t)) ^ policy_type::template rotl<23>(t); + } + }; + } // namespace detail + } // namespace block + } // namespace crypto3 +} // namespace nil + +#endif // CRYPTO3_SM4_FUNCTIONS_CPP_HPP diff --git a/include/nil/crypto3/block/detail/sm4/sm4_policy.hpp b/include/nil/crypto3/block/detail/sm4/sm4_policy.hpp new file mode 100644 index 0000000..0f51518 --- /dev/null +++ b/include/nil/crypto3/block/detail/sm4/sm4_policy.hpp @@ -0,0 +1,110 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2020 Mikhail Komarov +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef CRYPTO3_SM4_POLICY_HPP +#define CRYPTO3_SM4_POLICY_HPP + +#include + +#include + +namespace nil { + namespace crypto3 { + namespace block { + namespace detail { + struct sm4_policy : public sm4_functions<32> { + constexpr static const std::size_t rounds = 32; + + constexpr static const std::size_t block_bits = 128; + constexpr static const std::size_t block_words = block_bits / word_bits; + typedef std::array block_type; + + constexpr static const std::size_t key_bits = 128; + constexpr static const std::size_t key_words = key_bits / word_bits; + typedef std::array key_type; + + constexpr static const std::size_t substitution_size = 256; + typedef std::array constants_type; + typedef std::array transposed_constants_type; + + constexpr static const std::size_t key_schedule_size = 32; + typedef std::array key_schedule_type; + + constexpr static const std::size_t family_key_size = 4; + typedef std::array family_key_type; + + constexpr static const family_key_type fk = {0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc}; + + constexpr static const key_schedule_type ck = { + 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9, + 0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249, 0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9, + 0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229, 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299, + 0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209, 0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279}; + + constexpr static const constants_type constants = { + 0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, + 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, + 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, + 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, + 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, + 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, + 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87, + 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, + 0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, + 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3, + 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, + 0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51, + 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8, + 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, + 0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, + 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48}; + + constexpr static const transposed_constants_type transposed_constants = { + 0x8ED55B5B, 0xD0924242, 0x4DEAA7A7, 0x06FDFBFB, 0xFCCF3333, 0x65E28787, 0xC93DF4F4, 0x6BB5DEDE, + 0x4E165858, 0x6EB4DADA, 0x44145050, 0xCAC10B0B, 0x8828A0A0, 0x17F8EFEF, 0x9C2CB0B0, 0x11051414, + 0x872BACAC, 0xFB669D9D, 0xF2986A6A, 0xAE77D9D9, 0x822AA8A8, 0x46BCFAFA, 0x14041010, 0xCFC00F0F, + 0x02A8AAAA, 0x54451111, 0x5F134C4C, 0xBE269898, 0x6D482525, 0x9E841A1A, 0x1E061818, 0xFD9B6666, + 0xEC9E7272, 0x4A430909, 0x10514141, 0x24F7D3D3, 0xD5934646, 0x53ECBFBF, 0xF89A6262, 0x927BE9E9, + 0xFF33CCCC, 0x04555151, 0x270B2C2C, 0x4F420D0D, 0x59EEB7B7, 0xF3CC3F3F, 0x1CAEB2B2, 0xEA638989, + 0x74E79393, 0x7FB1CECE, 0x6C1C7070, 0x0DABA6A6, 0xEDCA2727, 0x28082020, 0x48EBA3A3, 0xC1975656, + 0x80820202, 0xA3DC7F7F, 0xC4965252, 0x12F9EBEB, 0xA174D5D5, 0xB38D3E3E, 0xC33FFCFC, 0x3EA49A9A, + 0x5B461D1D, 0x1B071C1C, 0x3BA59E9E, 0x0CFFF3F3, 0x3FF0CFCF, 0xBF72CDCD, 0x4B175C5C, 0x52B8EAEA, + 0x8F810E0E, 0x3D586565, 0xCC3CF0F0, 0x7D196464, 0x7EE59B9B, 0x91871616, 0x734E3D3D, 0x08AAA2A2, + 0xC869A1A1, 0xC76AADAD, 0x85830606, 0x7AB0CACA, 0xB570C5C5, 0xF4659191, 0xB2D96B6B, 0xA7892E2E, + 0x18FBE3E3, 0x47E8AFAF, 0x330F3C3C, 0x674A2D2D, 0xB071C1C1, 0x0E575959, 0xE99F7676, 0xE135D4D4, + 0x661E7878, 0xB4249090, 0x360E3838, 0x265F7979, 0xEF628D8D, 0x38596161, 0x95D24747, 0x2AA08A8A, + 0xB1259494, 0xAA228888, 0x8C7DF1F1, 0xD73BECEC, 0x05010404, 0xA5218484, 0x9879E1E1, 0x9B851E1E, + 0x84D75353, 0x00000000, 0x5E471919, 0x0B565D5D, 0xE39D7E7E, 0x9FD04F4F, 0xBB279C9C, 0x1A534949, + 0x7C4D3131, 0xEE36D8D8, 0x0A020808, 0x7BE49F9F, 0x20A28282, 0xD4C71313, 0xE8CB2323, 0xE69C7A7A, + 0x42E9ABAB, 0x43BDFEFE, 0xA2882A2A, 0x9AD14B4B, 0x40410101, 0xDBC41F1F, 0xD838E0E0, 0x61B7D6D6, + 0x2FA18E8E, 0x2BF4DFDF, 0x3AF1CBCB, 0xF6CD3B3B, 0x1DFAE7E7, 0xE5608585, 0x41155454, 0x25A38686, + 0x60E38383, 0x16ACBABA, 0x295C7575, 0x34A69292, 0xF7996E6E, 0xE434D0D0, 0x721A6868, 0x01545555, + 0x19AFB6B6, 0xDF914E4E, 0xFA32C8C8, 0xF030C0C0, 0x21F6D7D7, 0xBC8E3232, 0x75B3C6C6, 0x6FE08F8F, + 0x691D7474, 0x2EF5DBDB, 0x6AE18B8B, 0x962EB8B8, 0x8A800A0A, 0xFE679999, 0xE2C92B2B, 0xE0618181, + 0xC0C30303, 0x8D29A4A4, 0xAF238C8C, 0x07A9AEAE, 0x390D3434, 0x1F524D4D, 0x764F3939, 0xD36EBDBD, + 0x81D65757, 0xB7D86F6F, 0xEB37DCDC, 0x51441515, 0xA6DD7B7B, 0x09FEF7F7, 0xB68C3A3A, 0x932FBCBC, + 0x0F030C0C, 0x03FCFFFF, 0xC26BA9A9, 0xBA73C9C9, 0xD96CB5B5, 0xDC6DB1B1, 0x375A6D6D, 0x15504545, + 0xB98F3636, 0x771B6C6C, 0x13ADBEBE, 0xDA904A4A, 0x57B9EEEE, 0xA9DE7777, 0x4CBEF2F2, 0x837EFDFD, + 0x55114444, 0xBDDA6767, 0x2C5D7171, 0x45400505, 0x631F7C7C, 0x50104040, 0x325B6969, 0xB8DB6363, + 0x220A2828, 0xC5C20707, 0xF531C4C4, 0xA88A2222, 0x31A79696, 0xF9CE3737, 0x977AEDED, 0x49BFF6F6, + 0x992DB4B4, 0xA475D1D1, 0x90D34343, 0x5A124848, 0x58BAE2E2, 0x71E69797, 0x64B6D2D2, 0x70B2C2C2, + 0xAD8B2626, 0xCD68A5A5, 0xCB955E5E, 0x624B2929, 0x3C0C3030, 0xCE945A5A, 0xAB76DDDD, 0x867FF9F9, + 0xF1649595, 0x5DBBE6E6, 0x35F2C7C7, 0x2D092424, 0xD1C61717, 0xD66FB9B9, 0xDEC51B1B, 0x94861212, + 0x78186060, 0x30F3C3C3, 0x897CF5F5, 0x5CEFB3B3, 0xD23AE8E8, 0xACDF7373, 0x794C3535, 0xA0208080, + 0x9D78E5E5, 0x56EDBBBB, 0x235E7D7D, 0xC63EF8F8, 0x8BD45F5F, 0xE7C82F2F, 0xDD39E4E4, 0x68492121}; + }; + + constexpr sm4_policy::constants_type const sm4_policy::constants; + constexpr sm4_policy::transposed_constants_type const sm4_policy::transposed_constants; + constexpr sm4_policy::key_schedule_type const sm4_policy::ck; + } // namespace detail + } // namespace block + } // namespace crypto3 +} // namespace nil + +#endif // CRYPTO3_SM4_POLICY_HPP diff --git a/include/nil/crypto3/block/sm4.hpp b/include/nil/crypto3/block/sm4.hpp new file mode 100644 index 0000000..b695cbe --- /dev/null +++ b/include/nil/crypto3/block/sm4.hpp @@ -0,0 +1,150 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2020 Mikhail Komarov +// Copyright (c) 2020 Nikita Kaskov +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#ifndef CRYPTO3_BLOCK_SM4_HPP +#define CRYPTO3_BLOCK_SM4_HPP + +#include + +#include + +#include +#include + +namespace nil { + namespace crypto3 { + namespace block { + /*! + * @brief SM4. A 128-bit Chinese national cipher, required for use + * in certain commercial applications in China. Quite slow. Probably + * no reason to use it outside of legal requirements. + * + * @ingroup block + */ + class sm4 { + protected: + typedef detail::sm4_policy policy_type; + + constexpr static const std::size_t key_schedule_size = policy_type::key_schedule_size; + typedef typename policy_type::key_schedule_type key_schedule_type; + + public: + constexpr static const std::size_t rounds = policy_type::rounds; + + constexpr static const std::size_t word_bits = policy_type::word_bits; + typedef typename policy_type::word_type word_type; + + constexpr static const std::size_t block_bits = policy_type::block_bits; + constexpr static const std::size_t block_words = policy_type::block_words; + typedef typename policy_type::block_type block_type; + + constexpr static const std::size_t key_bits = policy_type::key_bits; + constexpr static const std::size_t key_words = policy_type::key_words; + typedef typename policy_type::key_type key_type; + + template + struct stream_processor { + struct params_type { + + constexpr static const std::size_t value_bits = ValueBits; + constexpr static const std::size_t length_bits = policy_type::word_bits * 2; + }; + + typedef block_stream_processor type; + }; + + + typedef typename stream_endian::little_octet_big_bit endian_type; + + sm4(const key_type &key) { + schedule_key(key); + } + + ~sm4() { + key_schedule.fill(0); + } + + inline block_type encrypt(const block_type &plaintext) const { + return encrypt_block(plaintext); + } + + inline block_type decrypt(const block_type &ciphertext) const { + return decrypt_block(ciphertext); + } + + protected: +#define SM4_RNDS(k0, k1, k2, k3, F, C) \ + do { \ + B0 ^= F(B1 ^ B2 ^ B3 ^ key_schedule[k0], C); \ + B1 ^= F(B0 ^ B2 ^ B3 ^ key_schedule[k1], C); \ + B2 ^= F(B0 ^ B1 ^ B3 ^ key_schedule[k2], C); \ + B3 ^= F(B0 ^ B1 ^ B2 ^ key_schedule[k3], C); \ + } while (0) + + key_schedule_type key_schedule; + + inline block_type encrypt_block(const block_type &plaintext) const { + word_type B0 = boost::endian::native_to_big(plaintext[0]); + word_type B1 = boost::endian::native_to_big(plaintext[1]); + word_type B2 = boost::endian::native_to_big(plaintext[2]); + word_type B3 = boost::endian::native_to_big(plaintext[3]); + + SM4_RNDS(0, 1, 2, 3, policy_type::t_slow, policy_type::constants); + SM4_RNDS(4, 5, 6, 7, policy_type::t, policy_type::transposed_constants); + SM4_RNDS(8, 9, 10, 11, policy_type::t, policy_type::transposed_constants); + SM4_RNDS(12, 13, 14, 15, policy_type::t, policy_type::transposed_constants); + SM4_RNDS(16, 17, 18, 19, policy_type::t, policy_type::transposed_constants); + SM4_RNDS(20, 21, 22, 23, policy_type::t, policy_type::transposed_constants); + SM4_RNDS(24, 25, 26, 27, policy_type::t, policy_type::transposed_constants); + SM4_RNDS(28, 29, 30, 31, policy_type::t_slow, policy_type::constants); + + return {boost::endian::big_to_native(B3), boost::endian::big_to_native(B2), + boost::endian::big_to_native(B1), boost::endian::big_to_native(B0)}; + } + + inline block_type decrypt_block(const block_type &plaintext) const { + word_type B0 = boost::endian::native_to_big(plaintext[0]); + word_type B1 = boost::endian::native_to_big(plaintext[1]); + word_type B2 = boost::endian::native_to_big(plaintext[2]); + word_type B3 = boost::endian::native_to_big(plaintext[3]); + + SM4_RNDS(31, 30, 29, 28, policy_type::t_slow, policy_type::constants); + SM4_RNDS(27, 26, 25, 24, policy_type::t, policy_type::transposed_constants); + SM4_RNDS(23, 22, 21, 20, policy_type::t, policy_type::transposed_constants); + SM4_RNDS(19, 18, 17, 16, policy_type::t, policy_type::transposed_constants); + SM4_RNDS(15, 14, 13, 12, policy_type::t, policy_type::transposed_constants); + SM4_RNDS(11, 10, 9, 8, policy_type::t, policy_type::transposed_constants); + SM4_RNDS(7, 6, 5, 4, policy_type::t, policy_type::transposed_constants); + SM4_RNDS(3, 2, 1, 0, policy_type::t_slow, policy_type::constants); + + return {boost::endian::big_to_native(B3), boost::endian::big_to_native(B2), + boost::endian::big_to_native(B1), boost::endian::big_to_native(B0)}; + } + + void schedule_key(const key_type &key) { + std::array K = {0}; + K[0] = boost::endian::native_to_big(key[0]) ^ policy_type::fk[0]; + K[1] = boost::endian::native_to_big(key[1]) ^ policy_type::fk[1]; + K[2] = boost::endian::native_to_big(key[2]) ^ policy_type::fk[2]; + K[3] = boost::endian::native_to_big(key[3]) ^ policy_type::fk[3]; + + for (size_t i = 0; i != 32; ++i) { + K[i % 4] ^= + policy_type::tp(K[(i + 1) % 4] ^ K[(i + 2) % 4] ^ K[(i + 3) % 4] ^ policy_type::ck[i], + policy_type::constants); + key_schedule[i] = K[i % 4]; + } + + K.fill(0); + } + }; + } // namespace block + } // namespace crypto3 +} // namespace nil +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6e6c334..c12c7ff 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -43,6 +43,7 @@ set(TESTS_NAMES "md5" "shacal" "shacal2" + "sm4" ) foreach(TEST_NAME ${TESTS_NAMES}) diff --git a/test/sm4.cpp b/test/sm4.cpp new file mode 100644 index 0000000..ab78091 --- /dev/null +++ b/test/sm4.cpp @@ -0,0 +1,71 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2018-2020 Mikhail Komarov +// +// Distributed under the Boost Software License, Version 1.0 +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +//---------------------------------------------------------------------------// + +#define BOOST_TEST_MODULE sm4_cipher_test + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +using namespace nil::crypto3::block; + +namespace boost { + namespace test_tools { + namespace tt_detail { + template class P, typename K, typename V> + struct print_log_value> { + void operator()(std::ostream&, P const&) { + } + }; + } // namespace tt_detail + } // namespace test_tools +} // namespace boost + +static const std::unordered_map> valid_data = { + {"Zg==", {0x66}}, + {"Zm8=", {0x66, 0x6F}}, + {"Zm9v", {0x66, 0x6F, 0x6F}}, + {"aGVsbG8gd29ybGQ=", {0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64}}, + {"aGVsbG8gd29ybGQh", {0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21}}, + {"SGVsbG8sIHdvcmxkLg==", {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x2E}}, + {"VGhlIDEyIGNoYXJz", {0x54, 0x68, 0x65, 0x20, 0x31, 0x32, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73}}, + {"VGhlIDEzIGNoYXJzLg==", {0x54, 0x68, 0x65, 0x20, 0x31, 0x33, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x2E}}, + {"VGhlIDE0IGNoYXJzLi4=", {0x54, 0x68, 0x65, 0x20, 0x31, 0x34, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x2E, 0x2E}}, + {"VGhlIDE1IGNoYXJzLi4u", + {0x54, 0x68, 0x65, 0x20, 0x31, 0x35, 0x20, 0x63, 0x68, 0x61, 0x72, 0x73, 0x2E, 0x2E, 0x2E}}, + {"QW4gVVRGLTggdXVtbDogw7w=", + {0x41, 0x6E, 0x20, 0x55, 0x54, 0x46, 0x2D, 0x38, 0x20, 0x75, 0x75, 0x6D, 0x6C, 0x3A, 0x20, 0xC3, 0xBC}}, + {"V2VpcmQgR2VybWFuIDIgYnl0ZSB0aGluZzogw58u", + {0x57, 0x65, 0x69, 0x72, 0x64, 0x20, 0x47, 0x65, 0x72, 0x6D, 0x61, 0x6E, 0x20, 0x32, 0x20, + 0x62, 0x79, 0x74, 0x65, 0x20, 0x74, 0x68, 0x69, 0x6E, 0x67, 0x3A, 0x20, 0xC3, 0x9F, 0x2E}}, + {"mw==", {0x9B}}, + {"HGA=", {0x1C, 0x60}}, + {"gTS9", {0x81, 0x34, 0xBD}}, + {"Xmz/3g==", {0x5E, 0x6C, 0xFF, 0xDE}}, + {"ss3w3H8=", {0xb2, 0xcd, 0xf0, 0xdc, 0x7f}}, + {"/FYt2tQO", {0xfc, 0x56, 0x2d, 0xda, 0xd4, 0x0e}}, + {"KbIyLohB6A==", {0x29, 0xb2, 0x32, 0x2e, 0x88, 0x41, 0xe8}}, + {"Dw/O2Ul6r5I=", {0x0f, 0x0f, 0xce, 0xd9, 0x49, 0x7a, 0xaf, 0x92}}, + {"Jw+xiYKADaZA", {0x27, 0x0f, 0xb1, 0x89, 0x82, 0x80, 0x0d, 0xa6, 0x40}}}; + +static const std::vector invalid_data = {"ZOOL!isnotvalidbase64", "Neitheris:this?"}; + +BOOST_AUTO_TEST_SUITE(sm4_encode_test_suite) + +BOOST_DATA_TEST_CASE(sm4_single_range_encode, boost::unit_test::data::make(valid_data), array_element) { +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file