Legrandin / pycryptodome

A self-contained cryptographic library for Python
https://www.pycryptodome.org
Other
2.84k stars 503 forks source link

AES Incorrect Password Error Not Raising #393

Closed KeerthiNaathan closed 4 years ago

KeerthiNaathan commented 4 years ago

in AES Mode - CFB, OFB, CTR when I enter the password it is not raising the error, instead, it gives random data.

I check the document, examples and tried , it not raising errors

Source-code: `class CTR: def encrypt(self, data, password): cipher = AES.new(password, AES.MODE_CTR) e_data = cipher.encrypt(data) return { "encrypted_data": e_data, "nonce": cipher.nonce, }

def decrypt(self, data, password):
    try:
        cipher = AES.new(password, AES.MODE_CTR, nonce=data['nonce'])
        ue_data = cipher.decrypt(data['encrypted_data'])
        return ue_data
    except (ValueError, KeyError) as e:
        print(e)
        return False

` Results: {'encryption': {'encrypted_data': b'\xbc\xca~\xe0\x81\x85\xf9R\xc7\xfcA?', 'nonce': b'[\x1c\x82\xc8J\xc8dn'}, 'mode': 'CTR'} output: b'\xf8\x94\x15,0q\xf0\x1e\xb1A\x0c\x1a'

texadactyl commented 4 years ago

It sounds like you really want to use the PBKDF2 functions (password-based cryptography). That's what I use in this type of application. See https://www.pycryptodome.org/en/latest/src/protocol/kdf.html?highlight=password

When I pass in a key instead of a password, your modified code works as expected (attached essai.py). Of course, decryption with a different key or nonce does not throw an exception but simply returns garbage cleartext.

essai.py.txt

KeerthiNaathan commented 4 years ago

is there any way to solve this issue?

texadactyl commented 4 years ago

@KeerthiNaathan

Did you read my earlier message and the attachment (essai.py.txt)?

Use the PyCryptodome PBKDF2 functions (password-based cryptography) instead of what you are currently doing. PyCryptodome is behaving as expected.

If you agree with me, please close this issue. If you do not, please explain what I missed/misunderstood.

KeerthiNaathan commented 4 years ago

I used PBKDF2 Functions to Generate Harsh, Still the Issue is there.

def encrypt(self, mode, data, password):
        # a customed based KDF 
        password_h = self.harsh_obj.generate(password, True)
        return {
            "password_org": password, # orginal password
            "password_h": password_h, # password harshed with PBKDF2 (harsh mode = SHA3-256)
            "encryption": self.AES_MODE[mode].encrypt(data, password_h), # Encrypted Data
            "mode": mode # type of AES Mode
        }

    def decrypt(self, data, password):
        password_h = self.harsh_obj.generate(password, True) # generating the harsh password
        return self.AES_MODE[data['mode']].decrypt(data['encryption'], password_h)

if __name__ == '__main__':
 e = AESclass()
 e_data = e.encrypt('CTR', b'Soviet Union', 'Stalin')
 print(e_data)
 # orginal password
 p_data = e.decrypt(e_data, 'Stalin')
 print('orginal_output:', p_data)
 # wrong password
 p_data = e.decrypt(e_data, 'Russia1')
 print('wrong_output:', p_data)

the self.harsh_obj using PBKDF2 Function. to generate the Harsh as u mentioned above.

the Output is i got is: {'password_org': 'Stalin', 'password_h': b'7511d40bb6fdb3e55a3a8082150796b6', 'encryption': {'encrypted_data': b'J3iLvK3tBo8JliDt', 'nonce': b'FePovVQ7rNI='}, 'mode': 'CTR'} orginal_output: b'Soviet Union' wrong_output: b'2\x13\xa3\xc5kT\xf2o\xd9\xf8*S'

As per the Documentation: https://www.pycryptodome.org/en/latest/src/cipher/classic.html#ctr-mode . If the nonce / password wrong it must raise ValueError , KeyError. instead it throws some garbage values.

texadactyl commented 4 years ago

Please attach (drag and drop) the source code file of your test program to a new message here. I'll give it a go as soon as I see it.

Agreed with your comment about ValueError in the documentation. Ditto for KeyError.

"harsh" >>> "hash" right? (=:

KeerthiNaathan commented 4 years ago

PasswordGenerator.py - Generate Hash using HashGenerator, and compression of file, and other stuff

AESModes.py - AES Modes and Main AES Class. Btw: Thanks for spelling mistake correction , i need to Change the Name from harsh to hash. 👍

If any doubt ask me. because there is no documentation. (sry for that)

File Attachments: AESModes.py.txt PasswordGenerator.py.txt

texadactyl commented 4 years ago

Got the same result as you:

Encrypt output with password 'Stalin' on b'Soviet Union' {'password_org': 'Stalin', 'password_h': b'a0f8d8030ca52073d1d1355ffd8ff220', 'encryption': {'encrypted_data': b'kauZBLxZjUWUqw03', 'nonce': b'vqUOpKmBDCs='}, 'mode': 'CTR'}
Decrypt output with password "Stalin": b'Soviet Union'
Decrypt output with password "Russia1": b'<\xa4\xaf\x03\x83\xa8\x10;\xcfmi('

Modified your code for whatever it is worth with a few annotations and did the respelling. AESModes.py.txt PasswordGenerator.py.txt

texadactyl commented 4 years ago

Bottom line (I should have said this before):

(1) It is not the intent in pycryptodrome (or its predecessor pycrypto) that just a wrong password-generated key can cause a ValueError or a KeyError. Those are lower-level errors usually caused by the ciphertext containing invalid pad characters or invalid counters. In short, the ciphertext is garbage or had been tampered with. Providing the wrong password and therefore making a valid but incorrect key may not be sufficient to generate an exception of some kind. See https://github.com/Legrandin/pycryptodome/blob/master/lib/Crypto/Cipher/AES.py ValueError circumstances:

(2) In commercial production, a banking system ATM PIN is used like a password. A common ATM function is Verify PIN. The customer's PIN is permanently stored in the database (encrypted or hashed or both in some form). The incoming encrypted PIN block from the external transaction originator (E.g. ATM) plus the database ciphertext are provided to the authorization system's secure cryptographic device along with the 2 keys: database key and the key shared with the transaction originator. The device decrypts both ciphertext blocks and returns simply "match" or "not matched" based on a comparison of the 2 cleartext blocks. In a way, pycryptodome user programs doing password based cryptography are like this cryptographic device.

I hope that this makes sense. I've been doing cryptography for a long time and might be making incorrect assumptions about your experience level.

I have a project called pycloaking under my github space which you are welcome to. This utility is used to disguise files for transporting data say on a thumb drive or attaching to an email. The key to cloak or uncloak is based on a password. The cloaked file appears to a casual browser as a graphic TIFF file.

KeerthiNaathan commented 4 years ago

Ok Thanks , I am Closing this Issue btw @texadactyl Thanks for your help and I will talk to you in Email. also i will also check your pycloaking also 👍