from Crypto.PublicKey import RSA
from Crypto.Hash import SHA256
from Crypto.Signature import pkcs1_15
import json
from base64 import b64encode, b64decode
from pprint import pprint


class ITKoin:
    def __init__(self):
        self.pending_transactions = []
        self.unspent_transactions = []
        self.sender_inputs = []
        self.chain = []

    @staticmethod
    def generate_rsa_key(filename):
        rsakey = RSA.generate(2048)  # generálj 2048 bites RSA kulcsot
        rsapublickey = rsakey.publickey()
        print(rsakey)
        pprint(rsakey)
        print(vars(rsakey))
        pprint(vars(rsakey))
        pprint(vars(rsakey))
        pprint(rsapublickey)
        pprint(vars(rsapublickey))
        PEMrsakey = rsakey.export_key(format="PEM")# PEM formátumra alakítsd az RSA kulcsot
        pprint(PEMrsakey)
        PEMrsapublickey = rsapublickey.export_key(format="PEM") # PEM formátumra alakítsd a kulcs publikus részét
        pprint(PEMrsapublickey)
        privatekeyfilename = filename + 'priv.pem'
        f = open(privatekeyfilename, 'wb')
        f.write(PEMrsakey)
        f.close()
        publickeyfilename = filename + 'pub.pem'
        f = open(publickeyfilename, 'wb')
        f.write(PEMrsapublickey)
        f.close()
        return

    def load_key(self, filename):
        privatekeyfilename = filename + 'priv.pem'
        privatekeyfileobject = open(privatekeyfilename, 'r')
        privatekeyfilecontent = privatekeyfileobject.read()
        pprint(privatekeyfilecontent)
        rsakey = RSA.import_key(privatekeyfilecontent)
        self.rsakey = rsakey
        pprint(vars(self.rsakey))
        rsapublickey = rsakey.publickey()
        self.rsapublickey = rsapublickey
        pprint(vars(self.rsapublickey))
        return

    def load_public_key(self, filename):
        publickeyfilename = filename + 'pub.pem'
        publickeyfileobject = open(publickeyfilename, 'r')
        publickeyfilecontent = publickeyfileobject.read()
        pprint(publickeyfilecontent)
        rsakey = RSA.import_key(publickeyfilecontent)
        rsapublickey = rsakey.publickey()
        self.rsapublickey = rsapublickey
        pprint(vars(self.rsapublickey))
        return

    @staticmethod
    def create_hashobject(data):
        stringdump = json.dumps(data) 
        binarydump = stringdump.encode()
        hashobject = SHA256.new(data=binarydump) 
        
        hashhexvalue = hashobject.hexdigest() 
        print(hashhexvalue)
        return hashobject


    def create_signature(self, data):
        signatureobject = pkcs1_15.new(self.rsakey)
        hashobject = ITKoin.create_hashobject(data)
        signaturevalue = signatureobject.sign(hashobject)
        print(signaturevalue)
        b64signaturevalue = b64encode(signaturevalue)
        print(b64signaturevalue)
        print(b64signaturevalue.decode())
        return b64signaturevalue.decode()


    def verify_signature(self, data, b64signaturevalue, rsapublickey):
        verifyobject = pkcs1_15.new(rsapublickey) 
        hashobject = ITKoin.create_hashobject(data) 
        signaturevalue = b64decode(b64signaturevalue)
        try:
            signatureerror = verifyobject.verify(hashobject, signaturevalue)
            validsignature = True
        except (ValueError, TypeError):
            validsignature = False
        return validsignature

csabaKoin = ITKoin()
print("######## Generate Keys #########")
ITKoin.generate_rsa_key("csaba")
print("######## Load Keys #########")
csabaKoin.load_key("csaba")
csabaKoin.load_public_key("csaba")

data = 'hutyutyu'
print("######## Create Signature #########")
signature = csabaKoin.create_signature(data)
#signature.encode('ascii')
signature_input = json.dumps(signature, sort_keys=True).encode()
print("######## Validate Signature #########")
valid = csabaKoin.verify_signature(data, signature_input, RSA.import_key(open("csabapub.pem").read()).publickey())
if (valid):
    print("valid sign")
else:
    print("not valid sign")
