#include "rsa.cpp"
#include "Utils.cpp"
#include <chrono>


SC_MODULE(measuringSubject)   
{
    bigint e;
    bigint d;
    bigint n;

   /* simple function to determine average power consumption per Hamming weight
    * in theory, there should be a correlation between power consumption and Hamming weight of the decrypted message
    */
    void subject_main(){
        bigint keySet[3];
        int time = 0;
        /* as long as n and d are not of the same length, the generation is restarted. 
         *(prerequistie for a ZEMD attack)
         */
        do{
            time = std::chrono::system_clock::now().time_since_epoch().count();
            default_random_engine generator (time);
            uniform_real_distribution<double> dist (0, 99999999999);
            int seed = dist(generator);
            rsa_generate_keys(seed, keySet);
        }while(Utils::unsignificantBitCount(keySet[0].to_int(),NBITS) != Utils::unsignificantBitCount(keySet[2].to_int(),NBITS));
        
        
        this->d = keySet[0];
        this->e = keySet[1];
        this->n = keySet[2];
        int omittedbits=Utils::unsignificantBitCount(n.to_int(), NBITS);
        long long results[32][2] = {0};
        int hamWeight = 0;
        for(int i=0; i< 1000; i++) {
            char msg[NBITS-omittedbits-1]= {0};
            rand_bitstr(msg, NBITS-omittedbits-1);
            bigint msgAsBigint=msg;
            hamWeight = Utils::hammingWeight(decipher(0,true, msg, d, n).to_int());
            results[hamWeight][0] += RessourceHandler::getInstance()->traceSum(RessourceHandler::getInstance()->powerTraces[RessourceHandler::getInstance()->powerTraces.size()-1]);
            results[hamWeight][1]++;
        }
        for(int i = 0; i < 32; i++){
            cout << "Hamming Weight = " << i << ", Results: " << results[i][1] << ", Average Power Consumption: ";
            if(results[i][1] > 0){
                cout << results[i][0]/results[i][1] << endl;
            }else{
                cout << "0" << endl;
            }
        }
    }

    SC_CTOR(measuringSubject)  
    {
        SC_THREAD(subject_main);

    }



};

