Skip to main content

Encrypt modules to pass private code through a repository.

Project description

Overview

passcode provides a simple way to encrypt python modules on a development machine, pass the protected code through a public repository, pull the protected code into production, automatically decrypt the protected code at runtime on the production machine, and reference the protected code from other components at runtime. Do all of that with just two lines of code!

passcode makes it possible to include secrets (such as a login password or some proprietary code) directly in your code without others being able to read it in a push-to-deploy repository.

passcode is written in pure Python 3.X, has no dependencies, and requires two lines of code to implement. You can easily inspect and verify the operation of passcode to see what it does.

Install

Installation

  • Install with pip:

    pip install passcode
    
  • or clone the repository into your own project from GitHub:

    git clone https://github.com/KenYounge/passcode.git
    

Usage

import passcode
passcode.execute('secrets', locals(), '~/mypasscode.key', '/private/mypasscode.key')

Instructions

  1. Install passcode.
pip install passcode
  1. Create a passphrase.

    • First option is to generate an ASCII passphrase manually and to thebn save it into a file, such as passcode.key

    • Second option is to leave the key_dev parameter blank, and passcode will prompt you for a passcode.

    • You can use different keys for different code modules, thereby enforcing differential access-control.

  2. Import passcode and private modules:

    • The following code uses the passcode.update() function to encrypt, decrypt, and import code modules.
    • The original source code is imported into local scope and you can reference variables and functions as normal.
import passcode 
passcode.execute('secrets1', locals(), '~/passphrase1.key', '/private/passphrase1.key')
passcode.execute('secrets1', locals(), '~/passphrase2.key', '/private/passphrase2.key')
  1. Exclude the original plaintext files (that you want to secure) from the repository.

    • You do not want the passphrase file(s, or the unencrypted module(s) that you want to protect, to appear in your git repository as plaintext. Therefore do not git add those file(s) to the repository.

    • Alternatively, you can list those files for exclusion in the .gitignore file.

  2. Include only the encrypted versions of the protected modules in the repository: git add *.rc4

  3. Re-run passcode.execute() each time you change a passcode protected module.

    • passcode.execute() will refresh the encrypted copy of a module each time it is executed.

    • Therefore re-run execute() each time you change a protected source fie.

  4. Push your project to the repository.

    • Configure .gitignore to exclude your secret module(s) and your secret password key(s) from the repository.

    • And/or make sure that you do not add those files to the repository in the first place.

  5. Deploy keys independently (and privately) to production.

    • You need to distribute your private keys to production by another, more-protected approach:

      • move the password key(s) to a more secure git repository with limited access by others;

      • install the password key(s) into a protected directory in a Docker Container or a VM Image;

      • manually copy the password key(s) to the production machine.

  6. OPTIONAL: Enable code completion for the development IDE.

    • IDEs will autocomplete and check for some errors when they can reference original code declarations.

    • The IDE cannot do that, however, if it cannot find a normal Python import statement to reference.

    • The following code will enable code completion & inspection on the dev-side IDE.

    • Note that the code will raise an error on a production machine (because the imports will be missing), so you must catch each error (independently) for each import.

try: from private_code import *   
except: pass   

try: from another_module import *   
except: pass  
  1. OPTIONAL: Recover an original source file from an rc4 file.
  • Your original source code is still backed up and protected in the git repository - just not in plain text.

  • You can recover the original source code (*.py) file from an encrypted *.rc4 file if you have the original key.

  • Run passcode.recover() to recover the original, unencrypted file.

Disclaimer

USE THIS CODE AT YOUR OWN RISK. I provide no guarantee about it's security, safety, reliability, or any other potential risk or harm.

Demonstration

See the file demonstration.py for an example of how to use passcode.

Tech notes

The production environment

The purpose of passcode is to protect secrets while in transit through a git repository. It does NOT protect secrets in the production environment. Although you can save passcode keys in an access-protected directory of the production environment (i.e., separate from the running code) that others cannot access, it may be possible for others to access the decryopted code during runtime by re-writing the application to stop, inspect, and dump out the secret code (although they also would have to have permission to change the runtime code in the production environment). This is a limitation of this apporoach. We are open to suggestions from others about ways to strength the last-stage of security with other "bring your own encryption key" steps that could be combined with passcode.

RC4 Encryption

Encryption is implemented with the "alleged" RC4 algorithm. Although RC4 is not as secure as AES, it is simple, it is fast, it is implemented in pure python, and it has no imports. Another advantage of RC4 is that you can easily inspect our code and confirm what it does. A more advanced algorithm would require dependencies and a more complicated installation/distribution. You can implement passcode by doing nothing more than just copying passcode.py into your project.

There is some concern that RC4 is breakable through a 'man-in-the-middle' attack over a very large volume of encrypted traffic. We presume, however, that you will use passcode to encrypt only a handful of python files, and that those files change infrequently. As such, you should not generate the millions (or billions) of examples that are needed for a statistical attack.

Set your own passphrase

Be sure to set your own passphrase in your own password files. In general, it is better to NOT use the file name passcode.key (the default assumed by passcode.update()), but rather generate and name your own file. A random file name for your key would also seem to reduce the chance of mistakenly using a key file from somone else.

Version History

Version 0.1.5 - 2021.02.17

Moved implementation into a __init__.py file so user an import it directly as a directory. Changed naming of the implementation methods. Fixed bug in RC4 which would break on some unicode characters.

Version 0.1.2 - 2021.02.11

Renamed the example files.

Version 0.1.1 - 2021.02.10

Improved the ReadMe.

Version 0.1.0 - 2021.02.09

First distribution to PyPi.

OPEN BUG REPORTS

  • Terminate modules (that you aim to encrypt) with at least one newline character. This helps python to distinguish complete vs. incomplete statements in the code module.

  • There are reports of the python compile() function failing to parse some types of code due to whitespace in it. This is being investigated.

  • There are reports of the our encrypt/decrypt sequence, plus the python compile() function, dropping an apostrophe (i.e., the ' character) - switching to double quotes seemd to fix the problem for some reason in the known case.
    This is being investigated.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

passcode-0.1.6.tar.gz (7.0 kB view details)

Uploaded Source

Built Distribution

passcode-0.1.6-py3-none-any.whl (8.5 kB view details)

Uploaded Python 3

File details

Details for the file passcode-0.1.6.tar.gz.

File metadata

  • Download URL: passcode-0.1.6.tar.gz
  • Upload date:
  • Size: 7.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/4.0.1 pkginfo/1.6.1 requests/2.24.0 requests-toolbelt/0.9.1 tqdm/4.50.2 CPython/3.8.5

File hashes

Hashes for passcode-0.1.6.tar.gz
Algorithm Hash digest
SHA256 445b393d5d257dc12aa61d2175eba06146ce22c95e08d479da8fe01470f0d9a4
MD5 55768ac096eea15515029152a87632ef
BLAKE2b-256 19706f2bf2222f57ad28f21b75400a69e2b81540749207ab615dda9efd1e2015

See more details on using hashes here.

File details

Details for the file passcode-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: passcode-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 8.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/4.0.1 pkginfo/1.6.1 requests/2.24.0 requests-toolbelt/0.9.1 tqdm/4.50.2 CPython/3.8.5

File hashes

Hashes for passcode-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 48126290e9382de3cb48f7e76d8426c299b5f0d17970d67ea27a9f8cd19d30f2
MD5 cbca97618eed280952cfcd945a67c96c
BLAKE2b-256 94903d4f998b77eb66ac8c943e8357e6db6ca9a737dd47904480053d86c3ca0e

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page