SKALE-4411 add new function to http server

parent ca720ecb
...@@ -985,20 +985,20 @@ SGXWalletServer::createBLSPrivateKeyV2Impl(const string &_blsKeyName, const stri ...@@ -985,20 +985,20 @@ SGXWalletServer::createBLSPrivateKeyV2Impl(const string &_blsKeyName, const stri
RETURN_SUCCESS(result); RETURN_SUCCESS(result);
} }
Json::Value SGXWalletServer::getDecryptionShareImpl(const std::string& teKeyName, const std::string& publicDecryptionValue) { Json::Value SGXWalletServer::getDecryptionShareImpl(const std::string& blsKeyName, const std::string& publicDecryptionValue) {
spdlog::info("Entering {}", __FUNCTION__); spdlog::info("Entering {}", __FUNCTION__);
INIT_RESULT(result) INIT_RESULT(result)
try { try {
if (!checkName(teKeyName, "BLS_KEY")) { if (!checkName(blsKeyName, "BLS_KEY")) {
throw SGXException(BLS_SIGN_INVALID_KS_NAME, string(__FUNCTION__) + ":Invalid BLSKey name"); throw SGXException(BLS_SIGN_INVALID_KS_NAME, string(__FUNCTION__) + ":Invalid BLSKey name");
} }
shared_ptr<string> encryptedKeyHex_ptr = readFromDb(teKeyName); shared_ptr<string> encryptedKeyHex_ptr = readFromDb(blsKeyName);
vector<string> decryptionValueVector = calculateDecryptionShare(encryptedKeyHex_ptr->c_str(), publicDecryptionValue); vector<string> decryptionValueVector = calculateDecryptionShare(encryptedKeyHex_ptr->c_str(), publicDecryptionValue);
for (uint8_t i = 0; i < 4; ++i) { for (uint8_t i = 0; i < 4; ++i) {
result["decryptionValue"][i] = decryptionValueVector.at(i); result["decryptionShare"][i] = decryptionValueVector.at(i);
} }
} HANDLE_SGX_EXCEPTION(result) } HANDLE_SGX_EXCEPTION(result)
...@@ -1105,8 +1105,8 @@ SGXWalletServer::createBLSPrivateKeyV2(const string &blsKeyName, const string &e ...@@ -1105,8 +1105,8 @@ SGXWalletServer::createBLSPrivateKeyV2(const string &blsKeyName, const string &e
return createBLSPrivateKeyV2Impl(blsKeyName, ethKeyName, polyName, SecretShare, t, n); return createBLSPrivateKeyV2Impl(blsKeyName, ethKeyName, polyName, SecretShare, t, n);
} }
Json::Value SGXWalletServer::getDecryptionShare(const std::string& teKeyName, const std::string& publicDecryptionValue) { Json::Value SGXWalletServer::getDecryptionShare(const std::string& blsKeyName, const std::string& publicDecryptionValue) {
return getDecryptionShareImpl(teKeyName, publicDecryptionValue); return getDecryptionShareImpl(blsKeyName, publicDecryptionValue);
} }
shared_ptr <string> SGXWalletServer::readFromDb(const string &name, const string &prefix) { shared_ptr <string> SGXWalletServer::readFromDb(const string &name, const string &prefix) {
......
...@@ -176,7 +176,7 @@ public: ...@@ -176,7 +176,7 @@ public:
static Json::Value createBLSPrivateKeyV2Impl(const std::string& blsKeyName, const std::string& ethKeyName, const std::string& polyName, const std::string & SecretShare, int t, int n); static Json::Value createBLSPrivateKeyV2Impl(const std::string& blsKeyName, const std::string& ethKeyName, const std::string& polyName, const std::string & SecretShare, int t, int n);
static Json::Value getDecryptionShareImpl(const std::string& teKeyName, const std::string& publicDecryptionValue); static Json::Value getDecryptionShareImpl(const std::string& KeyName, const std::string& publicDecryptionValue);
static void printDB(); static void printDB();
......
...@@ -34,12 +34,11 @@ ...@@ -34,12 +34,11 @@
#include "common.h" #include "common.h"
#include "SGXWalletServer.h" #include "SGXWalletServer.h"
#include "SEKManager.h"
#include "LevelDB.h"
#include "ServerInit.h"
#include "TECrypto.h" #include "TECrypto.h"
#include "CryptoTools.h" #include "CryptoTools.h"
#include <bls/BLSutils.h>
vector<string> calculateDecryptionShare(const string& encryptedKeyShare, vector<string> calculateDecryptionShare(const string& encryptedKeyShare,
const string& publicDecryptionValue) { const string& publicDecryptionValue) {
size_t sz = 0; size_t sz = 0;
...@@ -50,5 +49,22 @@ vector<string> calculateDecryptionShare(const string& encryptedKeyShare, ...@@ -50,5 +49,22 @@ vector<string> calculateDecryptionShare(const string& encryptedKeyShare,
if (!result) { if (!result) {
BOOST_THROW_EXCEPTION(invalid_argument("Invalid hex encrypted key")); BOOST_THROW_EXCEPTION(invalid_argument("Invalid hex encrypted key"));
} }
SAFE_CHAR_BUF(decryptionShare, BUF_LEN)
vector<char> errMsg(BUF_LEN, 0);
int errStatus = 0;
sgx_status_t status = SGX_SUCCESS;
status = trustedGetDecryptionShare(eid, &errStatus, errMsg.data(), encryptedKey,
publicDecryptionValue.data(), sz, decryptionShare);
HANDLE_TRUSTED_FUNCTION_ERROR(status, errStatus, errMsg.data());
auto splitted_share = BLSutils::SplitString(std::make_shared<std::string>(decryptionShare), ":");
return *splitted_share;
} }
\ No newline at end of file
...@@ -63,7 +63,7 @@ class AbstractStubServer : public jsonrpc::AbstractServer<AbstractStubServer> ...@@ -63,7 +63,7 @@ class AbstractStubServer : public jsonrpc::AbstractServer<AbstractStubServer>
this->bindAndAddMethod(jsonrpc::Procedure("dkgVerificationV2", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, "publicShares",jsonrpc::JSON_STRING, "ethKeyName",jsonrpc::JSON_STRING, "secretShare",jsonrpc::JSON_STRING,"t",jsonrpc::JSON_INTEGER, "n",jsonrpc::JSON_INTEGER, "index",jsonrpc::JSON_INTEGER, NULL), &AbstractStubServer::dkgVerificationV2I); this->bindAndAddMethod(jsonrpc::Procedure("dkgVerificationV2", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, "publicShares",jsonrpc::JSON_STRING, "ethKeyName",jsonrpc::JSON_STRING, "secretShare",jsonrpc::JSON_STRING,"t",jsonrpc::JSON_INTEGER, "n",jsonrpc::JSON_INTEGER, "index",jsonrpc::JSON_INTEGER, NULL), &AbstractStubServer::dkgVerificationV2I);
this->bindAndAddMethod(jsonrpc::Procedure("createBLSPrivateKeyV2", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, "blsKeyName",jsonrpc::JSON_STRING, "ethKeyName",jsonrpc::JSON_STRING, "polyName", jsonrpc::JSON_STRING, "secretShare",jsonrpc::JSON_STRING,"t", jsonrpc::JSON_INTEGER,"n",jsonrpc::JSON_INTEGER, NULL), &AbstractStubServer::createBLSPrivateKeyV2I); this->bindAndAddMethod(jsonrpc::Procedure("createBLSPrivateKeyV2", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, "blsKeyName",jsonrpc::JSON_STRING, "ethKeyName",jsonrpc::JSON_STRING, "polyName", jsonrpc::JSON_STRING, "secretShare",jsonrpc::JSON_STRING,"t", jsonrpc::JSON_INTEGER,"n",jsonrpc::JSON_INTEGER, NULL), &AbstractStubServer::createBLSPrivateKeyV2I);
this->bindAndAddMethod(jsonrpc::Procedure("getDecryptionShare", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, "teKeyName",jsonrpc::JSON_STRING,"publicDecryptionValue",jsonrpc::JSON_STRING, NULL), &AbstractStubServer::getDecryptionShareI); this->bindAndAddMethod(jsonrpc::Procedure("getDecryptionShare", jsonrpc::PARAMS_BY_NAME, jsonrpc::JSON_OBJECT, "blsKeyName",jsonrpc::JSON_STRING,"publicDecryptionValue",jsonrpc::JSON_STRING, NULL), &AbstractStubServer::getDecryptionShareI);
} }
inline virtual void importBLSKeyShareI(const Json::Value &request, Json::Value &response) inline virtual void importBLSKeyShareI(const Json::Value &request, Json::Value &response)
...@@ -165,7 +165,7 @@ class AbstractStubServer : public jsonrpc::AbstractServer<AbstractStubServer> ...@@ -165,7 +165,7 @@ class AbstractStubServer : public jsonrpc::AbstractServer<AbstractStubServer>
inline virtual void getDecryptionShareI(const Json::Value &request, Json::Value &response) inline virtual void getDecryptionShareI(const Json::Value &request, Json::Value &response)
{ {
response = this->getDecryptionShare(request["teKeyName"].asString(), request["publicDecryptionValue"].asString()); response = this->getDecryptionShare(request["blsKeyName"].asString(), request["publicDecryptionValue"].asString());
} }
virtual Json::Value importBLSKeyShare(const std::string& keyShare, const std::string& keyShareName) = 0; virtual Json::Value importBLSKeyShare(const std::string& keyShare, const std::string& keyShareName) = 0;
...@@ -194,7 +194,7 @@ class AbstractStubServer : public jsonrpc::AbstractServer<AbstractStubServer> ...@@ -194,7 +194,7 @@ class AbstractStubServer : public jsonrpc::AbstractServer<AbstractStubServer>
virtual Json::Value dkgVerificationV2( const std::string& publicShares, const std::string& ethKeyName, const std::string& SecretShare, int t, int n, int index) = 0; virtual Json::Value dkgVerificationV2( const std::string& publicShares, const std::string& ethKeyName, const std::string& SecretShare, int t, int n, int index) = 0;
virtual Json::Value createBLSPrivateKeyV2(const std::string& blsKeyName, const std::string& ethKeyName, const std::string& polyName, const std::string & SecretShare, int t, int n) = 0; virtual Json::Value createBLSPrivateKeyV2(const std::string& blsKeyName, const std::string& ethKeyName, const std::string& polyName, const std::string & SecretShare, int t, int n) = 0;
virtual Json::Value getDecryptionShare(const std::string& teKeyName, const std::string& publicDecryptionValue) = 0; virtual Json::Value getDecryptionShare(const std::string& KeyName, const std::string& publicDecryptionValue) = 0;
}; };
#endif //JSONRPC_CPP_STUB_ABSTRACTSTUBSERVER_H_ #endif //JSONRPC_CPP_STUB_ABSTRACTSTUBSERVER_H_
...@@ -84,7 +84,7 @@ CLEANFILES+= secure_enclave_t.c secure_enclave_t.h ...@@ -84,7 +84,7 @@ CLEANFILES+= secure_enclave_t.c secure_enclave_t.h
secure_enclave_SOURCES = secure_enclave_t.c secure_enclave_t.h \ secure_enclave_SOURCES = secure_enclave_t.c secure_enclave_t.h \
secure_enclave.c \ secure_enclave.c \
Curves.c NumberTheory.c Point.c Signature.c DHDkg.c AESUtils.c \ Curves.c NumberTheory.c Point.c Signature.c DHDkg.c AESUtils.c \
DKGUtils.cpp EnclaveCommon.cpp DomainParameters.cpp ../third_party/SCIPR/libff/algebra/curves/alt_bn128/alt_bn128_init.cpp \ DKGUtils.cpp TEUtils.cpp EnclaveCommon.cpp DomainParameters.cpp ../third_party/SCIPR/libff/algebra/curves/alt_bn128/alt_bn128_init.cpp \
../third_party/SCIPR/libff/algebra/curves/alt_bn128/alt_bn128_g2.cpp \ ../third_party/SCIPR/libff/algebra/curves/alt_bn128/alt_bn128_g2.cpp \
../third_party/SCIPR/libff/algebra/curves/alt_bn128/alt_bn128_g1.cpp $(ENCLAVE_KEY) $(ENCLAVE_CONFIG) ../third_party/SCIPR/libff/algebra/curves/alt_bn128/alt_bn128_g1.cpp $(ENCLAVE_KEY) $(ENCLAVE_CONFIG)
...@@ -113,7 +113,7 @@ secure_enclave_LDADD = @SGX_ENCLAVE_LDADD@ ...@@ -113,7 +113,7 @@ secure_enclave_LDADD = @SGX_ENCLAVE_LDADD@
## --startgroup and --endgroup flags. (This would be where you'd add ## --startgroup and --endgroup flags. (This would be where you'd add
## SGXSSL libraries, and your trusted c++ library ## SGXSSL libraries, and your trusted c++ library
SGX_EXTRA_TLIBS=-lsgx_tgmp -lsgx_tservice -lsgx_urts -lsgx_tcxx SGX_EXTRA_TLIBS=-lsgx_tgmp -lsgx_tservice -lsgx_urts -lsgx_tcxx
......
This diff is collapsed.
...@@ -37,6 +37,175 @@ ...@@ -37,6 +37,175 @@
#include <../tgmp-build/include/sgx_tgmp.h> #include <../tgmp-build/include/sgx_tgmp.h>
#endif #endif
EXTERNC int getDecryptionShare( char* secret, unsigned _t); #include <cstdio>
#include <stdio.h>
#include <string>
#include <vector>
#include <../SCIPR/libff/algebra/curves/alt_bn128/alt_bn128_pp.hpp>
#include <../SCIPR/libff/algebra/fields/fp.hpp>
#include <../SCIPR/libff/algebra/curves/alt_bn128/alt_bn128_g2.hpp>
#include "EnclaveConstants.h"
#include "EnclaveCommon.h"
#include "TEUtils.h"
template<class T>
std::string fieldElementToString(const T &field_elem, int base = 10) {
std::string ret;
mpz_t t;
mpz_init(t);
try {
field_elem.as_bigint().to_mpz(t);
SAFE_CHAR_BUF(arr, BUF_LEN);
char *tmp = mpz_get_str(arr, base, t);
ret = std::string(tmp);
goto clean;
} catch (std::exception &e) {
LOG_ERROR(e.what());
goto clean;
} catch (...) {
LOG_ERROR("Unknown throwable");
goto clean;
}
clean:
mpz_clear(t);
return ret;
}
std::string ConvertG2ElementToString(const libff::alt_bn128_G2 &elem, int base = 10, const std::string &delim = ":") {
std::string result = "";
try {
result += fieldElementToString(elem.X.c0);
result += delim;
result += fieldElementToString(elem.X.c1);
result += delim;
result += fieldElementToString(elem.Y.c0);
result += delim;
result += fieldElementToString(elem.Y.c1);
return result;
} catch (std::exception &e) {
LOG_ERROR(e.what());
return result;
} catch (...) {
LOG_ERROR("Unknown throwable");
return result;
}
return result;
}
std::vector <libff::alt_bn128_Fq> SplitStringToFq(const char *coeffs, const char symbol) {
std::vector <libff::alt_bn128_Fq > result;
std::string str(coeffs);
std::string delim;
CHECK_ARG_CLEAN(coeffs);
try {
delim.push_back(symbol);
size_t prev = 0, pos = 0;
do {
pos = str.find(delim, prev);
if (pos == std::string::npos) pos = str.length();
std::string token = str.substr(prev, pos - prev);
if (!token.empty()) {
libff::alt_bn128_Fq coeff(token.c_str());
result.push_back(coeff);
}
prev = pos + delim.length();
} while (pos < str.length() && prev < str.length());
return result;
} catch (std::exception &e) {
LOG_ERROR(e.what());
return result;
} catch (...) {
LOG_ERROR("Unknown throwable");
return result;
}
clean:
return result;
}
EXTERNC int getDecryptionShare(char* skey_hex, char* decryptionValue, char* decryption_share) {
mpz_t skey;
mpz_init(skey);
int ret = 1;
CHECK_ARG_CLEAN(skey_hex);
CHECK_ARG_CLEAN(decryptionValue);
CHECK_ARG_CLEAN(decryption_share);
try {
if (mpz_set_str(skey, skey_hex, 16) == -1) {
mpz_clear(skey);
return 1;
}
char skey_dec[mpz_sizeinbase(skey, 10) + 2];
mpz_get_str(skey_dec, 10, skey);
libff::alt_bn128_Fr bls_skey(skey_dec);
auto splitted_decryption_value = SplitStringToFq(decryptionValue, ':');
libff::alt_bn128_G2 decryption_value;
decryption_value.Z = libff::alt_bn128_Fq2::one();
decryption_value.X.c0 = splitted_decryption_value[0];
decryption_value.X.c1 = splitted_decryption_value[1];
decryption_value.Y.c0 = splitted_decryption_value[2];
decryption_value.Y.c1 = splitted_decryption_value[3];
if ( !decryption_value.is_well_formed() ) {
mpz_clear(skey);
return 1;
}
libff::alt_bn128_G2 decryption_share_point = bls_skey * decryption_value;
decryption_share_point.to_affine_coordinates();
std::string result = ConvertG2ElementToString(decryption_share_point);
strncpy(decryption_share, result.c_str(), result.length());
mpz_clear(skey);
return 0;
} catch (std::exception &e) {
LOG_ERROR(e.what());
return 1;
} catch (...) {
LOG_ERROR("Unknown throwable");
return 1;
}
clean:
mpz_clear(skey);
return ret;
}
#endif #endif
...@@ -37,6 +37,6 @@ ...@@ -37,6 +37,6 @@
#include <../tgmp-build/include/sgx_tgmp.h> #include <../tgmp-build/include/sgx_tgmp.h>
#endif #endif
EXTERNC int getDecryptionShare(char* secret, unsigned _t); EXTERNC int getDecryptionShare(char* secret, char* decryptionValue, char* decryption_share);
#endif #endif
...@@ -54,6 +54,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -54,6 +54,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Curves.h" #include "Curves.h"
#include "DHDkg.h" #include "DHDkg.h"
#include "AESUtils.h" #include "AESUtils.h"
#include "TEUtils.h"
#include "EnclaveConstants.h" #include "EnclaveConstants.h"
#include "EnclaveCommon.h" #include "EnclaveCommon.h"
...@@ -1368,3 +1369,35 @@ trustedGetBlsPubKey(int *errStatus, char *errString, uint8_t *encryptedPrivateKe ...@@ -1368,3 +1369,35 @@ trustedGetBlsPubKey(int *errStatus, char *errString, uint8_t *encryptedPrivateKe
clean: clean:
; ;
} }
void trustedGetDecryptionShare( int *errStatus, char* errString, uint8_t* encryptedPrivateKey,
const char* public_decryption_value, uint64_t key_len,
char* decryption_share ) {
LOG_DEBUG(__FUNCTION__);
INIT_ERROR_STATE
CHECK_STATE(decryption_share);
CHECK_STATE(encryptedPrivateKey);
SAFE_CHAR_BUF(skey_hex, BUF_LEN);
uint8_t type = 0;
uint8_t exportable = 0;
int status = AES_decrypt(encryptedPrivateKey, key_len, skey_hex, BUF_LEN,
&type, &exportable);
CHECK_STATUS2("AES decrypt failed %d");
skey_hex[ECDSA_SKEY_LEN - 1] = 0;
status = getDecryptionShare(skey_hex, public_decryption_value, decryption_share);
CHECK_STATUS("could not calculate decryption share");
SET_SUCCESS
clean:
;
}
...@@ -174,10 +174,18 @@ enclave { ...@@ -174,10 +174,18 @@ enclave {
public void trustedGetBlsPubKey( public void trustedGetBlsPubKey(
[out]int *errStatus, [out]int *errStatus,
[out, count = SMALL_BUF_SIZE] char* err_string, [out, count = SMALL_BUF_SIZE] char* err_string,
[in, count = SMALL_BUF_SIZE] uint8_t* encrypted_key, [in, count = SMALL_BUF_SIZE] uint8_t* encrypted_key,
uint64_t key_len, uint64_t key_len,
[out, count = 320] char* bls_pub_key); [out, count = 320] char* bls_pub_key);
public void trustedGetDecryptionShare(
[out]int *errStatus,
[out, count = SMALL_BUF_SIZE] char* err_string,
[in, count = SMALL_BUF_SIZE] uint8_t* encrypted_key,
[in, count = 320] const char* public_decryption_value,
uint64_t key_len,
[out, count = 320] char* decrption_share);
}; };
untrusted { untrusted {
......
...@@ -214,6 +214,19 @@ class StubClient : public jsonrpc::Client ...@@ -214,6 +214,19 @@ class StubClient : public jsonrpc::Client
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString()); throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
} }
Json::Value getDecryptionShare(const std::string& blsKeyName, const std::string& publicDecryptionValue)
{
Json::Value p;
p["blsKeyName"] = blsKeyName;
p["publicDecryptionValue"] = publicDecryptionValue;
Json::Value result = this->CallMethod("getDecryptionShare",p);
if (result.isObject())
return result;
else
throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());
}
Json::Value calculateAllBLSPublicKeys(const Json::Value& publicShares, int t, int n) Json::Value calculateAllBLSPublicKeys(const Json::Value& publicShares, int t, int n)
{ {
Json::Value p; Json::Value p;
......
...@@ -1183,6 +1183,38 @@ TEST_CASE_METHOD(TestFixtureNoReset, "Second run", "[second-run]") { ...@@ -1183,6 +1183,38 @@ TEST_CASE_METHOD(TestFixtureNoReset, "Second run", "[second-run]") {
} }
} }
TEST_CASE_METHOD(TestFixture, "Test decryption share for threshold encryption", "[te-decryption-share]") {
// auto client = make_shared<ZMQClient>(ZMQ_IP, ZMQ_PORT, true, "./sgx_data/cert_data/rootCA.pem",
// "./sgx_data/cert_data/rootCA.key");
HttpClient client(RPC_ENDPOINT);
StubClient c(client, JSONRPC_CLIENT_V2);
std::string key_str = "0xe632f7fde2c90a073ec43eaa90dca7b82476bf28815450a11191484934b9c3f";
std::string name = "BLS_KEY:SCHAIN_ID:123456789:NODE_ID:0:DKG_ID:0";
auto response = c.importBLSKeyShare(key_str, name);
// the same key writtn in decimal
libff::alt_bn128_Fr key = libff::alt_bn128_Fr(
"6507625568967977077291849236396320012317305261598035438182864059942098934847");
libff::alt_bn128_G2 decryption_value = libff::alt_bn128_G2::random_element();
decryption_value.to_affine_coordinates();
auto decrytion_value_str = convertG2ToString( decryption_value, ':' );
auto decryption_share = c.getDecryptionShare( name, decrytion_value_str )["decryptionShare"];
libff::alt_bn128_G2 share;
share.Z = libff::alt_bn128_Fq2::one();
share.X.c0 = libff::alt_bn128_Fq( decryption_share[0].asCString() );
share.X.c1 = libff::alt_bn128_Fq( decryption_share[1].asCString() );
share.Y.c0 = libff::alt_bn128_Fq( decryption_share[2].asCString() );
share.Y.c1 = libff::alt_bn128_Fq( decryption_share[3].asCString() );
REQUIRE( share == key * decryption_value );
}
TEST_CASE_METHOD(TestFixtureZMQSign, "ZMQ-ecdsa", "[zmq-ecdsa]") { TEST_CASE_METHOD(TestFixtureZMQSign, "ZMQ-ecdsa", "[zmq-ecdsa]") {
HttpClient htp(RPC_ENDPOINT); HttpClient htp(RPC_ENDPOINT);
......
...@@ -62,7 +62,8 @@ testList = [ "[zmq-ecdsa]", ...@@ -62,7 +62,8 @@ testList = [ "[zmq-ecdsa]",
"[dkg-aes-pub-shares]", "[dkg-aes-pub-shares]",
"[aes-encrypt-decrypt]", "[aes-encrypt-decrypt]",
"[aes-dkg-v2]", "[aes-dkg-v2]",
"[aes-dkg-v2-zmq]" "[aes-dkg-v2-zmq]",
"[te-decryption-share]"
] ]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment