Assistance encoding/decoding a message with DES - Python

Viewed 48

I am trying to create some code in Python to encrypt/decrypt a message using DES.

I seem to be getting the following error, and can't work out why.

'utf-8' codec can't decode byte 0xc1 in position 1: invalid start byte'

Code is as follows:

from Crypto.Cipher import DES

key = 'abcdefgh'

def encrypt(msg):
    cipher = DES.new(key.encode('utf-8'), DES.MODE_EAX)
    ciphertext = cipher.encrypt(msg.encode('utf-8'))
    return ciphertext

def decrypt(ciphertext):
    cipher = DES.new(key.encode('utf-8'), DES.MODE_EAX)
    plaintext = cipher.decrypt(ciphertext)
    return plaintext.decode('utf-8')
    

ciphertext = encrypt('Python')
plaintext = decrypt(ciphertext)


print(f'Cipher text: {ciphertext}')

print(f'Plain text: {plaintext}')
1 Answers

I cannot seem to find out the problem with your code, but may I suggest another way to do it, using the cryptography module?

from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from base64 import urlsafe_b64encode
from socket import getfqdn
from os.path import expanduser

print(expanduser("~")) # Get current users home directory, works for linux too, example: C:\Users\username
print(getfqdn()) # Get fully qualified domain name, works for linux too, example: user.company.com

KDF = PBKDF2HMAC(algorithm=hashes.SHA512(),length=32,salt=urlsafe_b64encode(expanduser("~").encode()),iterations=400000,)
FERNET_KEY = urlsafe_b64encode(KDF.derive(getfqdn().encode()))

def encryptString(string: str) -> str:
    cipher: Fernet = Fernet(FERNET_KEY)
    return(cipher.encrypt(string.encode()).decode())

def decryptString(string: str) -> str:
    cipher: Fernet = Fernet(FERNET_KEY)
    return(cipher.decrypt(string.encode()).decode())

ciphertext = encryptString("Python")
plaintext = decryptString(ciphertext)

print(f'Cipher text: {ciphertext}')
print(f'Plain text: {plaintext}')

Result:

Cipher text: gAAAAABjK_6v7Wg...truncated...Q8k8HoVA==
Plain text: Python

I'm using the expanduser as the salt to generate a key with 400.000 iterations. Then the actual key is being made by using the derive function and getfqdn as the password.

FYI: I do not take any responsibility for any lost data or wrong use. This is purely a demonstration of how to use the selected modules for encrypting strings.

PBKDF2HMAC documentation

Cryptography Fernet

Derive

If you are using Windows, you could take advantage of the build-in Data Protection API (DPAPI). You must install pywin32 by using pip install pywin32.

The code:

from win32crypt import CryptProtectData, CryptUnprotectData

def encryptString(string: str) -> str:
    return(CryptProtectData(string.encode()))

def decryptString(string: str) -> str:
    return(CryptUnprotectData(string)[1].decode())

ciphertext = encryptString("Python")
plaintext = decryptString(ciphertext)

print(f'Cipher text: {ciphertext}')
print(f'Plain text: {plaintext}')

Result:

Cipher text: b'\x01\x00\x00\x00\xd0...truncated ...\xeei\x1bI\xd9\x14\x00\x00\x00*\xe0\xc61P\xd0 \x1f3\n\xfb\xdb\x1d\x7fC7\nwL_'
Plain text: Python
Related