2

I am attempting to learn python and cryptography at the same time.

I am trying to alter the cipher text by a bit (or more) to see the effect it would have on my plaintext when decrypting.

For example:

from Crypto.Cipher import AES
import base64
import os

BLOCK_SIZE = 16
key = os.urandom(BLOCK_SIZE)

PADDING = '{'
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING

EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)

cipher = AES.new(key)

# encode a string
encoded = EncodeAES(cipher, 'This is some text.')
print 'Encrypted string:', encoded

# decode the encoded string
decoded = DecodeAES(cipher, encoded)
print 'Decrypted string:', decoded

So I want to decrypt again except having modified the cipher text ("encoded") before decrypting.

Thanks.

T.J.
  • 21
  • 1
  • This is already insecure. It's using the OS's random number generator, which may not be high enough quality for cryptography. – noɥʇʎԀʎzɐɹƆ Feb 21 '16 at 18:19
  • @CrazyPython urandom is perfectly fine for crypto (at least on linux). – Artjom B. Feb 21 '16 at 18:20
  • @T.J. Welcome to Stack Overflow! What is your actual question? Do you just want to modify `encoded` before you use `DecodeAES()` and are wondering what the best approach to doing that could be? – mech Feb 21 '16 at 18:23
  • @mech yes and thank you. – T.J. Feb 21 '16 at 18:23
  • Spoiler: Changing one bit in an encrypted block will essentially change about 50% of the decrypted bits in that block. – zaph Feb 22 '16 at 04:29

1 Answers1

0

The easiest way I can think of introducing some noise to the encoded string is to alter every nth character in it. You can play around with string manipulation to introduce more or less random noise (make the nth a random character, change it on every iteration, etc).

Add this function and imports somewhere before your code:

import string
import random

def noise_every_n(input, n, first=0):
    output = ""
    for i, c in enumerate(input, -first):
        if i % n == 0: # using ascii_letters and digits is just what came to mind, there's other ways to get random characters.
            output += random.choice(string.ascii_letters + string.digits)
        else:
            output += c
    return output

Then call the following between encode and decode:

every_n = random.randint(3, 5) # or just set it to a small integer
encoded = noise_every_n(encoded, every_n) 

The function above was adapted from this Stack Overflow answer.

Community
  • 1
  • 1
mech
  • 2,775
  • 5
  • 30
  • 38