Teaspeak-Server/client/src/MultithreadedIdentity.cpp

189 lines
7.1 KiB
C++

//
// Created by wolverindev on 14.10.17.
//
#include <iostream>
#include <openssl/sha.h>
#include <ThreadPool/Thread.h>
#include <vector>
#include <ThreadPool/Mutex.h>
#include <zconf.h>
#include "misc/base64.h"
#include "Identity.h"
#define ECC_TYPE_INDEX 5
#define USE_OPENSSL_SHA1
using namespace std::chrono;
using namespace std;
namespace ts {
inline int calculateSecutityLevel(uint8_t* hashBuffer, uint8_t* bufferToHash, int length){
register int zeroBits = 0;
register int bit;
register int i;
SHA1(bufferToHash, length, hashBuffer);
//Leading zero bits
for(i = 0; i < SHA_DIGEST_LENGTH; i++)
if(hashBuffer[i] == 0) zeroBits += 8;
else break;
if(i < SHA_DIGEST_LENGTH)
for(bit = 0; bit < 8; bit++)
if((hashBuffer[i] & (1 << bit)) == 0) zeroBits++;
else break;
return zeroBits;
}
inline void increaseNumBuffer(char* buffer, int numOffset, int* length){
int index = *length - 1;
while(true){
if(buffer[index] == '9'){
if(index - 1 < numOffset) {
buffer[index] = '1';
buffer[*length] = '0';
*length += 1;
return;
}
buffer[index--] = '0';
} else {
buffer[index] += 1;
return;
}
}
}
#define MaxUlongString 20
bool Identity::improveSecurityLevelMultithreaded(int target, int nthread, size_t nblockSize, size_t baseOffset, bool verbose) {
if(this->getSecurityLevel() >= target)
return false;
vector<threads::Thread*> threads;
auto publicKey = this->publicKey();
size_t currentBlockIndex = max(max(this->lastCheckedOffset, this->keyOffset), baseOffset);
threads::Mutex blockIndexLock;
auto activeDigging = new bool(true);
threads::Thread* thread;
for(int threadId = 0; threadId < nthread; threadId++){
thread = new threads::Thread([&](){
size_t offset = 0;
size_t endOffset = 0;
size_t bestOffset = 0;
char shaHashBuffer[SHA_DIGEST_LENGTH];
char hashBuffer[publicKey.length() + MaxUlongString];
memcpy(hashBuffer, publicKey.data(), publicKey.length());
#ifndef SLOW
//Setup some stuff
size_t pubKeyLength = publicKey.length();
#endif
while(*activeDigging){
//Get next range
blockIndexLock.lock();
offset = currentBlockIndex;
endOffset = currentBlockIndex + nblockSize;
currentBlockIndex += nblockSize;
blockIndexLock.unlock();
int bestLevel = this->getSecurityLevel(hashBuffer, publicKey.length(), this->keyOffset);
#ifdef SLOW
while(offset < endOffset){
int currentLevel = getSecurityLevel(hashBuffer, publicKey.length(), offset);
if(currentLevel >= best){
bestOffset = offset;
best = currentLevel;
}
offset++;
}
blockIndexLock.lock();
if(best > this->getSecurityLevel()){
if(verbose) cout << "Improved -> " << best << "/" << target << endl;
this->lastCheckedOffset = bestOffset;
this->keyOffset = bestOffset;
cout << "Got level: " << best << endl;
if(best >= target){
cout << "Done!" << endl;
*activeDigging = false;
}
}
blockIndexLock.unlock();
if(verbose) cout << "round done: highest -> " << best << endl;
#else
string strStartOffset = to_string(offset);
ssize_t roundsLeft = nblockSize;
auto hashBufferLength = static_cast<int>(publicKey.length() + strStartOffset.length());
memcpy(&hashBuffer[pubKeyLength], strStartOffset.c_str(), strStartOffset.length());
while(roundsLeft-- >= 0){
auto level = calculateSecutityLevel(reinterpret_cast<uint8_t *>(shaHashBuffer), reinterpret_cast<uint8_t *>(hashBuffer), hashBufferLength);
if(level > bestLevel){
{
threads::MutexLock l(blockIndexLock);
auto strOffset = string(&hashBuffer[pubKeyLength], hashBufferLength - pubKeyLength);
bestOffset = stoull(strOffset);
auto got = this->getSecurityLevel();
if(got >= level) {
cout << "Already got bedder level! (" << got << ")" << endl;
bestLevel = got;
continue;
}
if(verbose) cout << "Improved -> " << level << "/" << target << " [" << strOffset << "]" << endl;
this->lastCheckedOffset = bestOffset;
this->keyOffset = bestOffset;
bestLevel = level;
if(bestLevel >= target){
cout << "Done! (" << bestLevel << ")" << endl;
*activeDigging = false;
}
}
}
increaseNumBuffer(hashBuffer, pubKeyLength + 1, &hashBufferLength);
}
#endif
}
});
thread->name("IdentityHashDigger #" + to_string(threadId));
threads.push_back(thread);
}
if(verbose){
thread = new threads::Thread([&](){
auto lastIndex = currentBlockIndex;
while(*activeDigging){
for(int count = 0; count < 1000 && *activeDigging; count++)
usleep(1000);
blockIndexLock.lock();
cout << "Current level = " << this->getSecurityLevel() << " at " << this->keyOffset << endl;
cout << "Current offset index: " << currentBlockIndex << " block size: " << nblockSize << endl;
cout << "speed: " << (currentBlockIndex - lastIndex) / 1000 / 1000.f << " Mio. attemps/sec" << endl;
lastIndex = currentBlockIndex;
blockIndexLock.unlock();
}
});
thread->name("Status printer");
threads.push_back(thread);
}
for(auto elm : threads){
if(elm->state() == threads::ThreadState::RUNNING)
elm->join();
delete elm;
}
return true;
}
}