mirror of
https://github.com/twisterarmy/twister-core.git
synced 2025-02-04 02:44:16 +00:00
Properly implement spam signing and checking to prevent it from been used to impersonate users.
"nobody" is an exception so default client could still send unauthenticated/anonymous spam messages.
This commit is contained in:
parent
277c917b53
commit
2c48386b4e
4
TODO
4
TODO
@ -66,10 +66,6 @@ of his own torrent)
|
|||||||
- Estimate number of online followers by quering the "tracker" resource (implement a value within
|
- Estimate number of online followers by quering the "tracker" resource (implement a value within
|
||||||
this resource to report the number of torrent peers)
|
this resource to report the number of torrent peers)
|
||||||
|
|
||||||
- Properly implement spam signing and checking to prevent it from been used to impersonate users.
|
|
||||||
"nobody" might be an exception so default client could still send unauthenticated/anonymous spam
|
|
||||||
messages.
|
|
||||||
|
|
||||||
- Define and enforce html directory to serve from. Do installation scripts.
|
- Define and enforce html directory to serve from. Do installation scripts.
|
||||||
|
|
||||||
- Don't accept dht "post"+k if k violates the validatePostNumberForUser() rule.
|
- Don't accept dht "post"+k if k violates the validatePostNumberForUser() rule.
|
||||||
|
@ -124,64 +124,6 @@ bool AppInit(int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const string strSecret1C ("Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw");
|
|
||||||
|
|
||||||
static bool TestCreateSpamMsgTx()
|
|
||||||
{
|
|
||||||
CTransaction txNew;
|
|
||||||
|
|
||||||
txNew.message = CScript() << strSpamMessage;
|
|
||||||
|
|
||||||
CBitcoinSecret bsecret1;
|
|
||||||
bsecret1.SetString (strSecret1C);
|
|
||||||
|
|
||||||
CKey key;
|
|
||||||
key.MakeNewKey(true);
|
|
||||||
//CKey key = bsecret1.GetKey();
|
|
||||||
CPubKey pubkey( key.GetPubKey() );
|
|
||||||
|
|
||||||
printf("key valid: %d compressed: %d\n", key.IsValid(), key.IsCompressed());
|
|
||||||
printf("pubkey: %s\n", EncodeBase64(&pubkey[0], pubkey.size()).c_str() );
|
|
||||||
|
|
||||||
// compute message hash and sign it
|
|
||||||
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
|
||||||
ss << txNew.message;
|
|
||||||
uint256 hashMsg = ss.GetHash();
|
|
||||||
|
|
||||||
// vchSig is sig(hash(message))
|
|
||||||
vector<unsigned char> vchSig;
|
|
||||||
if (!key.Sign(hashMsg, vchSig)) {
|
|
||||||
printf("CreateNewBlock: Failed to sign SpamMessage\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
vector<unsigned char> vchSigCompact;
|
|
||||||
if (!key.SignCompact(hashMsg, vchSigCompact)) {
|
|
||||||
printf("CreateNewBlock: Failed to sign SpamMessage2\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
printf("sign size: %zu signCompact size: %zu\n", vchSig.size(), vchSigCompact.size());
|
|
||||||
printf("signCompact: %s\n", EncodeBase64(&vchSigCompact[0], vchSigCompact.size()).c_str());
|
|
||||||
*/
|
|
||||||
|
|
||||||
printf("CreateSpamMsgTx: msg = %s user = %s hash = %s signedhash = %s\n", txNew.message.ToString().c_str(), strSpamUser.c_str(),
|
|
||||||
hashMsg.ToString().c_str(), EncodeBase64(&vchSig[0], vchSig.size()).c_str() );
|
|
||||||
|
|
||||||
// add username and signature
|
|
||||||
txNew.userName = CScript() << strSpamUser;
|
|
||||||
txNew.userName += CScript() << vchSig;
|
|
||||||
txNew.pubKey.clear(); // pubKey will be updated to include extranonce
|
|
||||||
txNew.nNonce = 0; // no update needed for spamMessage's nonce.
|
|
||||||
|
|
||||||
std::vector< std::vector<unsigned char> > vData;
|
|
||||||
txNew.userName.ExtractPushData(vData);
|
|
||||||
|
|
||||||
printf("Verify: %d\n", pubkey.Verify(hashMsg,vData[1]));
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void GenesisMiner();
|
extern void GenesisMiner();
|
||||||
extern void noui_connect();
|
extern void noui_connect();
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
@ -190,7 +132,6 @@ int main(int argc, char* argv[])
|
|||||||
fHaveGUI = false;
|
fHaveGUI = false;
|
||||||
|
|
||||||
//GenesisMiner();
|
//GenesisMiner();
|
||||||
//TestCreateSpamMsgTx();
|
|
||||||
|
|
||||||
// Connect bitcoind signal handlers
|
// Connect bitcoind signal handlers
|
||||||
noui_connect();
|
noui_connect();
|
||||||
|
58
src/main.cpp
58
src/main.cpp
@ -425,10 +425,45 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
|
|||||||
{
|
{
|
||||||
// Basic checks that don't depend on any context
|
// Basic checks that don't depend on any context
|
||||||
if (tx.IsSpamMessage()) {
|
if (tx.IsSpamMessage()) {
|
||||||
if (tx.message.size() > MAX_SPAM_MSG_SIZE)
|
string spamMsg = tx.message.ExtractPushDataString(0);
|
||||||
return state.DoS(100, error("CheckTransaction() : spam message too big"));
|
if (!spamMsg.size())
|
||||||
// [MF] TODO: check message signature
|
return state.DoS(100, error("CheckTransaction() : invalid or empty spam message"));
|
||||||
// [MF] Problem: registration of this user may be in the block itself, better check later.
|
if (spamMsg.size() > MAX_SPAM_MSG_SIZE)
|
||||||
|
return state.DoS(100, error("CheckTransaction() : spam message too big"));
|
||||||
|
|
||||||
|
string spamUser = tx.userName.ExtractPushDataString(0);
|
||||||
|
if( spamUser != "nobody" ) {
|
||||||
|
string strSign = tx.userName.ExtractPushDataString(1);
|
||||||
|
if (!strSign.size())
|
||||||
|
return state.DoS(100, error("CheckTransaction() : spam signature missing"));
|
||||||
|
vector<unsigned char> vchSig((const unsigned char*)strSign.data(),
|
||||||
|
(const unsigned char*)strSign.data() + strSign.size());
|
||||||
|
|
||||||
|
CPubKey pubkey;
|
||||||
|
CTransaction txPubKey;
|
||||||
|
uint256 hashBlock;
|
||||||
|
uint256 userhash = SerializeHash(spamUser);
|
||||||
|
if( !GetTransaction(userhash, txPubKey, hashBlock) )
|
||||||
|
return state.DoS(100, error("CheckTransaction() : spam signed by unknown user"));
|
||||||
|
|
||||||
|
std::vector< std::vector<unsigned char> > vData;
|
||||||
|
if( !txPubKey.pubKey.ExtractPushData(vData) || vData.size() < 1 )
|
||||||
|
return state.DoS(100, error("CheckTransaction() : spam signed with broken pubkey"));
|
||||||
|
|
||||||
|
pubkey = CPubKey(vData[0]);
|
||||||
|
|
||||||
|
// compute message hash for signature checking
|
||||||
|
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
||||||
|
ss << strMessageMagic;
|
||||||
|
ss << tx.message;
|
||||||
|
|
||||||
|
CPubKey pubkeyRec;
|
||||||
|
if (!pubkeyRec.RecoverCompact(ss.GetHash(), vchSig))
|
||||||
|
return state.DoS(100, error("CheckTransaction() : RecoverCompact failed for spammsg"));
|
||||||
|
|
||||||
|
if (pubkeyRec.GetID() != pubkey.GetID())
|
||||||
|
return state.DoS(100, error("CheckTransaction() : spam signature verification failed"));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tx.userName.empty())
|
if (tx.userName.empty())
|
||||||
return state.DoS(10, error("CheckTransaction() : username empty"));
|
return state.DoS(10, error("CheckTransaction() : username empty"));
|
||||||
@ -1713,11 +1748,10 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
|
|||||||
if( pblock->vtx[0].IsSpamMessage() ) {
|
if( pblock->vtx[0].IsSpamMessage() ) {
|
||||||
string msg = pblock->vtx[0].message.ExtractPushDataString(0);
|
string msg = pblock->vtx[0].message.ExtractPushDataString(0);
|
||||||
string user = pblock->vtx[0].userName.ExtractPushDataString(0);
|
string user = pblock->vtx[0].userName.ExtractPushDataString(0);
|
||||||
// [MF] FIXME: validate user properly
|
|
||||||
if( msg.length() <= 140 ) {
|
// SpamMessage was already validated in CheckBlock => CheckTransation
|
||||||
printf("ProcessBlock: msg='%s' user='%s'\n", msg.c_str(), user.c_str());
|
printf("ProcessBlock: msg='%s' user='%s'\n", msg.c_str(), user.c_str());
|
||||||
receivedSpamMessage(msg, user);
|
receivedSpamMessage(msg, user);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3492,7 +3526,7 @@ static bool CreateSpamMsgTx(CTransaction &txNew, std::vector<unsigned char> &sal
|
|||||||
std::string strUsername = strSpamUser;
|
std::string strUsername = strSpamUser;
|
||||||
|
|
||||||
CKeyID keyID;
|
CKeyID keyID;
|
||||||
if( !pwalletMain->GetKeyIdFromUsername(strSpamUser, keyID) ) {
|
if( strSpamUser != "nobody" && !pwalletMain->GetKeyIdFromUsername(strSpamUser, keyID) ) {
|
||||||
if( pwalletMain->vchDefaultKey.IsValid() ) {
|
if( pwalletMain->vchDefaultKey.IsValid() ) {
|
||||||
keyID = pwalletMain->vchDefaultKey.GetID();
|
keyID = pwalletMain->vchDefaultKey.GetID();
|
||||||
strUsername = pwalletMain->mapKeyMetadata[keyID].username;
|
strUsername = pwalletMain->mapKeyMetadata[keyID].username;
|
||||||
@ -3534,6 +3568,10 @@ static bool CreateSpamMsgTx(CTransaction &txNew, std::vector<unsigned char> &sal
|
|||||||
txNew.pubKey.clear(); // pubKey will be updated to include extranonce
|
txNew.pubKey.clear(); // pubKey will be updated to include extranonce
|
||||||
txNew.nNonce = 0; // no update needed for spamMessage's nonce.
|
txNew.nNonce = 0; // no update needed for spamMessage's nonce.
|
||||||
|
|
||||||
|
CValidationState state;
|
||||||
|
bool ret = CheckTransaction(txNew, state);
|
||||||
|
printf("CheckTransaction returned %d\n", ret );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user