Revisiting obfuscating text in scripts

A little while ago I covered a technique that could be used to obfuscate sensitive text in scripts used to manage macOS; a recent issue with this particular technique left me needing to re-write this in python.

What you’ll need:

Installing pycrypto using pip requires Xcode tools to be installed, which for some environments is not possible or desired, so you will need to work out a means of getting the pycrypto module onto target machines. In my instance, I used logGen to take a snapshot pre/post installation and built a package for distributing to clients.

To create a key for encrypting/decrypting, a file is created containing 32bytes of random data. An example of how this is generated is some simple python code:

#!/usr/bin/python

import os
import sys

# Create a random 32 byte keyfile for use with aescrypto.py


def createKey(output_file):
    with open(output_file, 'wb') as output:
        output.write(os.urandom(32))


if len(sys.argv) is 2:
    createKey(sys.argv[1])
else:
    print 'Usage: {} '.format(sys.argv[0])
    sys.exit(1)

Next comes creating the encrypted text; turning that wonderful coder/scripter resource, Stack Overflow, in particular a discussion on how to encrypt text using AES256. Code has been borrowed heavily from this comment in particular, I have a deep appreciation for people willing to share their knowledge with others.

A sample script available here covers how this can be used to encrypt/decrypt plain text. This file outputs the encrypted text into a plist file simply because in my use case I want the data in a machine readable format. Any other output method can be used.

Fundamentally, the key is read in, and a random initialisation vector is generated when the encryptText() function is called, this ensures that each time a string is encrypted, it doesn’t result in the same cipher text. It does mean that the initialisation vector needs to be supplied with the cipher text in order to decrypt it.

The decryptText() reads the same key as used to encrypt, and the correct initialisation vector, then passes the cipher text back through the aes.decrypt() method to get the plain text.

I don’t claim to know the complex ins and outs of which encryption methods work the best, so I don’t plan on using this technique for mission critical/sensitive data, this is simply a means to ensuring simple text strings that don’t need to be trivially accessible are obfuscated from prying eyes, especially where it is fairly trivial to expand a package file out, or trawl through web directories that aren’t appropriately configured.

As this isn’t true asymmetric encryption (using a private/public key pair), using this technique does have some risks.

  • The key in this technique is the same key for encrypting and decrypting, so extra care needs to be taken to ensure it isn’t easily accessible
  • If storing the key on a target machine, store it in an area of the file system that only privileged users have access to, etc.
  • If deploying the key in a package, limit access to the location the package is stored to ensure only authorised devices/users can access it

It’s also advisable to assess whether this technique is appropriate for your needs and the scenario in which plain text must be obfuscated, and potentially any legislation governing how certain data must be protect. My particular use case doesn’t involve sensitive scenarios, and is sufficient enough to make it more complicated for any naughty little prying eyes to see what is going on.