Use Encryption for privacy

This notebook outlines some simple examples to show how simple it can be to use encryption techniques to protect privacy.

In general using encryption will help to protect privacy information in two ways:

  • For data at-rest: This includes all privacy information, so called storage objects, that exist on physical media on all forms. E.g. magnetic,optical disk, SSD, etc
  • For data in-transit: When personal data is being transferred systems, or system components, or programs, such as over the network, or internal APIs , or across a service bus. So all data that is 'in-motion'.

But never develop your own encryption algoritmes. We known it is fun, improves learning and makes you an excellent hacker. However the art and barrier to develop a good encryption algortime is very high.

Below some simple python examples, based on proven Python encryption algoritmes.

cryptography

The Cryptography library (https://cryptography.io/) includes both high level recipes and low level interfaces to common cryptographic algorithms such as symmetric ciphers, message digests, and key derivation functions.

Fernet is an implementation of symmetric (also known as “secret key”) authenticated cryptography. Fernet is ideal for encrypting data that easily fits in memory. As a design feature it does not expose unauthenticated bytes.

In [48]:
#Encryption algoritmes works on bytes most of the time. 
string='This is a test string to be encoded'.encode('UTF-8')
print(string)
#decode string:
decoded_string=string.decode('UTF-8')
print(decoded_string)
b'This is a test string to be encoded'
This is a test string to be encoded
In [49]:
from cryptography.fernet import Fernet
key = Fernet.generate_key()
cipher_suite = Fernet(key)
cipher_text = cipher_suite.encrypt(string)
plain_text = cipher_suite.decrypt(cipher_text)
print(cipher_text)
print(plain_text)
print(plain_text.decode('UTF-8'))
b'gAAAAABbAopEIq4jEmbIwQJsw67RB1vOnF4Vhzm0wpEwn5PXdv3KkEemv35RTcAu9LFhaW_wCeFfOYtQSnKo0RJdlAThQaw5NOmdq-cDA_8Wlt1RR1wmOaoBJtlp7Pjf58mDdMRoscQA'
b'This is a test string to be encoded'
This is a test string to be encoded

AES

To use AES you need to create a Key and an IV (initalization vector). The Key is shared between the pair, The IV can be different for each message.

Below a sample with use of the the Python Cryptography Toolkit https://www.dlitz.net/software/pycrypto/ (https://github.com/dlitz/pycrypto) This library is a collection of both secure hash functions (such as SHA256 and RIPEMD160), and various encryption algorithms (AES, DES, RSA, ElGamal, etc.).

In [50]:
from Crypto.Cipher import AES
 
key = b'ABCDEFGHIJ123456'
iv = b'1234567890ZYXWVU'
 
cipher = AES.new(key, AES.MODE_CFB, iv)
data = 'Encryption should be used to make life with GDPR simpler'
msg = iv + cipher.encrypt(data)
plain=cipher.decrypt(msg)
 
print (plain[16:])
b'Encryption should be used to make life with GDPR simpler'

In general you MUST use a Crypto library that is actively maintained. Prefferd is that the project has a CII badge. So always check: https://bestpractices.coreinfrastructure.org/en/projects?gteq=100

This pycrypto library is not active maintained anymore, so DO NOT use it for production. There is a fork: https://pypi.org/project/pycryptodome/ that has good documentation (https://www.pycryptodome.org/en/latest/) and is maintained.

In [51]:
from Crypto.Cipher import AES  
import base64

def cypher_aes(secret_key, msg_text, encrypt=True):
    # an AES key must be either 16, 24, or 32 bytes long
    remainder = len(secret_key) % 16
    modified_key = secret_key.ljust(len(secret_key) + (16 - remainder))[:32]
    print(modified_key)

    
    remainder = len(msg_text) % 16
    modified_text = msg_text.ljust(len(msg_text) + (16 - remainder))
    print(modified_text)

    cipher = AES.new(modified_key, AES.MODE_ECB)  # use of ECB mode in enterprise environments is very much frowned upon

    if encrypt:
        return base64.b64encode(cipher.encrypt(modified_text)).strip()

    return cipher.decrypt(base64.b64decode(modified_text)).strip()


#encrypted = cypher_aes(b'secret_AES_key_string_to_encrypt/decrypt_with', b'input_string_to_encrypt/decrypt', encrypt=True)
encrypted = cypher_aes(string, b'Encryption must be done good! Test,test and test!', encrypt=True)
print(encrypted)
print()
print('A wrong decryption string will not work:')
print(cypher_aes(b'tst', encrypted, encrypt=False))
print()
print('Now the correct string:')
print(cypher_aes(string, encrypted, encrypt=False))
b'This is a test string to be enco'
b'Encryption must be done good! Test,test and test!               '
b'swaNl1u8fhMDkpwasBvmHuc6nU6UW9NHVEfn/SQ0buDF0oK7Kf34gz2B+yXzp2T2sZpqax/MUGTZw8L96tW05A=='

A wrong decryption string will not work:
b'tst             '
b'swaNl1u8fhMDkpwasBvmHuc6nU6UW9NHVEfn/SQ0buDF0oK7Kf34gz2B+yXzp2T2sZpqax/MUGTZw8L96tW05A==        '
b'\xa3\xc7\x9c\xc1\xa8\x08\xdd\xa5\xe2\xeeE\xe4\xc2\xaaNX\x82\xdc\x0eh\x1b"\xdc\xd8K\x8d\x93.2\xe7\x99\r\xe8\xaf\x16me\x86%\xec\x14(y\x95\xaeuS\xb9&\xb7\xf9\xb7\x13\xd6\x8b8\x08_\x0f\xc4\xa9\x8a\\S'

Now the correct string:
b'This is a test string to be enco'
b'swaNl1u8fhMDkpwasBvmHuc6nU6UW9NHVEfn/SQ0buDF0oK7Kf34gz2B+yXzp2T2sZpqax/MUGTZw8L96tW05A==        '
b'Encryption must be done good! Test,test and test!'

Hashing

Python has nice default hashing library. This default implements a common interface to many different secure hash and message digest algorithms. E.g. hash algorithms SHA1, SHA224, SHA256, SHA384, and SHA512 are supported.

In [52]:
import hashlib
m = hashlib.sha256()
m.update(b"Nobody makes the mistake")
m.update(b" to use hashing to be protect privacy information!")
m.digest()
b'\x03\x1e\xdd}Ae\x15\x93\xc5\xfe\\\x00o\xa5u+7\xfd\xdf\xf7\xbcN\x84:\xa6\xaf\x0c\x95\x0fK\x94\x06'
print(m.digest_size)
print(m.block_size)
32
64