mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
added encryption of message sync requests for external circles-restricted groups, and verification that properly encrypted requests are sent before sending encrypted msg ID lists
This commit is contained in:
parent
ff4c360e27
commit
c79c9bae5e
@ -715,10 +715,19 @@ void RsGxsNetService::syncWithPeers()
|
|||||||
{
|
{
|
||||||
const RsGxsGrpMetaData* meta = mmit->second;
|
const RsGxsGrpMetaData* meta = mmit->second;
|
||||||
const RsGxsGroupId& grpId = mmit->first;
|
const RsGxsGroupId& grpId = mmit->first;
|
||||||
|
RsGxsCircleId encrypt_to_this_circle_id ;
|
||||||
|
|
||||||
if(!checkCanRecvMsgFromPeer(peerId, *meta))
|
if(!checkCanRecvMsgFromPeer(peerId, *meta,encrypt_to_this_circle_id))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
#ifdef NXS_NET_DEBUG_0
|
||||||
|
GXSNETDEBUG_PG(peerId,grpId) << " peer can send messages for group " << grpId ;
|
||||||
|
if(!encrypt_to_this_circle_id.isNull())
|
||||||
|
std::cerr << " request should be encrypted for circle ID " << encrypt_to_this_circle_id << std::endl;
|
||||||
|
else
|
||||||
|
std::cerr << " request should be sent in clear." << std::endl;
|
||||||
|
|
||||||
|
#endif
|
||||||
// On default, the info has never been received so the TS is 0, meaning the peer has sent that it had no information.
|
// On default, the info has never been received so the TS is 0, meaning the peer has sent that it had no information.
|
||||||
|
|
||||||
uint32_t updateTS = 0;
|
uint32_t updateTS = 0;
|
||||||
@ -737,12 +746,20 @@ void RsGxsNetService::syncWithPeers()
|
|||||||
msg->grpId = grpId;
|
msg->grpId = grpId;
|
||||||
msg->updateTS = updateTS;
|
msg->updateTS = updateTS;
|
||||||
|
|
||||||
//NxsBandwidthRecorder::recordEvent(mServType,msg) ;
|
if(encrypt_to_this_circle_id.isNull())
|
||||||
|
sendItem(msg);
|
||||||
//if(RSRandom::random_f32() < sending_probability)
|
else
|
||||||
//{
|
{
|
||||||
|
RsNxsItem *encrypted_item = NULL ;
|
||||||
sendItem(msg);
|
uint32_t status ;
|
||||||
|
|
||||||
|
if(encryptSingleNxsItem(msg, encrypt_to_this_circle_id, encrypted_item, status))
|
||||||
|
sendItem(encrypted_item) ;
|
||||||
|
else
|
||||||
|
std::cerr << "(WW) could not encrypt for circle ID " << encrypt_to_this_circle_id << ". Not yet in cache?" << std::endl;
|
||||||
|
|
||||||
|
delete msg ;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef NXS_NET_DEBUG_5
|
#ifdef NXS_NET_DEBUG_5
|
||||||
GXSNETDEBUG_PG(*sit,grpId) << "Service "<< std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending global message TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) for group " << grpId << " to himself" << std::endl;
|
GXSNETDEBUG_PG(*sit,grpId) << "Service "<< std::hex << ((mServiceInfo.mServiceType >> 8)& 0xffff) << std::dec << " sending global message TS of peer id: " << *sit << " ts=" << nice_time_stamp(time(NULL),updateTS) << " (secs ago) for group " << grpId << " to himself" << std::endl;
|
||||||
@ -1583,13 +1600,31 @@ void RsGxsNetService::recvNxsItemQueue()
|
|||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
bool item_was_encrypted = false ;
|
||||||
|
|
||||||
|
if(ni->PacketSubType() == RS_PKT_SUBTYPE_NXS_ENCRYPTED_DATA_ITEM)
|
||||||
|
{
|
||||||
|
RsNxsItem *decrypted_item ;
|
||||||
|
uint32_t status ;
|
||||||
|
|
||||||
|
if(decryptSingleNxsItem(dynamic_cast<RsNxsEncryptedDataItem*>(ni),decrypted_item))
|
||||||
|
{
|
||||||
|
delete ni ;
|
||||||
|
ni = decrypted_item ;
|
||||||
|
item_was_encrypted = true ;
|
||||||
|
#ifdef NXS_NET_DEBUG_1
|
||||||
|
GXSNETDEBUG_P_(item->PeerId()) << " decrypted item " << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
std::cerr << "(EE) Could not decrypt incoming encrypted NXS item. Probably a friend subscribed to a circle-restricted group." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
switch(ni->PacketSubType())
|
switch(ni->PacketSubType())
|
||||||
{
|
{
|
||||||
case RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM: handleRecvSyncGrpStatistics (dynamic_cast<RsNxsSyncGrpStatsItem*>(ni)) ; break ;
|
case RS_PKT_SUBTYPE_NXS_SYNC_GRP_STATS_ITEM: handleRecvSyncGrpStatistics (dynamic_cast<RsNxsSyncGrpStatsItem*>(ni)) ; break ;
|
||||||
case RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM: handleRecvSyncGroup (dynamic_cast<RsNxsSyncGrpReqItem*>(ni)) ; break ;
|
case RS_PKT_SUBTYPE_NXS_SYNC_GRP_REQ_ITEM: handleRecvSyncGroup (dynamic_cast<RsNxsSyncGrpReqItem*>(ni)) ; break ;
|
||||||
case RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM: handleRecvSyncMessage (dynamic_cast<RsNxsSyncMsgReqItem*>(ni)) ; break ;
|
case RS_PKT_SUBTYPE_NXS_SYNC_MSG_REQ_ITEM: handleRecvSyncMessage (dynamic_cast<RsNxsSyncMsgReqItem*>(ni),item_was_encrypted) ; break ;
|
||||||
case RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM:handleRecvPublishKeys (dynamic_cast<RsNxsGroupPublishKeyItem*>(ni)) ; break ;
|
case RS_PKT_SUBTYPE_NXS_GRP_PUBLISH_KEY_ITEM:handleRecvPublishKeys (dynamic_cast<RsNxsGroupPublishKeyItem*>(ni)) ; break ;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -3741,89 +3776,12 @@ bool RsGxsNetService::processTransactionForDecryption(NxsTransaction *tr)
|
|||||||
continue ;
|
continue ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need the private keys to decrypt the item. First load them in!
|
|
||||||
bool key_loading_failed = false ;
|
|
||||||
|
|
||||||
if(private_keys.empty())
|
|
||||||
{
|
|
||||||
#ifdef NXS_NET_DEBUG_7
|
|
||||||
GXSNETDEBUG_P_(peerId) << " need to retrieve private keys..." << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::list<RsGxsId> own_keys ;
|
|
||||||
mGixs->getOwnIds(own_keys) ;
|
|
||||||
|
|
||||||
for(std::list<RsGxsId>::const_iterator it(own_keys.begin());it!=own_keys.end();++it)
|
|
||||||
{
|
|
||||||
RsTlvSecurityKey private_key ;
|
|
||||||
|
|
||||||
if(mGixs->getPrivateKey(*it,private_key))
|
|
||||||
{
|
|
||||||
private_keys.push_back(private_key) ;
|
|
||||||
#ifdef NXS_NET_DEBUG_7
|
|
||||||
GXSNETDEBUG_P_(peerId)<< " retrieved private key " << *it << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << " (EE) Cannot retrieve private key for ID " << *it << std::endl;
|
|
||||||
key_loading_failed = true ;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(key_loading_failed)
|
|
||||||
{
|
|
||||||
#ifdef NXS_NET_DEBUG_7
|
|
||||||
GXSNETDEBUG_P_(peerId) << " Some keys not loaded.Returning false to retry later." << std::endl;
|
|
||||||
#endif
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we do this only when something actually needs to be decrypted.
|
|
||||||
|
|
||||||
unsigned char *decrypted_mem = NULL;
|
|
||||||
uint32_t decrypted_len =0;
|
|
||||||
|
|
||||||
#ifdef NXS_NET_DEBUG_7
|
|
||||||
GXSNETDEBUG_P_(peerId)<< " Trying to decrypt item..." ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(!GxsSecurity::decrypt(decrypted_mem,decrypted_len, (uint8_t*)encrypted_item->encrypted_data.bin_data,encrypted_item->encrypted_data.bin_len,private_keys))
|
|
||||||
{
|
|
||||||
std::cerr << "Failed! Cannot decrypt this item." << std::endl;
|
|
||||||
decrypted_mem = NULL ; // for safety
|
|
||||||
}
|
|
||||||
#ifdef NXS_NET_DEBUG_7
|
|
||||||
GXSNETDEBUG_P_(peerId)<< " Succeeded! deserialising..." << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// deserialise the item
|
|
||||||
|
|
||||||
|
|
||||||
RsItem *ditem = NULL ;
|
|
||||||
RsNxsItem *nxsitem = NULL ;
|
|
||||||
|
|
||||||
if(decrypted_mem!=NULL)
|
|
||||||
{
|
|
||||||
ditem = RsNxsSerialiser(mServType).deserialise(decrypted_mem,&decrypted_len) ;
|
|
||||||
|
|
||||||
if(ditem != NULL)
|
|
||||||
{
|
|
||||||
ditem->PeerId((*it)->PeerId()) ; // This is needed because the deserialised item has no peer id
|
|
||||||
nxsitem = dynamic_cast<RsNxsItem*>(ditem) ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
std::cerr << " Cannot deserialise. Item encoding error!" << std::endl;
|
|
||||||
|
|
||||||
if(nxsitem == NULL)
|
|
||||||
std::cerr << " (EE) Deserialised item is not an NxsItem. Weird. Dropping transaction." << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove the encrypted item. After that it points to the next item to handle
|
// remove the encrypted item. After that it points to the next item to handle
|
||||||
it = tr->mItems.erase(it) ;
|
it = tr->mItems.erase(it) ;
|
||||||
|
|
||||||
if(nxsitem != NULL)
|
RsNxsItem *nxsitem = NULL ;
|
||||||
|
|
||||||
|
if(decryptSingleNxsItem(encrypted_item,nxsitem,&private_keys))
|
||||||
{
|
{
|
||||||
#ifdef NXS_NET_DEBUG_7
|
#ifdef NXS_NET_DEBUG_7
|
||||||
GXSNETDEBUG_P_(peerId) << " Replacing the encrypted item with the clear one." << std::endl;
|
GXSNETDEBUG_P_(peerId) << " Replacing the encrypted item with the clear one." << std::endl;
|
||||||
@ -3837,6 +3795,92 @@ bool RsGxsNetService::processTransactionForDecryption(NxsTransaction *tr)
|
|||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RsGxsNetService::decryptSingleNxsItem(const RsNxsEncryptedDataItem *encrypted_item, RsNxsItem *& nxsitem,std::vector<RsTlvSecurityKey> *pprivate_keys)
|
||||||
|
{
|
||||||
|
// if private_keys storage is supplied use/update them, otherwise, find which key should be used, and store them in a local std::vector.
|
||||||
|
|
||||||
|
nxsitem = NULL ;
|
||||||
|
std::vector<RsTlvSecurityKey> local_keys ;
|
||||||
|
std::vector<RsTlvSecurityKey>& private_keys = pprivate_keys?(*pprivate_keys):local_keys ;
|
||||||
|
|
||||||
|
// we need the private keys to decrypt the item. First load them in!
|
||||||
|
bool key_loading_failed = false ;
|
||||||
|
|
||||||
|
if(private_keys.empty())
|
||||||
|
{
|
||||||
|
#ifdef NXS_NET_DEBUG_7
|
||||||
|
GXSNETDEBUG_P_(peerId) << " need to retrieve private keys..." << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::list<RsGxsId> own_keys ;
|
||||||
|
mGixs->getOwnIds(own_keys) ;
|
||||||
|
|
||||||
|
for(std::list<RsGxsId>::const_iterator it(own_keys.begin());it!=own_keys.end();++it)
|
||||||
|
{
|
||||||
|
RsTlvSecurityKey private_key ;
|
||||||
|
|
||||||
|
if(mGixs->getPrivateKey(*it,private_key))
|
||||||
|
{
|
||||||
|
private_keys.push_back(private_key) ;
|
||||||
|
#ifdef NXS_NET_DEBUG_7
|
||||||
|
GXSNETDEBUG_P_(peerId)<< " retrieved private key " << *it << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << " (EE) Cannot retrieve private key for ID " << *it << std::endl;
|
||||||
|
key_loading_failed = true ;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(key_loading_failed)
|
||||||
|
{
|
||||||
|
#ifdef NXS_NET_DEBUG_7
|
||||||
|
GXSNETDEBUG_P_(peerId) << " Some keys not loaded.Returning false to retry later." << std::endl;
|
||||||
|
#endif
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we do this only when something actually needs to be decrypted.
|
||||||
|
|
||||||
|
unsigned char *decrypted_mem = NULL;
|
||||||
|
uint32_t decrypted_len =0;
|
||||||
|
|
||||||
|
#ifdef NXS_NET_DEBUG_7
|
||||||
|
GXSNETDEBUG_P_(peerId)<< " Trying to decrypt item..." ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!GxsSecurity::decrypt(decrypted_mem,decrypted_len, (uint8_t*)encrypted_item->encrypted_data.bin_data,encrypted_item->encrypted_data.bin_len,private_keys))
|
||||||
|
{
|
||||||
|
std::cerr << "Failed! Cannot decrypt this item." << std::endl;
|
||||||
|
decrypted_mem = NULL ; // for safety
|
||||||
|
}
|
||||||
|
#ifdef NXS_NET_DEBUG_7
|
||||||
|
GXSNETDEBUG_P_(peerId)<< " Succeeded! deserialising..." << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// deserialise the item
|
||||||
|
|
||||||
|
RsItem *ditem = NULL ;
|
||||||
|
|
||||||
|
if(decrypted_mem!=NULL)
|
||||||
|
{
|
||||||
|
ditem = RsNxsSerialiser(mServType).deserialise(decrypted_mem,&decrypted_len) ;
|
||||||
|
|
||||||
|
if(ditem != NULL)
|
||||||
|
{
|
||||||
|
ditem->PeerId(encrypted_item->PeerId()) ; // This is needed because the deserialised item has no peer id
|
||||||
|
nxsitem = dynamic_cast<RsNxsItem*>(ditem) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
std::cerr << " Cannot deserialise. Item encoding error!" << std::endl;
|
||||||
|
|
||||||
|
return (nxsitem != NULL) ;
|
||||||
|
}
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
void RsGxsNetService::cleanTransactionItems(NxsTransaction* tr) const
|
void RsGxsNetService::cleanTransactionItems(NxsTransaction* tr) const
|
||||||
{
|
{
|
||||||
std::list<RsNxsItem*>::iterator lit = tr->mItems.begin();
|
std::list<RsNxsItem*>::iterator lit = tr->mItems.begin();
|
||||||
@ -4163,7 +4207,7 @@ bool RsGxsNetService::canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpM
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxsGrpMetaData& grpMeta)
|
bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxsGrpMetaData& grpMeta, RsGxsCircleId &should_encrypt_id)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef NXS_NET_DEBUG_4
|
#ifdef NXS_NET_DEBUG_4
|
||||||
@ -4172,6 +4216,7 @@ bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxs
|
|||||||
#endif
|
#endif
|
||||||
// first do the simple checks
|
// first do the simple checks
|
||||||
uint8_t circleType = grpMeta.mCircleType;
|
uint8_t circleType = grpMeta.mCircleType;
|
||||||
|
should_encrypt_id.clear() ;
|
||||||
|
|
||||||
if(circleType == GXS_CIRCLE_TYPE_LOCAL)
|
if(circleType == GXS_CIRCLE_TYPE_LOCAL)
|
||||||
{
|
{
|
||||||
@ -4194,6 +4239,7 @@ bool RsGxsNetService::checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxs
|
|||||||
#ifdef NXS_NET_DEBUG_4
|
#ifdef NXS_NET_DEBUG_4
|
||||||
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: EXTERNAL => returning true. Msgs will be encrypted." << std::endl;
|
GXSNETDEBUG_PG(sslId,grpMeta.mGroupId) << " Circle type: EXTERNAL => returning true. Msgs will be encrypted." << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
should_encrypt_id = grpMeta.mCircleId ;
|
||||||
return true ;
|
return true ;
|
||||||
#ifdef TO_BE_REMOVED_OLD_VETTING_FOR_EXTERNAL_CIRCLES
|
#ifdef TO_BE_REMOVED_OLD_VETTING_FOR_EXTERNAL_CIRCLES
|
||||||
const RsGxsCircleId& circleId = grpMeta.mCircleId;
|
const RsGxsCircleId& circleId = grpMeta.mCircleId;
|
||||||
@ -4304,7 +4350,7 @@ bool RsGxsNetService::locked_CanReceiveUpdate(const RsNxsSyncMsgReqItem *item)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item)
|
void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item,bool item_was_encrypted)
|
||||||
{
|
{
|
||||||
if (!item)
|
if (!item)
|
||||||
return;
|
return;
|
||||||
@ -4352,6 +4398,17 @@ void RsGxsNetService::handleRecvSyncMessage(RsNxsSyncMsgReqItem *item)
|
|||||||
#endif
|
#endif
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( (grpMeta->mCircleType == GXS_CIRCLE_TYPE_EXTERNAL) != item_was_encrypted )
|
||||||
|
{
|
||||||
|
std::cerr << "(EE) received a sync Msg request for group " << item->grpId << " from peer " << item->PeerId() ;
|
||||||
|
if(!item_was_encrypted)
|
||||||
|
std::cerr << ". The group is tied to an external circle (ID=" << grpMeta->mCircleId << ") but the request wasn't encrypted." << std::endl;
|
||||||
|
else
|
||||||
|
std::cerr << ". The group is not tied to an external circle (ID=" << grpMeta->mCircleId << ") but the request was encrypted." << std::endl;
|
||||||
|
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
GxsMsgReq req;
|
GxsMsgReq req;
|
||||||
req[item->grpId] = std::vector<RsGxsMessageId>();
|
req[item->grpId] = std::vector<RsGxsMessageId>();
|
||||||
|
@ -332,7 +332,7 @@ private:
|
|||||||
* Handles an nxs item for msgs synchronisation
|
* Handles an nxs item for msgs synchronisation
|
||||||
* @param item contaims msg sync info
|
* @param item contaims msg sync info
|
||||||
*/
|
*/
|
||||||
void handleRecvSyncMessage(RsNxsSyncMsgReqItem* item);
|
void handleRecvSyncMessage(RsNxsSyncMsgReqItem* item,bool item_was_encrypted);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Handles an nxs item for group publish key
|
* Handles an nxs item for group publish key
|
||||||
@ -354,7 +354,7 @@ private:
|
|||||||
bool canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpMeta, std::vector<GrpIdCircleVet>& toVet, bool &should_encrypt);
|
bool canSendGrpId(const RsPeerId& sslId, RsGxsGrpMetaData& grpMeta, std::vector<GrpIdCircleVet>& toVet, bool &should_encrypt);
|
||||||
bool canSendMsgIds(std::vector<RsGxsMsgMetaData*>& msgMetas, const RsGxsGrpMetaData&, const RsPeerId& sslId, RsGxsCircleId &should_encrypt_id);
|
bool canSendMsgIds(std::vector<RsGxsMsgMetaData*>& msgMetas, const RsGxsGrpMetaData&, const RsPeerId& sslId, RsGxsCircleId &should_encrypt_id);
|
||||||
|
|
||||||
bool checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxsGrpMetaData& meta);
|
bool checkCanRecvMsgFromPeer(const RsPeerId& sslId, const RsGxsGrpMetaData& meta, RsGxsCircleId& should_encrypt_id);
|
||||||
|
|
||||||
void locked_createTransactionFromPending(MsgRespPending* grpPend);
|
void locked_createTransactionFromPending(MsgRespPending* grpPend);
|
||||||
void locked_createTransactionFromPending(GrpRespPending* msgPend);
|
void locked_createTransactionFromPending(GrpRespPending* msgPend);
|
||||||
@ -455,6 +455,7 @@ private:
|
|||||||
* encrypts/decrypts the transaction for the destination circle id.
|
* encrypts/decrypts the transaction for the destination circle id.
|
||||||
*/
|
*/
|
||||||
bool encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, RsNxsItem *& encrypted_item, uint32_t &status) ;
|
bool encryptSingleNxsItem(RsNxsItem *item, const RsGxsCircleId& destination_circle, RsNxsItem *& encrypted_item, uint32_t &status) ;
|
||||||
|
bool decryptSingleNxsItem(const RsNxsEncryptedDataItem *encrypted_item, RsNxsItem *&nxsitem, std::vector<RsTlvSecurityKey> *private_keys=NULL);
|
||||||
bool processTransactionForDecryption(NxsTransaction *tr); // return false when the keys are not loaded => need retry later
|
bool processTransactionForDecryption(NxsTransaction *tr); // return false when the keys are not loaded => need retry later
|
||||||
|
|
||||||
void cleanRejectedMessages();
|
void cleanRejectedMessages();
|
||||||
|
Loading…
Reference in New Issue
Block a user