Private Key Encryption Scheme

In the private key encryption scheme:
  • The same key is used for encryption and decryption.
  • This key should be kept private against the adversary.
  • The private key must be securely shared before performing encryption and decryption.

Threat model

  • Passive attack: The adversary can simply perform eavesdropping the communication channel.
  • Known plaintext attack: The adversary has some plaintext-ciphertext pairs.
  • Chosen plaintext attack: The adversary has a control over which plaintext to be encrypte. (Example: World War II). In theory, we model an adversary who has encryption capability (even without knowing the key).
  • Chosen ciphertext attack: In an ultimately serious scenario, the adversary may additionally obtain some power of accessing the information about the decrypted message (Example: padding oracle attack). In theory, the attacker is modeled to have both encryption AND decryption capability (without knowing the key).

  • Security notion: indistinguishability (under a chosen plaintext attack)

    The security definition considers a mental experiment.
    Think of this mental experiment as a kind of car crash test to assess how secure and robust a car is.

    Although this experiment is designed to capture security concerns regarding real scenarios,
    but it's not really the same as any specific real scenario.

    1. Give the adversary time to inspect the encryption scheme.
    2. Let the adversary choose two plaintexts that will be most easily crackable from his perspective. (This step captures the chosen plaintext attack).
    3. Pick one of the two messages at random and encrypt it.
    4. Give the resulting ciphertext to the adversary.
    5. Have the adversary guess which message has been encrypted.
    6. The ciphertext reveals nothing about the plaintext, the adversary can be successfully only by random guessing, which is exactly probability 1/2.

      To capture this (relaxing it only slightly), if the probability that the adversary makes the good guess is 1/2 + negligible, then the encryption scheme is called indistinguishable. Here, negligible is something like 1/10000000000000.

    Block ciphers

    A block cipher works on fixed-length blocks. The most famous block cipher is AES.

    Spciefically, A block cipehr \(F\) is a deterministic algorithm that works as follows:

    • Input: \( K, M \)
      • \(K\): A fixed-length encryption key
      • \(M\): A fixed-length plaintext block.
    • Output: \(C\)
      • \(C\): A fixed-length ciphertext block.
      Requirement
      • The length of M is fixed, and it's the same as the length of C.
      • We call the length of M (= the length of C) as the block size.
      We use the following notation: \[ C \leftarrow F_K(M) \]

      Block cipher = Pseudorandom permutation

      A block cipher is also called a pseudorandom permutation. In particular, a cipher block looks random, if you don't know the key (and even if you know the message block).

    Decryption

    If you have a key, then block cipher allows you to decrypt a ciphertext.

    Mode of Operations: Encrypting a long message

    Electronic Code Book (ECB) Mode

    The encryption scheme with ECB mode is not indistinguishable under chosen plaintext attack.

    Cipher Block Chaining (CBC) Mode

    If IV is chosen uniformly random, the encryption scheme with CBC mode is indistinguishable under a chosen plaintext attack. It is important to choose IV randomly. Otherwise, for example, if the same message is encrypted again in some future, the adversary will note it.

    Counter (CTR) Mode

    If ctr is chosen uniformly random, the encryption scheme with CTR mode is indistinguishable under a chosen plaintext attack. It is important to choose IV randomly. Otherwise, for example, if the same message is encrypted again in some future, the adversary will note it.

    Comparison

    padding IV or ctr randomized encryption parallel encryption parallel decryption security
    ECB yes no no yes yes no
    CBC yes yes yes no yes yes with random IV
    CTR no yes yes yes yes yes with random ctr

    Message Authentication Code (MAC)

    A MAC scheme provides message integrity. A MAC consists of three algorithms \( ({\sf MGen}, {\sf Mac}, {\sf MVer}) \) shown in the following picture.

    Using MAC to ensure message integerity

    Security: unforgeability

    We call that a MAC scheme is unforgeable if no adversary should be able to generate a valid MAC tag on any new message.

    Secure MAC scheme: HMAC

    Let \( H: \{0,1\}^* \rightarrow \{0,1\}^n \) be a collision resistant hash function.

    The idea for the construction is that the tag should be something like the hash on both the key and the message. Since the adversary doesn't know the key, it will probably have hard time in guessing the right hash value on (key, message). However, simply computing $H( K || M )$ is known to be insecure, and the construction uses the "double-layer" hashing.

    HMAC with SHA-256 hash function

    Using Python

    Writing the experiment of indistinguishability under a chosen ciphertext attack

    Do you remember this experiment and how to break it?
    $ ./part7.py
    The target ciphertext is
    iv: 81109c7dff291f6c57f0d6479a334ac8
    ct: c892dfdcdaead56d88fbfebac7142442c0fdc499ff0694983d4cd251afd32fb0da6595f66d3e5fb091b7a0f0f18ad9b5
    
    
    =============
    Menu: 0 (encrypt), 1 (decrypt), 2 (open): 0
    msg to encrypt in a hexstring format: 11223344aabb
    iv: a681a0c60ae6fab05f9f1762d3de9ed5
    ct: 36be519e0bf9a9fe84e3d51323925195
    
    =============
    Menu: 0 (encrypt), 1 (decrypt), 2 (open): 1
    iv (in hexstring): a681a0c60ae6fab05f9f1762d3de9ed5
    ct (in hexstring): 36be519e0bf9a9fe84e3d51323925195
    decryption is:
        b'\x11"3D\xaa\xbb'
    
    =============
    Menu: 0 (encrypt), 1 (decrypt), 2 (open): 1
    iv (in hexstring):  81109c7dff291f6c57f0d6479a334ac8
    ct (in hexstring):  c892dfdcdaead56d88fbfebac7142442c0fdc499ff0694983d4cd251afd32fb0da6595f66d3e5fb091b7a0f0f18ad9b5
    Cannot decrypt the target ciphertext!
    
    =============
    Menu: 0 (encrypt), 1 (decrypt), 2 (open): 1
    iv (in hexstring):  a7bdcc39485abc97f1e20e372e08bfa1
    ct (in hexstring):  1216c53c503147f45eb6e970a90ba959
    decryption is:
        b'Hello World'
    
    =============
    Menu: 0 (encrypt), 1 (decrypt), 2 (open): 2
    The message was:  b"Don't use ECB. It's not IND-CPA secure"
    

    Using HMAC in Python

    Write code lab08.py that implements the following function:
    
    def computeHMAC(key, data):
    
    Sample run with pic_original.bmp.
    
    >>> import lab08
    
    >>> key = b"0123456789abcdef"
    >>> data = open("pic_original.bmp", "rb").read()
    
    >>> lab08.computeHMAC(key, data)
    b'c2\xba$\x93@\xa4\x9d\xe2\x07\x065`\xb0\xe5$\xb6F\xd5\xact>\x02\xf88r\xc1\x81\x04\xf3\xa45'
    
    >>> key = b"my really secret key"
    >>> lab08.computeHMAC(key, data)
    b'G]\x90\xb5\xd2:@s\xc3y\x1b\xed\x8a\x9d+$\xbe\r\x9b\x14g\xed \x06\x0c\x813%d\x889F'
    

    Pickle

    The pickle module implements serializing and de-serializing a Python object.

    Bytes → Object: Unpickling with pickle.loads()

    We can dump a Python object to a bytes stream using pickle.dumps() function. We can load a Python object from a bytes object using pickle.loads() function.
    
    >>> x = {1:"hello", "list":[1,2,3], "key": 100}
    >>> type(x)
    <class 'dict'>
    >>> import pickle
    >>> b = pickle.dumps(x)
    >>> b
    b'\x80\x04\x95(\x00\x00\x00\x00\x00\x00\x00}\x94(K\x01\x8c\x05hello\x94\x8c\x04list\x94]\x94(K\x01K\x02K\x03e\x8c\x03key\x94Kdu.'
    >>> y = pickle.loads(b)
    >>> y
    {1: 'hello', 'list': [1, 2, 3], 'key': 100}
    >>>
    

    Warning

    It is possible to construct malicious pickle data which will execute arbitrary code during unpickling. Never unpickle data that could have come from an untrusted source, or that could have been tampered with.

    Safer serialization formats such as json may be more appropriate if you are processing untrusted data.

    Json

    Pickle dumps an object in a binary format. Using json module, you can dump an object into a string format.
    
    >>> x = {1:"hello", "list":[1,2,3], "key": 100}
    >>> type(x)
    <class 'dict'>
    >>> import json
    >>> s = json.dumps(x)
    >>> s
    '{"1": "hello", "list": [1, 2, 3], "key": 100}'
    >>> type(s)
    <class 'str'>
    >>> y = json.loads(s)
    >>> y
    {'1': 'hello', 'list': [1, 2, 3], 'key': 100}