0

I'm trying to understand Public Key encryption so I wrote this little module using PyCryptodome and the RSA/PKCS1_OAEP module on Python 3 to help me along. However, I keep getting an error:

NameError: name 'aesenc' is not defined

This is a two part question:

  1. In standalone code (outside a class) the arg = default_val code will work, but I'm pretty sure this code will throw an error (assuming I fix question #2). I also know I can't use self.default_val as that needs an object to be created first. How do I assign a default value (in this case, the private/public key of the object?)

  2. With regard to the error message, a vgrep reveals that the suite has been declared before its been called but I still get the NameError. Can someone please take a look and let me know what I'm doing wrong?

Modules: (Breaking into parts as SO keeps jumbling the code)

from passlib.context import CryptContext
from Crypto.Cipher import AES, PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto import Random
from Crypto.Random import get_random_bytes

The Class:

class statEnc:
    pubcipher = None
    privcipher = None
    pubkeystr = None
    privkeystr = None
    sessionkey = None

    def __init__(self, pubkeystr = None, privkeystr = None, sessionkey = None):
        self.pubkeystr = pubkeystr
        self.privkeystr = privkeystr
        self.sessionkey = sessionkey
        if pubkeystr == None or privkeystr == None:  #if blank, generate keys
            self.random_generator = Random.new().read
            self.keys = RSA.generate(1024, self.random_generator)
            self.pubkey = self.keys.publickey()
            self.pubkeystr = self.pubkey.exportKey(format='PEM',
                                            passphrase=None,
                                            pkcs=1)
            self.pubcipher = PKCS1_OAEP.new(self.pubkey)
            self.privcipher = PKCS1_OAEP.new(self.keys)
            self.privkeystr = self.keys.exportKey(format='PEM',
                                                passphrase=None,
                                                pkcs=1)
            self.privkey = self.keys.exportKey()
        else:  #import the keys
            self.pubkey = RSA.importKey(pubkeystr)
            self.pubcipher = PKCS1_OAEP.new(pubkey)
            self.privkey = RSA.importKey(privkeystr)
            self.pubcipher = PKCS1_OAEP.new(privkey)
            if sessionkey == None:
                sessionkey = get_random_bytes(16)
            else:
                self.sessionkey = sessionkey

    def encrypt_val(self, session_key, cipher = pubcipher):
        # a little ditty to hep encrypt the AES session key
        try:
            session_key = session_key.encode('utf8')
        except:
            pass
        ciphertext = cipher.encrypt(session_key)
        return ciphertext


    def decrypt_val(self, ciphertext, cipher = privcipher):
        # a little ditty to hep decrypt the AES session key
        session_key = cipher.decrypt(ciphertext)
        try:
            session_key = session_key.decode('utf8')
        except:
            pass
        return session_key

    def aesenc(self, data, *args):
        #encrypt the payload using AES
        key = ''
        if args:
            if 'str' in str(type(args[0])):
                try:
                    key = int(args[0])
                except:
                    key = get_random_bytes(16)
        else:
            key = get_random_bytes(16)
        try:
            data = data.encode('utf8')
        except:
            pass
        cipher = AES.new(key, AES.MODE_EAX)
        ciphertext, tag = cipher.encrypt_and_digest(data)
        aesencdict = {
        'ciphertext' : ciphertext,
        'tag' : tag,
        'nonce' : cipher.nonce ,
        'key' : key
        }
        return(aesencdict)

    def aesdec(self, aesdict):
        #decrypt the AES encrypted payload
        cipher = AES.new(aesdict['key'], AES.MODE_EAX, aesdict['nonce'])
        data = cipher.decrypt_and_verify(aesdict['ciphertext'], aesdict['tag'])
        try:
            data = data.decode('utf8')
        except:
            pass
        return data

    def end2enc(self, val, cipher = pubcipher):
        # a master function to first encrypt the payload
        val = str(val)
        encval = aesenc(val)
        # and then PK encrypt the key
        encval['key'] = encrypt_val(encval['key'], cipher)
        return encval

    def end2dec(self, encval, cipher = privcipher):
        encval['key'] = decrypt_val(encval['key'], cipher)
        outval = aesdec(encval['aesdict'], encval['key'])
        return outval

Test function and main:

def test():
    val = { 'test' : "hello"}
    keypair = statEnc()
    print(str(type(keypair)))
    encval = keypair.end2enc(val, keypair.pubcipher)
    outval = keypair.end2dec(encval, keypair.privcipher)
    print(val, outval)
    if val == eval(outval):
        return(val)
    else:
        return False

if __name__ == '__main__':
    test()

[UPDATE] The Traceback is as follows:

[guha@katana stat]$ python statenc.py 
<class '__main__.statEnc'>
Traceback (most recent call last):
  File "statenc.py", line 124, in <module>
    test()
  File "statenc.py", line 115, in test
    encval = keypair.end2enc(val, keypair.pubcipher)
  File "statenc.py", line 100, in end2enc
    encval = aesenc(val)
NameError: name 'aesenc' is not defined
kilokahn
  • 1,136
  • 2
  • 18
  • 38

1 Answers1

0

Slept over my question and woke up with a fresh mind, and voila! the answer presented itself.

The answer to the second question is as follows: 2. putting a simple 'self.' solves the problem - i was calling 'aesenc(params)' instead of 'self.aesenc(params)'. Stupid of me, really.

Question 1 is answered in this SO question.

kilokahn
  • 1,136
  • 2
  • 18
  • 38