diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 6a6f163d..df295984 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -65,6 +65,7 @@ jobs: cd build $NIGHTLY_BUILD_FLAGS ./bls_unit_test $NIGHTLY_BUILD_FLAGS ./dkg_unit_test + $NIGHTLY_BUILD_FLAGS ./utils_unit_test $NIGHTLY_BUILD_FLAGS ./bls_test $NIGHTLY_BUILD_FLAGS ./threshold_encryption/te_unit_test $NIGHTLY_BUILD_FLAGS ./threshold_encryption/te_test diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 886bb6f8..1a9f082d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -75,6 +75,7 @@ jobs: cd build ./bls_unit_test ./dkg_unit_test + ./utils_unit_test ./bls_test ./threshold_encryption/te_unit_test ./threshold_encryption/te_test diff --git a/CMakeLists.txt b/CMakeLists.txt index ccf2ee33..02034c5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ list( APPEND CMAKE_MODULE_PATH ${LIBBLS_CMAKE_DIR} ) find_library( GMP_LIBRARY NAMES "gmp" PATHS "${DEPS_INSTALL_ROOT}/lib" ) find_library( GMPXX_LIBRARY NAMES "gmpxx" PATHS "${DEPS_INSTALL_ROOT}/lib" ) +find_library( CRYPTOPP NAMES "crypto" PATHS "${DEPS_INSTALL_ROOT}/lib" ) set( HUNTER_ENABLED OFF ) @@ -134,70 +135,77 @@ set(BLS_INCLUDE_DIRS ) target_include_directories(bls PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(bls PRIVATE ff ${GMPXX_LIBRARY} ${GMP_LIBRARY}) +target_link_libraries(bls PRIVATE ff ${CRYPTOPP} ${GMPXX_LIBRARY} ${GMP_LIBRARY}) add_subdirectory(threshold_encryption) add_executable(dkg_keygen tools/dkg_key_gen.cpp) target_include_directories(dkg_keygen PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(dkg_keygen PRIVATE bls ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) +target_link_libraries(dkg_keygen PRIVATE bls ${CRYPTOPP} ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) add_executable(dkg_glue tools/dkg_glue.cpp) target_include_directories(dkg_glue PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(dkg_glue PRIVATE bls ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) +target_link_libraries(dkg_glue PRIVATE bls ${CRYPTOPP} ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) add_executable(sign_bls tools/sign_bls.cpp) target_include_directories(sign_bls PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(sign_bls PRIVATE bls ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) +target_link_libraries(sign_bls PRIVATE bls ${CRYPTOPP} ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) add_executable(hash_g1 tools/hash_g1.cpp) target_include_directories(hash_g1 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(hash_g1 PRIVATE bls ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) +target_link_libraries(hash_g1 PRIVATE bls ${CRYPTOPP} ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) add_executable(bls_glue tools/bls_glue.cpp) target_include_directories(bls_glue PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(bls_glue PRIVATE bls ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) +target_link_libraries(bls_glue PRIVATE bls ${CRYPTOPP} ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) add_executable(verify_bls tools/verify_bls.cpp) target_include_directories(verify_bls PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(verify_bls PRIVATE bls ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) +target_link_libraries(verify_bls PRIVATE bls ${CRYPTOPP} ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) add_executable(generate_key_system tools/generate_key_system.cpp) target_include_directories(generate_key_system PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -target_link_libraries(generate_key_system PRIVATE bls ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) +target_link_libraries(generate_key_system PRIVATE bls ${CRYPTOPP} ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) if(BUILD_TESTS) add_executable(bls_unit_test test/unit_tests_bls.cpp) target_include_directories(bls_unit_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - target_link_libraries(bls_unit_test PRIVATE bls ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) + target_link_libraries(bls_unit_test PRIVATE bls ${CRYPTOPP} ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) add_test(NAME bls_tests COMMAND bls_unit_test) add_executable(dkg_unit_test test/unit_tests_dkg.cpp) target_include_directories(dkg_unit_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - target_link_libraries(dkg_unit_test PRIVATE bls ff ${GMP_LIBRARY} ${GMPXX_LIBRARY} ${BOOST_LIBS_4_BLS}) + target_link_libraries(dkg_unit_test PRIVATE bls ${CRYPTOPP} ff ${GMP_LIBRARY} ${GMPXX_LIBRARY} ${BOOST_LIBS_4_BLS}) add_test(NAME dkg_tests COMMAND dkg_unit_test) add_executable(bls_test test/test_bls.cpp) target_include_directories(bls_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - target_link_libraries(bls_test PRIVATE bls ff ${GMP_LIBRARY} ${GMPXX_LIBRARY} ${BOOST_LIBS_4_BLS}) + target_link_libraries(bls_test PRIVATE bls ${CRYPTOPP} ff ${GMP_LIBRARY} ${GMPXX_LIBRARY} ${BOOST_LIBS_4_BLS}) add_test(NAME bls_test COMMAND bls_test) add_executable(dkg_attack test/dkg_attack.cpp) target_include_directories(dkg_attack PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - target_link_libraries(dkg_attack PRIVATE bls ff ${GMP_LIBRARY} ${GMPXX_LIBRARY} ${BOOST_LIBS_4_BLS}) + target_link_libraries(dkg_attack PRIVATE bls ${CRYPTOPP} ff ${GMP_LIBRARY} ${GMPXX_LIBRARY} ${BOOST_LIBS_4_BLS}) add_test(NAME dkg_attack COMMAND dkg_attack) + add_executable(utils_unit_test test/unit_tests_utils.cpp) + target_include_directories(utils_unit_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + target_link_libraries(utils_unit_test PRIVATE bls te ${CRYPTOPP} ff ${GMPXX_LIBRARY} ${GMP_LIBRARY} ${BOOST_LIBS_4_BLS}) + + add_test(NAME utils_tests COMMAND utils_unit_test) + add_custom_target(all_bls_tests COMMAND ./bls_unit_test COMMAND ./dkg_unit_test COMMAND ./bls_test - COMMAND ./dkg_attack + COMMAND ./dkg_attack + COMMAND ./utils_unit_test DEPENDS bls_unit_test dkg_unit_test WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Run all BLS and DKG tests" diff --git a/deps/build.sh b/deps/build.sh index 5b288a20..6a8359d9 100755 --- a/deps/build.sh +++ b/deps/build.sh @@ -638,7 +638,7 @@ then export KERNEL_BITS=64 ./Configure darwin64-x86_64-cc -fPIC no-shared --prefix="$INSTALL_ROOT" else - ./config -fPIC no-shared --prefix="$INSTALL_ROOT" --openssldir="$INSTALL_ROOT" + ./config -fPIC --prefix="$INSTALL_ROOT" --openssldir="$INSTALL_ROOT" fi else ./Configure linux-armv4 --prefix="$INSTALL_ROOT" "${ADDITIONAL_INCLUDES}" "${ADDITIONAL_LIBRARIES}" no-shared no-tests no-dso diff --git a/test/test_TE_wrappers.cpp b/test/test_TE_wrappers.cpp index c95cd43a..3a99f1a6 100644 --- a/test/test_TE_wrappers.cpp +++ b/test/test_TE_wrappers.cpp @@ -262,7 +262,6 @@ BOOST_AUTO_TEST_CASE( ThresholdEncryptionWithDKG ) { public_shares_all.push_back( *public_shares_ptr ); } - for ( size_t i = 0; i < num_all; i++ ) for ( size_t j = 0; j < num_all; j++ ) { BOOST_REQUIRE( dkgs.at( i ).VerifyDKGShare( j, secret_shares_all.at( i ).at( j ), @@ -288,32 +287,6 @@ BOOST_AUTO_TEST_CASE( ThresholdEncryptionWithDKG ) { pkeys.push_back( TEPublicKeyShare( pkey_share, num_signed, num_all ) ); } - /* element_t public_key; - element_init_G1(public_key, TEDataSingleton::getData().pairing_); - element_set0(public_key); - - for (size_t i = 0; i < num_all; i++) { - - element_t temp; - element_init_G1(temp, TEDataSingleton::getData().pairing_); - element_set(temp, public_shares_all.at(i).at(0).el_); - - element_t value; - element_init_G1(value, TEDataSingleton::getData().pairing_); - element_add(value, public_key, temp); - - element_clear(temp); - element_clear(public_key); - element_init_G1(public_key, TEDataSingleton::getData().pairing_); - - element_set(public_key, value); - - element_clear(value); - } - - TEPublicKey common_public(crypto::element_wrapper(public_key), num_signed, num_all); - element_clear(public_key);*/ - TEPublicKey common_public = DKGTEWrapper::CreateTEPublicKey( std::make_shared< std::vector< std::vector< libff::alt_bn128_G2 > > >( public_shares_all ), @@ -352,287 +325,282 @@ BOOST_AUTO_TEST_CASE( ThresholdEncryptionWithDKG ) { } BOOST_AUTO_TEST_CASE( ExceptionsTest ) { - for ( size_t i = 0; i < 1; i++ ) { - size_t num_all = rand_gen() % 15 + 2; - size_t num_signed = rand_gen() % num_all + 1; + size_t num_all = rand_gen() % 15 + 2; + size_t num_signed = rand_gen() % num_all + 1; - BOOST_REQUIRE_THROW( crypto::ThresholdUtils::checkSigners( 0, num_all ), - crypto::ThresholdUtils::IncorrectInput ); + BOOST_REQUIRE_THROW( crypto::ThresholdUtils::checkSigners( 0, num_all ), + crypto::ThresholdUtils::IncorrectInput ); - BOOST_REQUIRE_THROW( - crypto::ThresholdUtils::checkSigners( 0, 0 ), crypto::ThresholdUtils::IncorrectInput ); + BOOST_REQUIRE_THROW( + crypto::ThresholdUtils::checkSigners( 0, 0 ), crypto::ThresholdUtils::IncorrectInput ); - // null public key share - BOOST_REQUIRE_THROW( TEPublicKeyShare( nullptr, 1, num_signed, num_all ), - crypto::ThresholdUtils::IncorrectInput ); + // null public key share + BOOST_REQUIRE_THROW( TEPublicKeyShare( nullptr, 1, num_signed, num_all ), + crypto::ThresholdUtils::IncorrectInput ); - { - // 1 coord of public key share is not digit - std::vector< std::string > pkey_str( {"123", "abc"} ); - BOOST_REQUIRE_THROW( - TEPublicKeyShare( std::make_shared< std::vector< std::string > >( pkey_str ), 1, - num_signed, num_all ), - crypto::ThresholdUtils::IncorrectInput ); - } + { + // 1 coord of public key share is not a number + std::vector< std::string > pkey_str( {"123", "abc"} ); + BOOST_REQUIRE_THROW( + TEPublicKeyShare( std::make_shared< std::vector< std::string > >( pkey_str ), 1, + num_signed, num_all ), + crypto::ThresholdUtils::IncorrectInput ); + } - { - // zero public key share - std::vector< std::string > pkey_str( {"0", "0"} ); - BOOST_REQUIRE_THROW( - TEPublicKeyShare( std::make_shared< std::vector< std::string > >( pkey_str ), 1, - num_signed, num_all ), - crypto::ThresholdUtils::IncorrectInput ); - } + { + // wrong formated public key share + std::vector< std::string > pkey_str( {"0", "0", "0", "0"} ); + BOOST_REQUIRE_THROW( + TEPublicKeyShare( std::make_shared< std::vector< std::string > >( pkey_str ), 1, + num_signed, num_all ), + crypto::ThresholdUtils::IsNotWellFormed ); + } - { - // one component public key share - std::vector< std::string > pkey_str( {"1232450"} ); - BOOST_REQUIRE_THROW( - TEPublicKeyShare( std::make_shared< std::vector< std::string > >( pkey_str ), 1, - num_signed, num_all ), - crypto::ThresholdUtils::IncorrectInput ); - } + { + // one component public key share + std::vector< std::string > pkey_str( {"1232450"} ); + BOOST_REQUIRE_THROW( + TEPublicKeyShare( std::make_shared< std::vector< std::string > >( pkey_str ), 1, + num_signed, num_all ), + crypto::ThresholdUtils::IncorrectInput ); + } - { - // one zero component in cypher - libff::alt_bn128_Fr el = libff::alt_bn128_Fr::random_element(); - TEPublicKeyShare pkey( - TEPrivateKeyShare( el, 1, num_signed, num_all ), num_signed, num_all ); + { + // one zero component in cypher + libff::alt_bn128_Fr el = libff::alt_bn128_Fr::random_element(); + TEPublicKeyShare pkey( + TEPrivateKeyShare( el, 1, num_signed, num_all ), num_signed, num_all ); - libff::alt_bn128_G2 U = libff::alt_bn128_G2::zero(); + libff::alt_bn128_G2 U = libff::alt_bn128_G2::zero(); - libff::alt_bn128_G1 W = libff::alt_bn128_G1::random_element(); + libff::alt_bn128_G1 W = libff::alt_bn128_G1::random_element(); - crypto::Ciphertext cypher; - std::get< 0 >( cypher ) = U; - std::get< 1 >( cypher ) = "tra-la-la"; - std::get< 2 >( cypher ) = W; + crypto::Ciphertext cypher; + std::get< 0 >( cypher ) = U; + std::get< 1 >( cypher ) = "tra-la-la"; + std::get< 2 >( cypher ) = W; - BOOST_REQUIRE_THROW( pkey.Verify( cypher, U ), crypto::ThresholdUtils::IncorrectInput ); - } + BOOST_REQUIRE_THROW( pkey.Verify( cypher, U ), crypto::ThresholdUtils::IncorrectInput ); + } - { - // wrong string length in cypher - libff::alt_bn128_Fr el = libff::alt_bn128_Fr::random_element(); + { + // wrong string length in cypher + libff::alt_bn128_Fr el = libff::alt_bn128_Fr::random_element(); - TEPublicKeyShare pkey( - TEPrivateKeyShare( el, 1, num_signed, num_all ), num_signed, num_all ); - libff::alt_bn128_G2 U = libff::alt_bn128_G2::random_element(); + TEPublicKeyShare pkey( + TEPrivateKeyShare( el, 1, num_signed, num_all ), num_signed, num_all ); + libff::alt_bn128_G2 U = libff::alt_bn128_G2::random_element(); - libff::alt_bn128_G1 W = libff::alt_bn128_G1::random_element(); + libff::alt_bn128_G1 W = libff::alt_bn128_G1::random_element(); - crypto::Ciphertext cypher; - std::get< 0 >( cypher ) = U; - std::get< 1 >( cypher ) = "tra-la-la"; - std::get< 2 >( cypher ) = W; + crypto::Ciphertext cypher; + std::get< 0 >( cypher ) = U; + std::get< 1 >( cypher ) = "tra-la-la"; + std::get< 2 >( cypher ) = W; - BOOST_REQUIRE_THROW( pkey.Verify( cypher, U ), crypto::ThresholdUtils::IncorrectInput ); - } + BOOST_REQUIRE_THROW( pkey.Verify( cypher, U ), crypto::ThresholdUtils::IncorrectInput ); + } - { - // zero decrypted - libff::alt_bn128_Fr el = libff::alt_bn128_Fr::random_element(); - TEPublicKeyShare pkey( - TEPrivateKeyShare( el, 1, num_signed, num_all ), num_signed, num_all ); + { + // zero decrypted + libff::alt_bn128_Fr el = libff::alt_bn128_Fr::random_element(); + TEPublicKeyShare pkey( + TEPrivateKeyShare( el, 1, num_signed, num_all ), num_signed, num_all ); - libff::alt_bn128_G2 U = libff::alt_bn128_G2::random_element(); + libff::alt_bn128_G2 U = libff::alt_bn128_G2::random_element(); - libff::alt_bn128_G1 W = libff::alt_bn128_G1::random_element(); + libff::alt_bn128_G1 W = libff::alt_bn128_G1::random_element(); - crypto::Ciphertext cypher; - std::get< 0 >( cypher ) = U; - std::get< 1 >( cypher ) = - "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; - std::get< 2 >( cypher ) = W; + crypto::Ciphertext cypher; + std::get< 0 >( cypher ) = U; + std::get< 1 >( cypher ) = + "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; + std::get< 2 >( cypher ) = W; - libff::alt_bn128_G2 decrypt = libff::alt_bn128_G2::zero(); + libff::alt_bn128_G2 decrypt = libff::alt_bn128_G2::zero(); - BOOST_REQUIRE_THROW( - pkey.Verify( cypher, decrypt ), crypto::ThresholdUtils::IsNotWellFormed ); - } + BOOST_REQUIRE_THROW( + pkey.Verify( cypher, decrypt ), crypto::ThresholdUtils::IsNotWellFormed ); + } - { - // null private key share - BOOST_REQUIRE_THROW( TEPrivateKeyShare( nullptr, 1, num_signed, num_all ), - crypto::ThresholdUtils::IncorrectInput ); - } + { + // null private key share + BOOST_REQUIRE_THROW( TEPrivateKeyShare( nullptr, 1, num_signed, num_all ), + crypto::ThresholdUtils::IncorrectInput ); + } - { - // zero private key share - std::string zero_str = "0"; - BOOST_REQUIRE_THROW( TEPrivateKeyShare( std::make_shared< std::string >( zero_str ), 1, - num_signed, num_all ), - crypto::ThresholdUtils::ZeroSecretKey ); - } + { + // zero private key share + std::string zero_str = "0"; + BOOST_REQUIRE_THROW( TEPrivateKeyShare( std::make_shared< std::string >( zero_str ), 1, + num_signed, num_all ), + crypto::ThresholdUtils::ZeroSecretKey ); + } - { - // zero private key share - libff::alt_bn128_Fr el = libff::alt_bn128_Fr::zero(); - BOOST_REQUIRE_THROW( TEPrivateKeyShare( el, 1, num_signed, num_all ), - crypto::ThresholdUtils::ZeroSecretKey ); - } + { + // zero private key share + libff::alt_bn128_Fr el = libff::alt_bn128_Fr::zero(); + BOOST_REQUIRE_THROW( TEPrivateKeyShare( el, 1, num_signed, num_all ), + crypto::ThresholdUtils::ZeroSecretKey ); + } - { - // wrong signer index - BOOST_REQUIRE_THROW( TEPrivateKeyShare( libff::alt_bn128_Fr::random_element(), - num_all + 1, num_signed, num_all ), - crypto::ThresholdUtils::IncorrectInput ); - } + { + // wrong signer index + BOOST_REQUIRE_THROW( TEPrivateKeyShare( libff::alt_bn128_Fr::random_element(), num_all + 1, + num_signed, num_all ), + crypto::ThresholdUtils::IncorrectInput ); + } - { - // null public key - BOOST_REQUIRE_THROW( TEPublicKey( nullptr, num_signed, num_all ), - crypto::ThresholdUtils::IncorrectInput ); - } + { + // null public key + BOOST_REQUIRE_THROW( + TEPublicKey( nullptr, num_signed, num_all ), crypto::ThresholdUtils::IncorrectInput ); + } - { - // wrong formated public key - std::vector< std::string > pkey_str( {"0", "0", "0", "0"} ); - BOOST_REQUIRE_THROW( - TEPublicKey( std::make_shared< std::vector< std::string > >( pkey_str ), num_signed, - num_all ), - crypto::ThresholdUtils::IsNotWellFormed ); - } + { + // wrong formated public key + std::vector< std::string > pkey_str( {"0", "0", "0", "0"} ); + BOOST_REQUIRE_THROW( + TEPublicKey( + std::make_shared< std::vector< std::string > >( pkey_str ), num_signed, num_all ), + crypto::ThresholdUtils::IsNotWellFormed ); + } - { - // zero public key - libff::alt_bn128_Fr el = libff::alt_bn128_Fr::zero(); - BOOST_REQUIRE_THROW( - TEPublicKey pkey( TEPrivateKey( el, num_signed, num_all ), num_signed, num_all ), - crypto::ThresholdUtils::IsNotWellFormed ); - } + { + // zero public key + libff::alt_bn128_Fr el = libff::alt_bn128_Fr::zero(); + BOOST_REQUIRE_THROW( + TEPublicKey pkey( TEPrivateKey( el, num_signed, num_all ), num_signed, num_all ), + crypto::ThresholdUtils::IsNotWellFormed ); + } - { - // zero public key - libff::alt_bn128_G2 el = libff::alt_bn128_G2::zero(); - BOOST_REQUIRE_THROW( TEPublicKey pkey( el, num_signed, num_all ), - crypto::ThresholdUtils::IsNotWellFormed ); - } + { + // zero public key + libff::alt_bn128_G2 el = libff::alt_bn128_G2::zero(); + BOOST_REQUIRE_THROW( + TEPublicKey pkey( el, num_signed, num_all ), crypto::ThresholdUtils::IsNotWellFormed ); + } - { - // null message - libff::alt_bn128_G2 el = libff::alt_bn128_G2::random_element(); + { + // null message + libff::alt_bn128_G2 el = libff::alt_bn128_G2::random_element(); - TEPublicKey pkey( el, num_signed, num_all ); + TEPublicKey pkey( el, num_signed, num_all ); - BOOST_REQUIRE_THROW( pkey.encrypt( nullptr ), crypto::ThresholdUtils::IncorrectInput ); - } + BOOST_REQUIRE_THROW( pkey.encrypt( nullptr ), crypto::ThresholdUtils::IncorrectInput ); + } - { - // message length is not 64 - libff::alt_bn128_G2 el = libff::alt_bn128_G2::random_element(); + { + // message length is not 64 + libff::alt_bn128_G2 el = libff::alt_bn128_G2::random_element(); - TEPublicKey pkey( el, num_signed, num_all ); + TEPublicKey pkey( el, num_signed, num_all ); - BOOST_REQUIRE_THROW( pkey.encrypt( std::make_shared< std::string >( "tra-la-la" ) ), - crypto::ThresholdUtils::IncorrectInput ); - } + BOOST_REQUIRE_THROW( pkey.encrypt( std::make_shared< std::string >( "tra-la-la" ) ), + crypto::ThresholdUtils::IncorrectInput ); + } - { - // null private key - BOOST_REQUIRE_THROW( TEPrivateKey( nullptr, num_signed, num_all ), - crypto::ThresholdUtils::IncorrectInput ); - } + { + // null private key + BOOST_REQUIRE_THROW( + TEPrivateKey( nullptr, num_signed, num_all ), crypto::ThresholdUtils::IncorrectInput ); + } - { - // zero private key - std::string zero_str = "0"; - BOOST_REQUIRE_THROW( - TEPrivateKey( std::make_shared< std::string >( zero_str ), num_signed, num_all ), - crypto::ThresholdUtils::IsNotWellFormed ); - } + { + // zero private key + std::string zero_str = "0"; + BOOST_REQUIRE_THROW( + TEPrivateKey( std::make_shared< std::string >( zero_str ), num_signed, num_all ), + crypto::ThresholdUtils::IsNotWellFormed ); + } - { - // zero private key - libff::alt_bn128_Fr el = libff::alt_bn128_Fr::zero(); - BOOST_REQUIRE_THROW( - TEPrivateKey( el, num_signed, num_all ), crypto::ThresholdUtils::IsNotWellFormed ); - } + { + // zero private key + libff::alt_bn128_Fr el = libff::alt_bn128_Fr::zero(); + BOOST_REQUIRE_THROW( + TEPrivateKey( el, num_signed, num_all ), crypto::ThresholdUtils::IsNotWellFormed ); + } - { - //_requiredSigners > _totalSigners - BOOST_REQUIRE_THROW( TEDecryptSet decr_set( num_all + 1, num_signed ), - crypto::ThresholdUtils::IsNotWellFormed ); - } + { + //_requiredSigners > _totalSigners + BOOST_REQUIRE_THROW( TEDecryptSet decr_set( num_all + 1, num_signed ), + crypto::ThresholdUtils::IsNotWellFormed ); + } - { - // same indices in decrypt set - TEDecryptSet decr_set( num_signed, num_all ); + { + // same indices in decrypt set + TEDecryptSet decr_set( num_signed, num_all ); - libff::alt_bn128_G2 el1 = libff::alt_bn128_G2::random_element(); - auto el_ptr1 = std::make_shared< libff::alt_bn128_G2 >( el1 ); + libff::alt_bn128_G2 el1 = libff::alt_bn128_G2::random_element(); + auto el_ptr1 = std::make_shared< libff::alt_bn128_G2 >( el1 ); - libff::alt_bn128_G2 el2 = libff::alt_bn128_G2::random_element(); - auto el_ptr2 = std::make_shared< libff::alt_bn128_G2 >( el2 ); + libff::alt_bn128_G2 el2 = libff::alt_bn128_G2::random_element(); + auto el_ptr2 = std::make_shared< libff::alt_bn128_G2 >( el2 ); - decr_set.addDecrypt( 1, el_ptr1 ); - BOOST_REQUIRE_THROW( - decr_set.addDecrypt( 1, el_ptr2 ), crypto::ThresholdUtils::IncorrectInput ); - } + decr_set.addDecrypt( 1, el_ptr1 ); + BOOST_REQUIRE_THROW( + decr_set.addDecrypt( 1, el_ptr2 ), crypto::ThresholdUtils::IncorrectInput ); + } - { - // zero element in decrypt set - TEDecryptSet decr_set( num_signed, num_all ); + { + // zero element in decrypt set + TEDecryptSet decr_set( num_signed, num_all ); - libff::alt_bn128_G2 el1 = libff::alt_bn128_G2::zero(); - auto el_ptr1 = std::make_shared< libff::alt_bn128_G2 >( el1 ); + libff::alt_bn128_G2 el1 = libff::alt_bn128_G2::zero(); + auto el_ptr1 = std::make_shared< libff::alt_bn128_G2 >( el1 ); - BOOST_REQUIRE_THROW( - decr_set.addDecrypt( 1, el_ptr1 ), crypto::ThresholdUtils::IsNotWellFormed ); - } + BOOST_REQUIRE_THROW( + decr_set.addDecrypt( 1, el_ptr1 ), crypto::ThresholdUtils::IsNotWellFormed ); + } - { - // null element in decrypt set - TEDecryptSet decr_set( num_signed, num_all ); - libff::alt_bn128_G2 el1 = libff::alt_bn128_G2::zero(); + { + // null element in decrypt set + TEDecryptSet decr_set( num_signed, num_all ); - auto el_ptr1 = std::make_shared< libff::alt_bn128_G2 >( el1 ); - el_ptr1 = nullptr; - BOOST_REQUIRE_THROW( - decr_set.addDecrypt( 1, el_ptr1 ), crypto::ThresholdUtils::IncorrectInput ); - } + std::shared_ptr< libff::alt_bn128_G2 > el_ptr1 = nullptr; + BOOST_REQUIRE_THROW( + decr_set.addDecrypt( 1, el_ptr1 ), crypto::ThresholdUtils::IncorrectInput ); + } - { - // not enough elements in decrypt set - TEDecryptSet decr_set( num_signed, num_all ); - libff::alt_bn128_G2 el1 = libff::alt_bn128_G2::random_element(); + { + // not enough elements in decrypt set + TEDecryptSet decr_set( num_signed, num_all ); + libff::alt_bn128_G2 el1 = libff::alt_bn128_G2::random_element(); - auto el_ptr1 = std::make_shared< libff::alt_bn128_G2 >( el1 ); - decr_set.addDecrypt( 1, el_ptr1 ); + auto el_ptr1 = std::make_shared< libff::alt_bn128_G2 >( el1 ); + decr_set.addDecrypt( 1, el_ptr1 ); - libff::alt_bn128_G2 U = libff::alt_bn128_G2::random_element(); + libff::alt_bn128_G2 U = libff::alt_bn128_G2::random_element(); - libff::alt_bn128_G1 W = libff::alt_bn128_G1::random_element(); + libff::alt_bn128_G1 W = libff::alt_bn128_G1::random_element(); - crypto::Ciphertext cypher; - std::get< 0 >( cypher ) = U; - std::get< 1 >( cypher ) = - "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; - std::get< 2 >( cypher ) = W; + crypto::Ciphertext cypher; + std::get< 0 >( cypher ) = U; + std::get< 1 >( cypher ) = + "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; + std::get< 2 >( cypher ) = W; - BOOST_REQUIRE_THROW( - decr_set.merge( cypher ), crypto::ThresholdUtils::IsNotWellFormed ); - } + BOOST_REQUIRE_THROW( decr_set.merge( cypher ), crypto::ThresholdUtils::IsNotWellFormed ); + } - { - // cannot combine shares - TEDecryptSet decr_set( 1, 1 ); - libff::alt_bn128_G2 el1 = libff::alt_bn128_G2::random_element(); - auto el_ptr1 = std::make_shared< libff::alt_bn128_G2 >( el1 ); - decr_set.addDecrypt( 1, el_ptr1 ); + { + // cannot combine shares + TEDecryptSet decr_set( 1, 1 ); + libff::alt_bn128_G2 el1 = libff::alt_bn128_G2::random_element(); + auto el_ptr1 = std::make_shared< libff::alt_bn128_G2 >( el1 ); + decr_set.addDecrypt( 1, el_ptr1 ); - libff::alt_bn128_G2 U = libff::alt_bn128_G2::random_element(); + libff::alt_bn128_G2 U = libff::alt_bn128_G2::random_element(); - libff::alt_bn128_G1 W = libff::alt_bn128_G1::random_element(); + libff::alt_bn128_G1 W = libff::alt_bn128_G1::random_element(); - crypto::Ciphertext cypher; - std::get< 0 >( cypher ) = U; - std::get< 1 >( cypher ) = - "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; - std::get< 2 >( cypher ) = W; + crypto::Ciphertext cypher; + std::get< 0 >( cypher ) = U; + std::get< 1 >( cypher ) = + "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; + std::get< 2 >( cypher ) = W; - BOOST_REQUIRE_THROW( decr_set.merge( cypher ), crypto::ThresholdUtils::IncorrectInput ); - } + BOOST_REQUIRE_THROW( decr_set.merge( cypher ), crypto::ThresholdUtils::IncorrectInput ); } } diff --git a/test/unit_tests_bls.cpp b/test/unit_tests_bls.cpp index 49ed8f88..78b03afa 100644 --- a/test/unit_tests_bls.cpp +++ b/test/unit_tests_bls.cpp @@ -441,72 +441,6 @@ BOOST_AUTO_TEST_CASE(differentMessages) { BOOST_AUTO_TEST_SUITE_END() -BOOST_AUTO_TEST_SUITE( LagrangeInterpolation ) -// a goal is to get correct polynomial's value at zero point - -BOOST_AUTO_TEST_CASE( RandomPolynomial ) { - std::cout << "Testing Random Polynomial case\n"; - - std::srand( unsigned( std::time( 0 ) ) ); - - size_t deg = std::rand() % 30 + 1; // a degree of polynomial should never be 0 - - std::vector< libff::alt_bn128_Fr > pol( deg + 1 ); - - crypto::ThresholdUtils::initCurve(); - - // random polynomial generation - for ( size_t i = 0; i < deg + 1; ++i ) { - pol[i] = libff::alt_bn128_Fr::random_element(); - - while ( i == deg && pol[i] == libff::alt_bn128_Fr::zero() ) { - pol[i] = libff::alt_bn128_Fr::random_element(); - } - } - - auto polynomial_value = [&pol, deg]( libff::alt_bn128_Fr point ) { - libff::alt_bn128_Fr value = libff::alt_bn128_Fr::zero(); - - libff::alt_bn128_Fr pow = libff::alt_bn128_Fr::one(); - - for ( size_t i = 0; i < deg + 1; ++i ) { - if ( i == deg && pol[i] == libff::alt_bn128_Fr::zero() ) { - throw std::runtime_error( "Error, incorrect degree of a polynomial" ); - } - value += pol[i] * pow; - pow *= point; - } - - return value; - }; - - // generating random points to interpolate their values and to get a value at point zero - std::vector< size_t > indexes( deg + 1, 0 ); - std::set< size_t > nodes; - for ( size_t i = 0; i < deg + 1; ++i ) { - std::srand( unsigned( std::time( 0 ) ) ); - while ( indexes[i] == 0 || nodes.find( indexes[i] ) != nodes.end() ) { - indexes[i] = std::rand() % ( 5 * deg ); - } - nodes.insert( indexes[i] ); - } - - crypto::Bls obj = crypto::Bls( deg + 1, deg + 1 ); - auto coeffs = crypto::ThresholdUtils::LagrangeCoeffs( indexes, deg + 1 ); - - std::vector< libff::alt_bn128_Fr > values( deg + 1 ); - for ( size_t i = 0; i < deg + 1; ++i ) { - values[i] = polynomial_value( libff::alt_bn128_Fr( std::to_string( indexes[i] ).c_str() ) ); - } - - libff::alt_bn128_Fr value_at_zero_point = pol[0]; - - BOOST_REQUIRE( value_at_zero_point == obj.KeysRecover( coeffs, values ).first ); -} - - -BOOST_AUTO_TEST_SUITE_END() - BOOST_AUTO_TEST_SUITE( Exceptions ) diff --git a/test/unit_tests_te.cpp b/test/unit_tests_te.cpp index de9829fd..64a18d8c 100644 --- a/test/unit_tests_te.cpp +++ b/test/unit_tests_te.cpp @@ -21,9 +21,12 @@ @date 2019 */ +#include + #include #include -#include + +#include #define BOOST_TEST_MODULE @@ -42,7 +45,7 @@ BOOST_AUTO_TEST_CASE( SimpleEncryption ) { libff::alt_bn128_G2 public_key = secret_key * libff::alt_bn128_G2::one(); - auto ciphertext = te_instance.Encrypt( message, public_key ); + auto ciphertext = te_instance.getCiphertext( message, public_key ); libff::alt_bn128_G2 decryption_share = te_instance.getDecryptionShare( ciphertext, secret_key ); @@ -56,6 +59,225 @@ BOOST_AUTO_TEST_CASE( SimpleEncryption ) { BOOST_REQUIRE( res == message ); } +BOOST_AUTO_TEST_CASE( SimpleEncryptionWithAES ) { + crypto::TE te_instance = crypto::TE( 1, 1 ); + + std::string message = + "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; // message should be 64 + // length + + libff::alt_bn128_Fr secret_key = libff::alt_bn128_Fr::random_element(); + + libff::alt_bn128_G2 public_key = secret_key * libff::alt_bn128_G2::one(); + + auto ciphertext_with_aes = te_instance.encryptWithAES( message, public_key ); + + auto ciphertext = ciphertext_with_aes.first; + auto encrypted_message = ciphertext_with_aes.second; + + libff::alt_bn128_G2 decryption_share = te_instance.getDecryptionShare( ciphertext, secret_key ); + + BOOST_REQUIRE( te_instance.Verify( ciphertext, decryption_share, public_key ) ); + + std::vector< std::pair< libff::alt_bn128_G2, size_t > > shares; + shares.push_back( std::make_pair( decryption_share, size_t( 1 ) ) ); + + std::string decrypted_aes_key = te_instance.CombineShares( ciphertext, shares ); + + std::string plaintext = + crypto::ThresholdUtils::aesDecrypt( encrypted_message, decrypted_aes_key ); + + BOOST_REQUIRE( plaintext == message ); +} + +BOOST_AUTO_TEST_CASE( encryptionWithAESWrongKey ) { + crypto::TE te_instance = crypto::TE( 1, 1 ); + + std::string message = + "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; // message should be 64 + // length + + libff::alt_bn128_Fr secret_key = libff::alt_bn128_Fr::random_element(); + + libff::alt_bn128_G2 public_key = secret_key * libff::alt_bn128_G2::one(); + + auto ciphertext_with_aes = te_instance.encryptWithAES( message, public_key ); + + auto ciphertext = ciphertext_with_aes.first; + auto encrypted_message = ciphertext_with_aes.second; + + libff::alt_bn128_G2 decryption_share = te_instance.getDecryptionShare( ciphertext, secret_key ); + + BOOST_REQUIRE( te_instance.Verify( ciphertext, decryption_share, public_key ) ); + + std::vector< std::pair< libff::alt_bn128_G2, size_t > > shares; + shares.push_back( std::make_pair( decryption_share, size_t( 1 ) ) ); + + // std::string decrypted_aes_key = te_instance.CombineShares( ciphertext, shares ); + crypto::ThresholdUtils::initAES(); + unsigned char key_bytes[32]; + RAND_bytes( key_bytes, sizeof( key_bytes ) ); + std::string random_aes_key = std::string( ( char* ) key_bytes, sizeof( key_bytes ) ); + + std::string plaintext = crypto::ThresholdUtils::aesDecrypt( encrypted_message, random_aes_key ); + + BOOST_REQUIRE( plaintext != message ); +} + +BOOST_AUTO_TEST_CASE( encryptionWithAESWrongCiphertext ) { + crypto::TE te_instance = crypto::TE( 1, 1 ); + + std::string message = + "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; // message should be 64 + // length + + libff::alt_bn128_Fr secret_key = libff::alt_bn128_Fr::random_element(); + + libff::alt_bn128_G2 public_key = secret_key * libff::alt_bn128_G2::one(); + + auto ciphertext_with_aes = te_instance.encryptWithAES( message, public_key ); + + auto ciphertext = ciphertext_with_aes.first; + // auto encrypted_message = ciphertext_with_aes.second; + + libff::alt_bn128_G2 decryption_share = te_instance.getDecryptionShare( ciphertext, secret_key ); + + BOOST_REQUIRE( te_instance.Verify( ciphertext, decryption_share, public_key ) ); + + std::vector< std::pair< libff::alt_bn128_G2, size_t > > shares; + shares.push_back( std::make_pair( decryption_share, size_t( 1 ) ) ); + + std::string decrypted_aes_key = te_instance.CombineShares( ciphertext, shares ); + + std::string bad_message = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; + auto bad_encrypted_message = te_instance.encryptWithAES( bad_message, public_key ).second; + + std::string plaintext = + crypto::ThresholdUtils::aesDecrypt( bad_encrypted_message, decrypted_aes_key ); + + BOOST_REQUIRE( plaintext != message ); +} + +BOOST_AUTO_TEST_CASE( ConvertionToStringAndBack ) { + crypto::ThresholdUtils::initCurve(); + + std::string message = + "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; // message should be 64 + // length + + libff::alt_bn128_Fr secret_key = libff::alt_bn128_Fr::random_element(); + + libff::alt_bn128_G2 public_key = secret_key * libff::alt_bn128_G2::one(); + + auto ciphertext_with_aes = crypto::TE::encryptWithAES( message, public_key ); + + auto str = + crypto::TE::aesCiphertextToString( ciphertext_with_aes.first, ciphertext_with_aes.second ); + + auto ciphertext_from_string = crypto::TE::aesCiphertextFromString( str ); + auto V_old = std::get< 1 >( ciphertext_with_aes.first ); + auto V_new = std::get< 1 >( ciphertext_from_string.first ); + + auto W_old = std::get< 2 >( ciphertext_with_aes.first ); + auto W_new = std::get< 2 >( ciphertext_from_string.first ); + + auto U_old = std::get< 0 >( ciphertext_with_aes.first ); + auto U_new = std::get< 0 >( ciphertext_from_string.first ); + + BOOST_REQUIRE( U_old == U_new ); + BOOST_REQUIRE( W_old == W_new ); + BOOST_REQUIRE( V_old == V_new ); + BOOST_REQUIRE( ciphertext_with_aes.first == ciphertext_from_string.first ); + BOOST_REQUIRE( ciphertext_with_aes.second.size() == ciphertext_from_string.second.size() ); + BOOST_REQUIRE( ciphertext_with_aes == ciphertext_from_string ); +} + +BOOST_AUTO_TEST_CASE( ConvertionToStringAndBackTooShort ) { + crypto::ThresholdUtils::initCurve(); + + // std::string message = + // "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; // message should be + // 64 + // // length + + // libff::alt_bn128_Fr secret_key = libff::alt_bn128_Fr::random_element(); + + // libff::alt_bn128_G2 public_key = secret_key * libff::alt_bn128_G2::one(); + + // auto ciphertext_with_aes = crypto::TE::encryptWithAES( message, public_key ); + + // auto str = + // crypto::TE::aesCiphertextToString( ciphertext_with_aes.first, ciphertext_with_aes.second + // ); + + BOOST_REQUIRE_THROW( crypto::TE::aesCiphertextFromString( "acefbdg11356" ), + crypto::ThresholdUtils::IncorrectInput ); +} + +BOOST_AUTO_TEST_CASE( ConvertionToStringAndBackNonHex ) { + crypto::ThresholdUtils::initCurve(); + + // std::string message = + // "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; // message should be + // 64 + // // length + + // libff::alt_bn128_Fr secret_key = libff::alt_bn128_Fr::random_element(); + + // libff::alt_bn128_G2 public_key = secret_key * libff::alt_bn128_G2::one(); + + // auto ciphertext_with_aes = crypto::TE::encryptWithAES( message, public_key ); + + // auto str = + // crypto::TE::aesCiphertextToString( ciphertext_with_aes.first, ciphertext_with_aes.second + // ); + + BOOST_REQUIRE_THROW( + crypto::TE::aesCiphertextFromString( "qwerty" ), crypto::ThresholdUtils::IncorrectInput ); +} + +BOOST_AUTO_TEST_CASE( EncryptionCipherToString ) { + crypto::TE te_instance = crypto::TE( 1, 1 ); + + std::string message = + "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; // message should be 64 + // length + + libff::alt_bn128_Fr secret_key = libff::alt_bn128_Fr::random_element(); + + libff::alt_bn128_G2 public_key = secret_key * libff::alt_bn128_G2::one(); + + auto str = crypto::ThresholdUtils::G2ToString( public_key, 16 ); + std::string common_public_str = ""; + for ( auto& elem : str ) { + while ( elem.size() < 64 ) { + elem = "0" + elem; + } + common_public_str += elem; + } + + auto ciphertext_string = te_instance.encryptMessage( message, common_public_str ); + + auto ciphertext_with_aes = te_instance.aesCiphertextFromString( ciphertext_string ); + + auto ciphertext = ciphertext_with_aes.first; + auto encrypted_message = ciphertext_with_aes.second; + + libff::alt_bn128_G2 decryption_share = te_instance.getDecryptionShare( ciphertext, secret_key ); + + BOOST_REQUIRE( te_instance.Verify( ciphertext, decryption_share, public_key ) ); + + std::vector< std::pair< libff::alt_bn128_G2, size_t > > shares; + shares.push_back( std::make_pair( decryption_share, size_t( 1 ) ) ); + + std::string decrypted_aes_key = te_instance.CombineShares( ciphertext, shares ); + + std::string plaintext = + crypto::ThresholdUtils::aesDecrypt( encrypted_message, decrypted_aes_key ); + + BOOST_REQUIRE( plaintext == message ); +} + BOOST_AUTO_TEST_CASE( ThresholdEncryptionReal ) { crypto::TE obj = crypto::TE( 11, 16 ); @@ -93,7 +315,7 @@ BOOST_AUTO_TEST_CASE( ThresholdEncryptionReal ) { "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; // message should be 64 // length - auto ciphertext = obj.Encrypt( message, common_public ); + auto ciphertext = obj.getCiphertext( message, common_public ); std::vector< std::pair< libff::alt_bn128_G2, size_t > > shares( 11 ); @@ -154,7 +376,7 @@ BOOST_AUTO_TEST_CASE( ThresholdEncryptionRandomPK ) { "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; // message should be 64 // length - auto ciphertext = obj.Encrypt( message, common_public ); + auto ciphertext = obj.getCiphertext( message, common_public ); std::vector< std::pair< libff::alt_bn128_G2, size_t > > shares( 11 ); @@ -217,7 +439,7 @@ BOOST_AUTO_TEST_CASE( ThresholdEncryptionRandomSK ) { "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; // message should be 64 // length - auto ciphertext = obj.Encrypt( message, common_public ); + auto ciphertext = obj.getCiphertext( message, common_public ); std::vector< std::pair< libff::alt_bn128_G2, size_t > > shares( 11 ); @@ -275,7 +497,7 @@ BOOST_AUTO_TEST_CASE( ThresholdEncryptionCorruptedCiphertext ) { "Hello, SKALE users and fans, gl!Hello, SKALE users and fans, gl!"; // message should be 64 // length - auto ciphertext = obj.Encrypt( message, common_public ); + auto ciphertext = obj.getCiphertext( message, common_public ); libff::alt_bn128_G1 rand = libff::alt_bn128_G1::random_element(); diff --git a/test/unit_tests_utils.cpp b/test/unit_tests_utils.cpp new file mode 100644 index 00000000..2613340f --- /dev/null +++ b/test/unit_tests_utils.cpp @@ -0,0 +1,160 @@ +/* + Copyright (C) 2018-2019 SKALE Labs + + This file is part of libBLS. + + libBLS is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libBLS 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with libBLS. If not, see . + + @file unit_tests_utils.cpp + @author Oleh Nikolaiev + @date 2021 +*/ + +#include +#include +#include +#include + +#include + +#include + +#include + + +#define BOOST_TEST_MODULE + +#include + +BOOST_AUTO_TEST_SUITE( TestLagrange ) + +// a goal is to get correct polynomial's value at zero point + +BOOST_AUTO_TEST_CASE( RandomPolynomial ) { + std::cout << "Testing Random Polynomial case\n"; + + std::srand( unsigned( std::time( 0 ) ) ); + + size_t deg = std::rand() % 30 + 1; // a degree of polynomial should never be 0 + + std::vector< libff::alt_bn128_Fr > pol( deg + 1 ); + + crypto::ThresholdUtils::initCurve(); + + // random polynomial generation + for ( size_t i = 0; i < deg + 1; ++i ) { + pol[i] = libff::alt_bn128_Fr::random_element(); + + while ( i == deg && pol[i] == libff::alt_bn128_Fr::zero() ) { + pol[i] = libff::alt_bn128_Fr::random_element(); + } + } + + auto polynomial_value = [&pol, deg]( libff::alt_bn128_Fr point ) { + libff::alt_bn128_Fr value = libff::alt_bn128_Fr::zero(); + + libff::alt_bn128_Fr pow = libff::alt_bn128_Fr::one(); + + for ( size_t i = 0; i < deg + 1; ++i ) { + if ( i == deg && pol[i] == libff::alt_bn128_Fr::zero() ) { + throw std::runtime_error( "Error, incorrect degree of a polynomial" ); + } + value += pol[i] * pow; + pow *= point; + } + + return value; + }; + + // generating random points to interpolate their values and to get a value at point zero + std::vector< size_t > indexes( deg + 1, 0 ); + std::set< size_t > nodes; + for ( size_t i = 0; i < deg + 1; ++i ) { + std::srand( unsigned( std::time( 0 ) ) ); + while ( indexes[i] == 0 || nodes.find( indexes[i] ) != nodes.end() ) { + indexes[i] = std::rand() % ( 5 * deg ); + } + nodes.insert( indexes[i] ); + } + + crypto::Bls obj = crypto::Bls( deg + 1, deg + 1 ); + auto coeffs = crypto::ThresholdUtils::LagrangeCoeffs( indexes, deg + 1 ); + + std::vector< libff::alt_bn128_Fr > values( deg + 1 ); + for ( size_t i = 0; i < deg + 1; ++i ) { + values[i] = polynomial_value( libff::alt_bn128_Fr( std::to_string( indexes[i] ).c_str() ) ); + } + + libff::alt_bn128_Fr value_at_zero_point = pol[0]; + + BOOST_REQUIRE( value_at_zero_point == obj.KeysRecover( coeffs, values ).first ); +} + +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE( TestAES ) + +BOOST_AUTO_TEST_CASE( SimpleAES ) { + crypto::ThresholdUtils::initAES(); + unsigned char key_bytes[32]; + RAND_bytes( key_bytes, sizeof( key_bytes ) ); + std::string random_aes_key = std::string( ( char* ) key_bytes, sizeof( key_bytes ) ); + + const std::string message = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + + auto ciphertext = crypto::ThresholdUtils::aesEncrypt( message, random_aes_key ); + auto decrypted_text = crypto::ThresholdUtils::aesDecrypt( ciphertext, random_aes_key ); + + BOOST_REQUIRE( decrypted_text == message ); +} + +BOOST_AUTO_TEST_CASE( wrongCiphertext ) { + crypto::ThresholdUtils::initAES(); + unsigned char key_bytes[32]; + RAND_bytes( key_bytes, sizeof( key_bytes ) ); + std::string random_aes_key = std::string( ( char* ) key_bytes, sizeof( key_bytes ) ); + + const std::string message = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + + auto ciphertext = crypto::ThresholdUtils::aesEncrypt( message, random_aes_key ); + + const std::string bad_message = + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; + auto bad_ciphertext = crypto::ThresholdUtils::aesEncrypt( bad_message, random_aes_key ); + + auto decrypted_text = crypto::ThresholdUtils::aesDecrypt( bad_ciphertext, random_aes_key ); + + BOOST_REQUIRE( decrypted_text != message ); +} + +BOOST_AUTO_TEST_CASE( wrongKey ) { + crypto::ThresholdUtils::initAES(); + unsigned char key_bytes[32]; + RAND_bytes( key_bytes, sizeof( key_bytes ) ); + std::string random_aes_key = std::string( ( char* ) key_bytes, sizeof( key_bytes ) ); + + const std::string message = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + + auto ciphertext = crypto::ThresholdUtils::aesEncrypt( message, random_aes_key ); + + unsigned char bad_key_bytes[32]; + RAND_bytes( bad_key_bytes, sizeof( bad_key_bytes ) ); + std::string bad_key = std::string( ( char* ) bad_key_bytes, sizeof( bad_key_bytes ) ); + + auto decrypted_text = crypto::ThresholdUtils::aesDecrypt( ciphertext, bad_key ); + + BOOST_REQUIRE( decrypted_text != message ); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/threshold_encryption/CMakeLists.txt b/threshold_encryption/CMakeLists.txt index 868905a5..a2604456 100644 --- a/threshold_encryption/CMakeLists.txt +++ b/threshold_encryption/CMakeLists.txt @@ -48,18 +48,18 @@ include_directories(${CMAKE_BINARY_DIR}/deps/include ) link_directories(${CMAKE_BINARY_DIR}/deps/lib) target_include_directories(te PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${THIRD_PARTY_DIR}) -target_link_libraries(te PRIVATE ff ${GMPXX_LIBRARY} ${GMP_LIBRARY}) +target_link_libraries(te PRIVATE ${CRYPTOPP} ff ${GMPXX_LIBRARY} ${GMP_LIBRARY}) if (BUILD_TESTS) add_executable(te_unit_test ../test/unit_tests_te.cpp) target_include_directories(te_unit_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${THIRD_PARTY_DIR}) - target_link_libraries(te_unit_test PRIVATE te ff ${GMPXX_LIBRARY} ${GMP_LIBRARY}) + target_link_libraries(te_unit_test PRIVATE te ${CRYPTOPP} ff ${GMPXX_LIBRARY} ${GMP_LIBRARY}) add_test(NAME te_tests COMMAND te_unit_test) add_executable(te_test ../test/test_TE_wrappers.cpp) target_include_directories(te_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${THIRD_PARTY_DIR}) - target_link_libraries(te_test PRIVATE te ff ${GMPXX_LIBRARY} ${GMP_LIBRARY}) + target_link_libraries(te_test PRIVATE te ${CRYPTOPP} ff ${GMPXX_LIBRARY} ${GMP_LIBRARY}) add_test(NAME te_wrap_tests COMMAND te_unit_test) diff --git a/threshold_encryption/TEDecryptSet.cpp b/threshold_encryption/TEDecryptSet.cpp index 176dfda9..12c08e19 100644 --- a/threshold_encryption/TEDecryptSet.cpp +++ b/threshold_encryption/TEDecryptSet.cpp @@ -56,7 +56,7 @@ void TEDecryptSet::addDecrypt( size_t _signerIndex, std::shared_ptr< libff::alt_ } std::string TEDecryptSet::merge( const crypto::Ciphertext& cyphertext ) { - crypto::ThresholdUtils::checkCypher( cyphertext ); + crypto::TE::checkCypher( cyphertext ); was_merged = true; diff --git a/threshold_encryption/TEPrivateKeyShare.cpp b/threshold_encryption/TEPrivateKeyShare.cpp index f6cb717b..4336d993 100644 --- a/threshold_encryption/TEPrivateKeyShare.cpp +++ b/threshold_encryption/TEPrivateKeyShare.cpp @@ -65,7 +65,7 @@ TEPrivateKeyShare::TEPrivateKeyShare( libff::alt_bn128_Fr _skey_share, size_t _s } libff::alt_bn128_G2 TEPrivateKeyShare::getDecryptionShare( crypto::Ciphertext& cipher ) { - crypto::ThresholdUtils::checkCypher( cipher ); + crypto::TE::checkCypher( cipher ); crypto::TE te( requiredSigners, totalSigners ); diff --git a/threshold_encryption/TEPublicKey.cpp b/threshold_encryption/TEPublicKey.cpp index 6cb90265..bbd61dd3 100644 --- a/threshold_encryption/TEPublicKey.cpp +++ b/threshold_encryption/TEPublicKey.cpp @@ -97,8 +97,8 @@ crypto::Ciphertext TEPublicKey::encrypt( std::shared_ptr< std::string > mes_ptr throw crypto::ThresholdUtils::IncorrectInput( "Message length is not equal to 64" ); } - crypto::Ciphertext cypher = te.Encrypt( *mes_ptr, PublicKey ); - crypto::ThresholdUtils::checkCypher( cypher ); + crypto::Ciphertext cypher = te.getCiphertext( *mes_ptr, PublicKey ); + crypto::TE::checkCypher( cypher ); return std::make_tuple( std::get< 0 >( cypher ), std::get< 1 >( cypher ), std::get< 2 >( cypher ) ); diff --git a/threshold_encryption/TEPublicKeyShare.cpp b/threshold_encryption/TEPublicKeyShare.cpp index 5b21385c..c1fa620b 100644 --- a/threshold_encryption/TEPublicKeyShare.cpp +++ b/threshold_encryption/TEPublicKeyShare.cpp @@ -76,7 +76,7 @@ TEPublicKeyShare::TEPublicKeyShare( bool TEPublicKeyShare::Verify( const crypto::Ciphertext& cyphertext, const libff::alt_bn128_G2& decryptionShare ) { - crypto::ThresholdUtils::checkCypher( cyphertext ); + crypto::TE::checkCypher( cyphertext ); if ( decryptionShare.is_zero() || !decryptionShare.is_well_formed() ) { throw crypto::ThresholdUtils::IsNotWellFormed( "zero decrypt" ); } diff --git a/threshold_encryption/threshold_encryption.cpp b/threshold_encryption/threshold_encryption.cpp index 5dd9f316..3b9bc880 100644 --- a/threshold_encryption/threshold_encryption.cpp +++ b/threshold_encryption/threshold_encryption.cpp @@ -27,6 +27,8 @@ #include #include + +#include #include namespace crypto { @@ -38,6 +40,15 @@ TE::TE( const size_t t, const size_t n ) : t_( t ), n_( n ) { TE::~TE() {} +void TE::checkCypher( + const std::tuple< libff::alt_bn128_G2, std::string, libff::alt_bn128_G1 >& cyphertext ) { + if ( std::get< 0 >( cyphertext ).is_zero() || std::get< 2 >( cyphertext ).is_zero() ) + throw ThresholdUtils::IncorrectInput( "zero element in cyphertext" ); + + if ( std::get< 1 >( cyphertext ).length() != 64 ) + throw ThresholdUtils::IncorrectInput( "wrong string length in cyphertext" ); +} + std::string TE::Hash( const libff::alt_bn128_G2& Y, std::string ( *hash_func )( const std::string& str ) ) { auto vectorCoordinates = ThresholdUtils::G2ToString( Y ); @@ -69,7 +80,8 @@ libff::alt_bn128_G1 TE::HashToGroup( const libff::alt_bn128_G2& U, const std::st return ThresholdUtils::HashtoG1( hash_bytes_arr ); } -Ciphertext TE::Encrypt( const std::string& message, const libff::alt_bn128_G2& common_public ) { +Ciphertext TE::getCiphertext( + const std::string& message, const libff::alt_bn128_G2& common_public ) { libff::alt_bn128_Fr r = libff::alt_bn128_Fr::random_element(); while ( r.is_zero() ) { @@ -80,31 +92,30 @@ Ciphertext TE::Encrypt( const std::string& message, const libff::alt_bn128_G2& c U = r * libff::alt_bn128_G2::one(); Y = r * common_public; - std::string hash = this->Hash( Y ); - - // assuming message and hash are the same size strings - // the behaviour is undefined when the two arguments are valarrays with different sizes + std::string hash = Hash( Y ); - std::valarray< uint8_t > lhs_to_hash( hash.size() ); - for ( size_t i = 0; i < hash.size(); ++i ) { - lhs_to_hash[i] = static_cast< uint8_t >( hash[i] ); + size_t size = std::max( message.size(), hash.size() ); + std::valarray< uint8_t > lhs_to_hash( size ); + for ( size_t i = 0; i < size; ++i ) { + lhs_to_hash[i] = i < hash.size() ? static_cast< uint8_t >( hash[i] ) : 0; } - std::valarray< uint8_t > rhs_to_hash( message.size() ); - for ( size_t i = 0; i < message.size(); ++i ) { - rhs_to_hash[i] = static_cast< uint8_t >( message[i] ); + std::valarray< uint8_t > rhs_to_hash( size ); + for ( size_t i = 0; i < size; ++i ) { + rhs_to_hash[i] = i < message.size() ? static_cast< uint8_t >( message[i] ) : 0; } std::valarray< uint8_t > res = lhs_to_hash ^ rhs_to_hash; - std::string V = ""; - for ( size_t i = 0; i < res.size(); ++i ) { - V += static_cast< char >( res[i] ); + std::string V; + V.resize( size ); + for ( size_t i = 0; i < size; ++i ) { + V[i] = static_cast< uint8_t >( res[i] ); } libff::alt_bn128_G1 W, H; - H = this->HashToGroup( U, V ); + H = HashToGroup( U, V ); W = r * H; Ciphertext result; @@ -115,9 +126,33 @@ Ciphertext TE::Encrypt( const std::string& message, const libff::alt_bn128_G2& c return result; } +std::pair< Ciphertext, std::vector< uint8_t > > TE::encryptWithAES( + const std::string& message, const libff::alt_bn128_G2& common_public ) { + ThresholdUtils::initAES(); + unsigned char key_bytes[32]; + RAND_bytes( key_bytes, sizeof( key_bytes ) ); + std::string random_aes_key = std::string( ( char* ) key_bytes, sizeof( key_bytes ) ); + + auto encrypted_message = ThresholdUtils::aesEncrypt( message, random_aes_key ); + + auto ciphertext = getCiphertext( random_aes_key, common_public ); + + auto U = std::get< 0 >( ciphertext ); + auto V = std::get< 1 >( ciphertext ); + auto W = std::get< 2 >( ciphertext ); + + return {{U, V, W}, encrypted_message}; +} + +std::string TE::encryptMessage( const std::string& message, const std::string& common_public_str ) { + libff::alt_bn128_G2 common_public = ThresholdUtils::stringToG2( common_public_str ); + auto ciphertext_with_aes = encryptWithAES( message, common_public ); + return aesCiphertextToString( ciphertext_with_aes.first, ciphertext_with_aes.second ); +} + libff::alt_bn128_G2 TE::getDecryptionShare( const Ciphertext& ciphertext, const libff::alt_bn128_Fr& secret_key ) { - ThresholdUtils::checkCypher( ciphertext ); + checkCypher( ciphertext ); if ( secret_key.is_zero() ) throw ThresholdUtils::ZeroSecretKey( "zero secret key" ); @@ -127,7 +162,7 @@ libff::alt_bn128_G2 TE::getDecryptionShare( libff::alt_bn128_G1 W = std::get< 2 >( ciphertext ); - libff::alt_bn128_G1 H = this->HashToGroup( U, V ); + libff::alt_bn128_G1 H = HashToGroup( U, V ); libff::alt_bn128_GT fst, snd; fst = libff::alt_bn128_ate_reduced_pairing( W, libff::alt_bn128_G2::one() ); @@ -152,7 +187,7 @@ bool TE::Verify( const Ciphertext& ciphertext, const libff::alt_bn128_G2& decryp libff::alt_bn128_G1 W = std::get< 2 >( ciphertext ); - libff::alt_bn128_G1 H = this->HashToGroup( U, V ); + libff::alt_bn128_G1 H = HashToGroup( U, V ); libff::alt_bn128_GT fst, snd; fst = libff::alt_bn128_ate_reduced_pairing( W, libff::alt_bn128_G2::one() ); @@ -239,4 +274,81 @@ std::string TE::CombineShares( const Ciphertext& ciphertext, return message; } +std::string TE::aesCiphertextToString( + const Ciphertext& cipher, const std::vector< uint8_t >& data ) { + ThresholdUtils::initCurve(); + ThresholdUtils::initAES(); + + auto U = std::get< 0 >( cipher ); + auto V = std::get< 1 >( cipher ); + auto W = std::get< 2 >( cipher ); + + std::string v_str = ThresholdUtils::carray2Hex( ( unsigned char* ) ( V.data() ), V.size() ); + + std::string encrypted_data = ThresholdUtils::carray2Hex( data.data(), data.size() ); + + auto str = ThresholdUtils::G2ToString( U, 16 ); + std::string u_str = ""; + for ( auto& elem : str ) { + while ( elem.size() < 64 ) { + elem = "0" + elem; + } + u_str += elem; + } + + W.to_affine_coordinates(); + std::string x = ThresholdUtils::fieldElementToString( W.X, 16 ); + while ( x.size() < 64 ) { + x = "0" + x; + } + + std::string y = ThresholdUtils::fieldElementToString( W.Y, 16 ); + while ( y.size() < 64 ) { + y = "0" + y; + } + + std::string w_str = x + y; + + return u_str + v_str + w_str + encrypted_data; +} + +std::pair< Ciphertext, std::vector< uint8_t > > TE::aesCiphertextFromString( + const std::string& str ) { + ThresholdUtils::initCurve(); + ThresholdUtils::initAES(); + + if ( !ThresholdUtils::checkHex( str ) ) { + throw ThresholdUtils::IncorrectInput( "Provided string contains non-hex symbols" ); + } + + if ( str.size() < 256 + 129 + 128 + 1 ) { + throw ThresholdUtils::IncorrectInput( + "Incoming string to short to convert to aes ciphertext" ); + } + + std::string u_str = str.substr( 0, 256 ); + std::string v_str = str.substr( 256, 129 ); + std::string w_str = str.substr( 256 + 129, 128 ); + + std::string encrypted_data = str.substr( 256 + 129 + 128, std::string::npos ); + + uint64_t bin_len; + std::vector< uint8_t > aes_cipher( encrypted_data.size() / 2 ); + if ( !ThresholdUtils::hex2carray( encrypted_data.data(), &bin_len, &aes_cipher[0] ) ) { + throw ThresholdUtils::IncorrectInput( "Bad aes_cipher provided" ); + } + + libff::alt_bn128_G2 U = ThresholdUtils::stringToG2( u_str ); + + libff::alt_bn128_G1 W = ThresholdUtils::stringToG1( w_str ); + + std::string V; + V.resize( ( v_str.size() - 1 ) / 2 ); + if ( !ThresholdUtils::hex2carray( v_str.data(), &bin_len, ( unsigned char* ) &V[0] ) ) { + throw ThresholdUtils::IncorrectInput( "Bad encrypted aes key provided" ); + } + + return {{U, V, W}, aes_cipher}; +} + } // namespace crypto diff --git a/threshold_encryption/threshold_encryption.h b/threshold_encryption/threshold_encryption.h index 12e091b1..7896922d 100644 --- a/threshold_encryption/threshold_encryption.h +++ b/threshold_encryption/threshold_encryption.h @@ -42,23 +42,38 @@ class TE { ~TE(); - Ciphertext Encrypt( const std::string& message, const libff::alt_bn128_G2& common_public ); + static Ciphertext getCiphertext( + const std::string& message, const libff::alt_bn128_G2& common_public ); - libff::alt_bn128_G2 getDecryptionShare( + static std::pair< Ciphertext, std::vector< uint8_t > > encryptWithAES( + const std::string& message, const libff::alt_bn128_G2& common_public ); + + static std::string encryptMessage( + const std::string& message, const std::string& common_public ); + + static libff::alt_bn128_G2 getDecryptionShare( const Ciphertext& ciphertext, const libff::alt_bn128_Fr& secret_key ); - libff::alt_bn128_G1 HashToGroup( const libff::alt_bn128_G2& U, const std::string& V, + static libff::alt_bn128_G1 HashToGroup( const libff::alt_bn128_G2& U, const std::string& V, std::string ( *hash_func )( const std::string& str ) = cryptlite::sha256::hash_hex ); - std::string Hash( const libff::alt_bn128_G2& Y, + static std::string Hash( const libff::alt_bn128_G2& Y, std::string ( *hash_func )( const std::string& str ) = cryptlite::sha256::hash_hex ); - bool Verify( const Ciphertext& ciphertext, const libff::alt_bn128_G2& decryptionShare, + static bool Verify( const Ciphertext& ciphertext, const libff::alt_bn128_G2& decryptionShare, const libff::alt_bn128_G2& public_key ); std::string CombineShares( const Ciphertext& ciphertext, const std::vector< std::pair< libff::alt_bn128_G2, size_t > >& decryptionShare ); + static void checkCypher( const Ciphertext& cypher ); + + static std::string aesCiphertextToString( + const Ciphertext& cipher, const std::vector< uint8_t >& data ); + + static std::pair< Ciphertext, std::vector< uint8_t > > aesCiphertextFromString( + const std::string& str ); + private: const size_t t_ = 0; diff --git a/tools/hash_g1.cpp b/tools/hash_g1.cpp index 11436727..6b564583 100644 --- a/tools/hash_g1.cpp +++ b/tools/hash_g1.cpp @@ -36,33 +36,6 @@ static bool g_b_verbose_mode = false; static bool g_b_rehash = false; -int char2int( char _input ) { - if ( _input >= '0' && _input <= '9' ) - return _input - '0'; - if ( _input >= 'A' && _input <= 'F' ) - return _input - 'A' + 10; - if ( _input >= 'a' && _input <= 'f' ) - return _input - 'a' + 10; - return -1; -} - -bool hex2carray( const char* _hex, uint64_t* _bin_len, uint8_t* _bin ) { - int len = strnlen( _hex, 2 * 1024 ); - - if ( len == 0 && len % 2 == 1 ) - return false; - *_bin_len = len / 2; - for ( int i = 0; i < len / 2; i++ ) { - int high = char2int( ( char ) _hex[i * 2] ); - int low = char2int( ( char ) _hex[i * 2 + 1] ); - if ( high < 0 || low < 0 ) { - return false; - } - _bin[i] = ( unsigned char ) ( high * 16 + low ); - } - return true; -} - void hash_g1( const size_t t, const size_t n ) { libff::inhibit_profiling_info = true; crypto::Bls bls_instance = crypto::Bls( t, n ); @@ -82,7 +55,8 @@ void hash_g1( const size_t t, const size_t n ) { } } else { uint64_t bin_len; - if ( !hex2carray( to_be_hashed.c_str(), &bin_len, hash_bytes_arr->data() ) ) { + if ( !crypto::ThresholdUtils::hex2carray( + to_be_hashed.c_str(), &bin_len, hash_bytes_arr->data() ) ) { throw std::runtime_error( "Invalid hash" ); } } diff --git a/tools/utils.cpp b/tools/utils.cpp index 210e6479..c65113b3 100644 --- a/tools/utils.cpp +++ b/tools/utils.cpp @@ -21,9 +21,15 @@ @date 2021 */ -#include #include +#include +#include +#include + +#include + + namespace crypto { @@ -53,19 +59,82 @@ void ThresholdUtils::checkSigners( size_t _requiredSigners, size_t _totalSigners } } -std::vector< std::string > ThresholdUtils::G2ToString( libff::alt_bn128_G2 elem ) { +std::vector< std::string > ThresholdUtils::G2ToString( libff::alt_bn128_G2 elem, int base ) { std::vector< std::string > pkey_str_vect; elem.to_affine_coordinates(); - pkey_str_vect.push_back( fieldElementToString( elem.X.c0 ) ); - pkey_str_vect.push_back( fieldElementToString( elem.X.c1 ) ); - pkey_str_vect.push_back( fieldElementToString( elem.Y.c0 ) ); - pkey_str_vect.push_back( fieldElementToString( elem.Y.c1 ) ); + pkey_str_vect.push_back( fieldElementToString( elem.X.c0, base ) ); + pkey_str_vect.push_back( fieldElementToString( elem.X.c1, base ) ); + pkey_str_vect.push_back( fieldElementToString( elem.Y.c0, base ) ); + pkey_str_vect.push_back( fieldElementToString( elem.Y.c1, base ) ); return pkey_str_vect; } +std::string ThresholdUtils::convertHexToDec( const std::string& hex_str ) { + mpz_t dec; + mpz_init( dec ); + + std::string output; + + try { + if ( mpz_set_str( dec, hex_str.c_str(), 16 ) == -1 ) { + mpz_clear( dec ); + throw IsNotWellFormed( "Bad formatted hex string provided" ); + } + + char arr[mpz_sizeinbase( dec, 10 ) + 2]; + char* tmp = mpz_get_str( arr, 10, dec ); + mpz_clear( dec ); + + output = tmp; + } catch ( std::exception& e ) { + mpz_clear( dec ); + throw IsNotWellFormed( e.what() ); + } catch ( ... ) { + mpz_clear( dec ); + throw IsNotWellFormed( "Exception in convert hex to dec" ); + } + + return output; +} + +libff::alt_bn128_G2 ThresholdUtils::stringToG2( const std::string& str ) { + if ( str.size() != 256 ) { + throw IncorrectInput( "Wrong string size to convert to G2" ); + } + + libff::alt_bn128_G2 ret; + + ret.Z = libff::alt_bn128_Fq2::one(); + + ret.X.c0 = + libff::alt_bn128_Fq( ThresholdUtils::convertHexToDec( str.substr( 0, 64 ) ).c_str() ); + ret.X.c1 = + libff::alt_bn128_Fq( ThresholdUtils::convertHexToDec( str.substr( 64, 64 ) ).c_str() ); + ret.Y.c0 = + libff::alt_bn128_Fq( ThresholdUtils::convertHexToDec( str.substr( 128, 64 ) ).c_str() ); + ret.Y.c1 = libff::alt_bn128_Fq( + ThresholdUtils::convertHexToDec( str.substr( 192, std::string::npos ) ).c_str() ); + + return ret; +} + +libff::alt_bn128_G1 ThresholdUtils::stringToG1( const std::string& str ) { + if ( str.size() != 128 ) { + throw IncorrectInput( "Wrong string size to convert to G1" ); + } + + libff::alt_bn128_G1 ret; + + ret.Z = libff::alt_bn128_Fq::one(); + ret.X = libff::alt_bn128_Fq( ThresholdUtils::convertHexToDec( str.substr( 0, 64 ) ).c_str() ); + ret.Y = libff::alt_bn128_Fq( ThresholdUtils::convertHexToDec( str.substr( 64, 64 ) ).c_str() ); + + return ret; +} + std::vector< libff::alt_bn128_Fr > ThresholdUtils::LagrangeCoeffs( const std::vector< size_t >& idx, size_t t ) { if ( idx.size() < t ) { @@ -162,10 +231,10 @@ libff::alt_bn128_G1 ThresholdUtils::HashtoG1( return result; } -bool ThresholdUtils::isStringNumber( std::string& str ) { +bool ThresholdUtils::isStringNumber( const std::string& str ) { if ( str.at( 0 ) == '0' && str.length() > 1 ) return false; - for ( char& c : str ) { + for ( const char& c : str ) { if ( !( c >= '0' && c <= '9' ) ) { return false; } @@ -173,13 +242,62 @@ bool ThresholdUtils::isStringNumber( std::string& str ) { return true; } -void ThresholdUtils::checkCypher( - const std::tuple< libff::alt_bn128_G2, std::string, libff::alt_bn128_G1 >& cyphertext ) { - if ( std::get< 0 >( cyphertext ).is_zero() || std::get< 2 >( cyphertext ).is_zero() ) - throw IncorrectInput( "zero element in cyphertext" ); +std::string ThresholdUtils::carray2Hex( const unsigned char* d, uint64_t len ) { + std::string _hexArray; + _hexArray.resize( 2 * len + 1 ); + + char hexval[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + for ( uint64_t j = 0; j < len; j++ ) { + _hexArray[j * 2] = hexval[( ( d[j] >> 4 ) & 0xF )]; + _hexArray[j * 2 + 1] = hexval[( d[j] ) & 0x0F]; + } + + _hexArray[len * 2] = 0; + + return _hexArray; +} + +int ThresholdUtils::char2int( char _input ) { + if ( _input >= '0' && _input <= '9' ) + return _input - '0'; + if ( _input >= 'A' && _input <= 'F' ) + return _input - 'A' + 10; + if ( _input >= 'a' && _input <= 'f' ) + return _input - 'a' + 10; + return -1; +} + +bool ThresholdUtils::hex2carray( const char* _hex, uint64_t* _bin_len, uint8_t* _bin ) { + int len = strnlen( _hex, 2 * 1024 ); + + if ( len % 2 == 1 ) { + return false; + } + *_bin_len = len / 2; + for ( int i = 0; i < len / 2; i++ ) { + int high = char2int( ( char ) _hex[i * 2] ); + int low = char2int( ( char ) _hex[i * 2 + 1] ); + if ( high < 0 || low < 0 ) { + return false; + } + _bin[i] = ( unsigned char ) ( high * 16 + low ); + } + return true; +} + +bool ThresholdUtils::checkHex( const std::string& hex ) { + mpz_t num; + mpz_init( num ); - if ( std::get< 1 >( cyphertext ).length() != 64 ) - throw IncorrectInput( "wrong string length in cyphertext" ); + if ( mpz_set_str( num, hex.c_str(), 16 ) == -1 ) { + mpz_clear( num ); + return false; + } + mpz_clear( num ); + + return true; } std::pair< libff::alt_bn128_Fq, libff::alt_bn128_Fq > ThresholdUtils::ParseHint( @@ -217,4 +335,68 @@ std::shared_ptr< std::vector< std::string > > ThresholdUtils::SplitString( return std::make_shared< std::vector< std::string > >( tokens ); } +void ThresholdUtils::initAES() { + static int init = 0; + if ( init == 0 ) { + // initialize openssl ciphers + OpenSSL_add_all_ciphers(); + + // initialize random number generator (for IVs) + RAND_load_file( "/dev/urandom", 32 ); + ++init; + } +} + +std::vector< uint8_t > ThresholdUtils::aesEncrypt( + const std::string& plaintext, const std::string& key ) { + initAES(); + + size_t enc_length = plaintext.length() * 3; + std::vector< unsigned char > output; + output.resize( enc_length, '\0' ); + + unsigned char tag[AES_BLOCK_SIZE]; + unsigned char iv[AES_BLOCK_SIZE]; + RAND_bytes( iv, sizeof( iv ) ); + std::copy( iv, iv + 16, output.begin() + 16 ); + + int actual_size = 0, final_size = 0; + EVP_CIPHER_CTX* e_ctx = EVP_CIPHER_CTX_new(); + // EVP_CIPHER_CTX_ctrl(e_ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL); + EVP_EncryptInit( e_ctx, EVP_aes_256_gcm(), ( const unsigned char* ) key.c_str(), iv ); + EVP_EncryptUpdate( e_ctx, &output[64], &actual_size, ( const unsigned char* ) plaintext.data(), + plaintext.length() ); + EVP_EncryptFinal( e_ctx, &output[64 + actual_size], &final_size ); + EVP_CIPHER_CTX_ctrl( e_ctx, EVP_CTRL_GCM_GET_TAG, 16, tag ); + std::copy( tag, tag + 16, output.begin() ); + std::copy( iv, iv + 16, output.begin() + 16 ); + output.resize( 64 + actual_size + final_size ); + EVP_CIPHER_CTX_free( e_ctx ); + return output; +} + +std::string ThresholdUtils::aesDecrypt( + const std::vector< uint8_t >& ciphertext, const std::string& key ) { + initAES(); + + unsigned char tag[AES_BLOCK_SIZE]; + unsigned char iv[AES_BLOCK_SIZE]; + std::copy( ciphertext.begin(), ciphertext.begin() + 16, tag ); + std::copy( ciphertext.begin() + 16, ciphertext.begin() + 32, iv ); + std::vector< unsigned char > plaintext; + plaintext.resize( ciphertext.size(), '\0' ); + + int actual_size = 0, final_size = 0; + EVP_CIPHER_CTX* d_ctx = EVP_CIPHER_CTX_new(); + EVP_DecryptInit( d_ctx, EVP_aes_256_gcm(), ( const unsigned char* ) key.c_str(), iv ); + EVP_DecryptUpdate( + d_ctx, &plaintext[0], &actual_size, &ciphertext[64], ciphertext.size() - 64 ); + EVP_CIPHER_CTX_ctrl( d_ctx, EVP_CTRL_GCM_SET_TAG, 16, tag ); + EVP_DecryptFinal( d_ctx, &plaintext[actual_size], &final_size ); + EVP_CIPHER_CTX_free( d_ctx ); + plaintext.resize( actual_size + final_size, '\0' ); + + return std::string( plaintext.begin(), plaintext.end() ); +} + } // namespace crypto diff --git a/tools/utils.h b/tools/utils.h index 5f7a40ea..62d4c957 100644 --- a/tools/utils.h +++ b/tools/utils.h @@ -68,14 +68,14 @@ class ThresholdUtils { } }; + static std::atomic< bool > is_initialized; + static void initCurve(); - static std::atomic< bool > is_initialized; + static void initAES(); static void checkSigners( size_t _requiredSigners, size_t _totalSigners ); - static std::vector< std::string > G2ToString( libff::alt_bn128_G2 elem ); - static std::vector< libff::alt_bn128_Fr > LagrangeCoeffs( const std::vector< size_t >& idx, size_t t ); @@ -85,10 +85,18 @@ class ThresholdUtils { static libff::alt_bn128_G1 HashtoG1( std::shared_ptr< std::array< uint8_t, 32 > > hash_byte_arr ); - static bool isStringNumber( std::string& str ); + static std::vector< uint8_t > aesEncrypt( const std::string& message, const std::string& key ); + + static std::string aesDecrypt( + const std::vector< uint8_t >& ciphertext, const std::string& key ); + + static bool isStringNumber( const std::string& str ); + + static int char2int( char _input ); - static void checkCypher( - const std::tuple< libff::alt_bn128_G2, std::string, libff::alt_bn128_G1 >& cypher ); + static std::string carray2Hex( const unsigned char* d, uint64_t len ); + + static bool hex2carray( const char* _hex, uint64_t* _bin_len, uint8_t* _bin ); static std::pair< libff::alt_bn128_Fq, libff::alt_bn128_Fq > ParseHint( const std::string& hint ); @@ -97,19 +105,29 @@ class ThresholdUtils { const std::shared_ptr< std::string >, const std::string& delim ); template < class T > - static std::string fieldElementToString( const T& field_elem ); + static std::string fieldElementToString( const T& field_elem, int base = 10 ); + + static std::vector< std::string > G2ToString( libff::alt_bn128_G2 elem, int base = 10 ); + + static libff::alt_bn128_G2 stringToG2( const std::string& str ); + + static libff::alt_bn128_G1 stringToG1( const std::string& str ); + + static std::string convertHexToDec( const std::string& hex_str ); + + static bool checkHex( const std::string& hex ); }; template < class T > -std::string ThresholdUtils::fieldElementToString( const T& field_elem ) { +std::string ThresholdUtils::fieldElementToString( const T& field_elem, int base ) { mpz_t t; mpz_init( t ); field_elem.as_bigint().to_mpz( t ); - char arr[mpz_sizeinbase( t, 10 ) + 2]; + char arr[mpz_sizeinbase( t, base ) + 2]; - char* tmp = mpz_get_str( arr, 10, t ); + char* tmp = mpz_get_str( arr, base, t ); mpz_clear( t ); std::string output = tmp;