How to be a better spy using Python

Alice is a spy, Bob is her handler and Charlie is a spy catcher.

Alice needs to send message to Bob. Charlie is able to intercept all messages. Alice need to be able to do some things:

  1. Even if Charlie gets his hand on the message, he shouldn’t be able to read it.
  2. Bob needs to know if the message was sent by Alice and not intercepted and changed by Charlie.

This is the basis of cryptography. How to communicate securely on a network that is not secure.

Alice wants to try her programming skills building a cryptography system, but she has been advised not to do so. It is a bad idea to build a cryptography system from scratch. Some one will be able to break it. It is better to use an already established one.

Symmetric Cryptography

Alice can encrypt her message using a secret key. The key is used to change the message. What comes out is an unreadable message that can only be changed back using the same key. Anyone not in possession of the key won’t be able to decode the message.

from cryptography.fernet import Fernet

key = Fernet.generate_key()

message = 'The plans are in safety deposit box 42'
f = Fernet(key)
encrypted = f.encrypt(message.encode())
decrypted = f.decrypt(encrypted)

print('{:>18}: {}'.format('Original Message', message))
print('{:>18}: {}'.format('Key', key.decode()))
print('{:>18}: {}'.format('Encrypted Message', encrypted.decode()))
print('{:>18}: {}'.format('Decrypted Message', decrypted.decode()))

  Original Message: The plans are in safety deposit box 42
               Key: wK2eAuvEEJqTlU80ekum6KToW2L97NivM1ul8pFvHLI=
 Encrypted Message: gAAAAABf6wdRksZaonpcHi1WXwC6WSd96b82CNJjbta2kM71mVsK3bPQuaEgnpN6RbFQnWyKsJXSXxYJUqq1HV5e5_dnX6R3XmMlpjAVS1aKpypt9qUEOuw-o4320JIYE_Wi5n9k_PmV
 Decrypted Message: The plans are in safety deposit box 42

Bob will be able to decrypt the message with the key. But Bob would have had to agree the key with Alice before receiving the messages. If Alice sent the key to Bob separately, it would still be over the network. If Charlie intercepted the key in some way, he could read alter and encode a new message and send it to Bob. Very John le Carré.

There has to be some way for Alice to send Bob a message where the key isn’t compromised and where Bob is sure that the message originated from Alice and was not altered in any way.

Asymmetric Cryptography

The solution is Asymmetric cryptography. In this case there are two keys. A secret one and a public one. Both Alice and Bob will have a private and public key each. A message encoded with a public key can only be decoded with a private key.

If Alice wants to send Bob a secret message, she encodes it with his public key. Charlie is unable to decode this message without Bob’s private key. Bob doesn’t have to compromise his private key by sending it over the network and is the only one able to decode the message.

Another interesting feature is that Alice can encode a message with her private key that can only be decoded with the public key. This means that anyone will be able to decode the message because the public key is out there. But the only person who could have written the message was Alice. This means that Bob can be sure the message originated from Alice and hasn’t been tampered with.

Alice can write a message, encrypt it with her private key, and re encrypt that message with Bob’s public key. This means that only Bob will be able to decrypt the message and will be able to confirm that the message did indeed come from Alice and hadn’t been tampered with.

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding

message = 'The plans are in safety deposit box 42'.encode()


private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
    backend=default_backend()
)
public_key = private_key.public_key()
pem = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption()
)

encrypted = public_key.encrypt(
        message,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )

decrypt = private_key.decrypt(
    encrypted,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)

# Sign a message
signature = private_key.sign(message, padding.PKCS1v15(), hashes.SHA1())
verified = public_key.verify(signature, message, padding.PKCS1v15(), hashes.SHA1()) is None

print('{:>18}: {}'.format('Original Message', message.decode()))
print('{:>18}: {}'.format('Private Key', private_key))
print('{:>18}: {}'.format('Encrypted Message', encrypted))
print('{:>18}: {}'.format('Decrypted Message', decrypted.decode()))
print('{:>18}: {}'.format('Signature', signature))
print('{:>18}: {}'.format('Verified', verified))


  Original Message: The plans are in safety deposit box 42
       Private Key: <cryptography.hazmat.backends.openssl.rsa._RSAPrivateKey object at 0x7fb692cb3a20>
 Encrypted Message: b'\\\x9f\x91\xcf\xd4\x99\xdc\x01\xda\x1fe\t/\xeaw\xc8\xe3\x08.\x7f\xf9\x94\xe8Om\x18\x98\x8e\xff|#\x86{\xb5\xba\xfcSJx\xc9cVS\tm\x05+]\xce\x17\x9c\x8d\xc8Q\x95Q\x83H\xe8\xa3l\xe7\xdd\xe2Y\xea]\xb3z\xbc\x12\x1aB~\x1c3\xcc\xed%0#h/\xe0/x\x83~p\xd4\x1b\xa6h\xc35\xc3\xe8\x8aw\xdb\xed\x89\xebk\x11\xdc[\xc8\x99\x9c\xa6s\xc7\x92\x04\xbf!\xb3\xbc\xe1\xa1\xbbiU*\xd8\x10\x19\x87b\x9d.2\x99\xe8=\xde\x87\xa0\x8c\xc0\x16,\xf8\xe5\r\xec\xdf\xaaL\xca\xa7|\xbc\x80\xd6i\x14I%6\xc0\x80\x10D\x1e\xcdC\x9e8\x96\xc4\xf1\x94Z\xae\xaa\xbd\x19d\x90JV\\\xeb\xbf\xe3\x16\xe5\xca\xd5s\x9b-;Fu\x1e\xa2\xdd\x05\x8b\x83\xf4\x0f\x8b$\xe0\x00\x13\x8e\x14\xad\xb8\xa8_bG\x91\x92\x19b\xd7\xd9o\xed\x0cT\x10\xf6\x1f]\xcf\xea+;\n\x01\xb3\x99\xac\x0f\x91\x06\x1e>\x98K\xc3\xb9\x08U\x03;\xc6\xb7'
 Decrypted Message: The plans are in safety deposit box 42
         Signature: b'q\xd5K\x10bv\xbfd\x0bb\x9f_\xcc<\xc4\x83\x071F\xe8\x99\xe2\x87\xa6\x0b\xaae\xdfZ{\xa8Y\xfa\xbdg\xff\xf8@AF\xba\xe7\xe9SO\x84\x97b\xd2r\x7fb\xa9\xeb\xba\x83\x0f\x1c\xdfX%6UD\x0f\x8a\x86:\xb2\x14\xbd9\xec\x93\xf3\x04\xc4M\x07\x88\xbeae]8l\xc8\xbfl\x03M\xec3\xbdBP\xb2\x96MR?\xd4u\x87x\x1d15m\xae^\x94\xb7l\xc2 I`\x02\x86j\xa5\x8a\xfd\x7f\xcd\xcd\xe3\x0c\xb18\x14X\x82\xf6BK\xcf\xbcl0\xe0x\xb7%"\xecD7.\x1d\xf82g#\xa0bX\xfb\xeb|\xd52$\xb8:\xf8\xc9X4\xb5)\r8\x00AB\xcd\xc6<\x91\x0b\xb7\x98\xd8\xb3\x1d\xdc\xb6Q\xcb\xc2\xfdG\xc2\xb5\xc7^\xb7\x05];6\xcb\x14\x96\x12c\x94\xa7{\xf3B\xf6\x81\x81\x80s#e\xfc\x88@\xa8P\x91\xd9\x0eX+\x92\x16\n\x83\x98\x0bFb:!\xdc\xf2\'\x9f\x84\xb6\xc2\x9bY|[#s\x1eo$'
          Verified: True

This type of process is done hundreds of times on an average day of a personal computer. Each time you log into a secure site or write an email, this happens in the background. It is worth having an overall understanding of what is happening because it is such an integral process for communication.

References

The code for this post was from the excellent post here.

Leave a comment

Your email address will not be published. Required fields are marked *