I have a simple encryption module that is used to "encrypt" a text file because it contains some passwords. I only need to encrypt it because I need those passwords in my program (they are used to send an automated bug-report email), but I don't want the end-user to be able to see them.

My "encryption" function is VERY simple and straightforward: it replaces each character in the file with a two-character sequence (either two numbers, two letters, or a number and a letter - these are mapped using a dictionary). The "decryption" function simply reverses the dictionary ({v: k for k, v in _encrypt_key.items()}), then reads the file two-characters at a time and replaces each pair with the corresponding letter. All of this works fine. The file just looks like a bunch of random numbers and letters, so it can't be "read" without the decryption algorithm by any normal end-user.

I used Cython to convert my encryption module (which is a basic Python, .py file), to a .pyd file, so the module itself cannot be read by a normal text-editor.

The problem occurs if the end-user has any Python experience.

For example, it is a very basic task to open the Python console, import the module, open the text file, and decrypt it using the module's "decrypt" function. To prevent this, I used the __main__ module:

import __main__ as main
if hasattr(main, '__file__'):
    # define functions here

Now, it cannot be used interactively in a Python console, because the functions simply won't be defined if it is not being imported from an actual Python program.

To "secure" the key, I made the encryption key local to both functions (both the "encrypt" and "decrypt" functions have a copy of a different variable with the same data). Thus, the user cannot view the key directly.

Finally, I made sure that only certain modules can import it:

import __main__ as main
if hasattr(main, '__file__'):
    path = os.path.basename(main.__file__)
    if path in # tuple of specific files:
        # define functions here

The only loophole I can think of is if the main program itself is edited - other than the encryption module (which is packaged as a .pyd, so I'm not considering it as "open-source"), everything is open-source. If the end-user knows any Python, (s)he can simply open the main program and add a single line, which would show the passwords: print(EXTRA_DATA).

I thought of one way to prevent this:

from __future__ import print_function
print = lambda *args: None # prevent any printing, since my program itself doesn't require it

Of course, the user could always remove this, so it doesn't really fix it.

So, my overall questions are: Can I make this any more secure (make the data and module inaccessible by end-users), and can I prevent any way to print variables in my main program? I want to keep it as open-source if possible.


Manual attack

First of all, your encryption scheme is very weak and easily exploitable. Given a few hundred characters of ciphertext, even a novice cryptanalyst can crack this cipher in less than 30 minutes with only pen and paper. I recommend you stick to industrial-strength ciphers.

Security by obscurity

The obfuscations you are talking about (making a .pyd file and so on) will do little if anything to stop a serious attacker. The closest analogy I can think of is putting your door mat over the key, instead of just leaving the key in plain sight outside your door. It doesn't work very well. Any true encryption scheme needs to adhere to Kerchhoff's Principle, which states that a cryptosystem must be secure even if all parts of it (apart from the encryption key) are known by the attacker.

Wrong approach

In other words, you are approaching the problem from the wrong angle. For example, obfuscating the files won't help, because if an attacker has access to the computer the program is run on, he/she can access the memory directly to view the cleartext and/or key. Even worse, the attacker may even have a keylogger running. You need to design an algorithm that is so secure that having a completely open-source program isn't a problem. That is exactly what the people behind e.g. GPG have done. However, securing such a program against a malicious user isn't practically possible.

The problem is that cryptography is really, really hard. Some of the brightest people on the planet are continuously working to create new, unbreakable ciphers -- and still those ciphers are often broken.

What to do instead

I recommend reading about common cryptography principles and theory, and how basic ciphers are often broken. Don't bother with securing your program against a user - instead presume the program is running on a secure computer and make the ciphertext as secure as possible instead. Instead, write a cipher that is resistant to common techniques like frequency analysis and similar lexical attacks.

Finally, if you want easy and completely uncrackable encryption, I recommend looking into one-time pads. They are cryptographically secure, but they require a key that is at least as long as the plaintext.


To be honest, you algorithms looks secure for 5 year old kids and younger, but smarter kids could guess your encoding scheme and decode text message by counting frequences of the letters/digits. (Looking random is not the same as be random)

It's hard to tell how to make it make it more secure. The sure way is to use very long random key (ideally - as long as the message itself) and, for example, XOR your file with it.

There are a lot of options in between, which is what cryptography is about.

Python have a "disassembler", so having .pyc or .pyd file won't help. It's the secret key you need to hide, not the algorithm.

  • 1
    \$\begingroup\$ While it doesn't remove the underlying problem, Cython will produce C which is then compiled to native code. It's certainly possible to disassemble that as well, but it's nowhere near as easy as disassembling Python bytecode. \$\endgroup\$ – icktoofay Aug 13 '13 at 5:05

Not the answer you're looking for? Browse other questions tagged or ask your own question.