One time pad python

One-Time Pad Implementation (Python)

A One-Time Pad is a stream cipher which is considered to grant unconditional security, since it uses a randomly generated bit stream, which has to be at least as long as the message.

A simple scheme to show how the OTP works was implemented in Python, where two parties (Alice and Bob) generate their set of secret keys and then send to each other encrypted messages. The set of keys is stored in a text file by each of them, and as they encrypt or decrypt a message, said key must be deleted, so it is not reused.

Since the messages must be mapped to bits to be able to perform the XOR operation, a classical alphabet consisting of the 26 letters in English was defined using an instantaneous and one-way type-B code. In the implementation, the dictionary structure was employed.

Considering that the number of bits per letter increases considerably, it was decided to assign the shorter bit mappings to the most frequent letters found in the English language. source

The first step was to generate securely a stream of bits. For this purpose, the built-in urandom method was employed. It generates a string of n bytes, which are then converted to a binary representation in a string.

def generateBitStream(n): byts = urandom(n) bits = '' count = 0 for i in bytearray(byts): byte = bin(i)[2:] if len(byte) < 8: zeros = '' dif = 8 - len(byte) for j in xrange(dif): zeros += '0' byte = zeros + byte bits += byte return bits

It has to be noted that, depending on the number of bytes generated, the messages to be encrypted are limited in length. This is due the cipher requiring that the key must be at least as long as the message.
Afterwards, the set of randomly generated keys are stored in two files: alicekeys and bobkeys using the standard functions in Python.
For Alice or Bob to send a message, it must first be cleaned (making all the letters uppercase and deleting whitespaces), and then, using the letter-to-bits- dictionary, mapped properly.

def plaintextToBits(msg): p = msg.upper().replace(' ', '') bits = ''; for i in p: if i in alphabet: bits += str(alphabet[i]) return bits

It is then possible to encrypt whichever message is to be sent to the other party by performing the XOR operation on each of the bits of both the plaintext and the key. The decryption method does the same as the encryption one, so there was no need to duplicate code.

def encrypt(p, k): c = '' if len(p) > len(k): print 'Mensaje muy largo' exit() for i in xrange(len(p)): a = int(p[i]) b = int(k[i]) tmp = a^b c += str(tmp) return c

I would note that there might be unnecessary lines in the code above; however, the interpreter would not allow for the XOR operation to work properly if it were on a single line.

Читайте также:  Bhop cfg для css

As mentioned before, each key must be deleted whenever it is read, whether for encryption or decryption, so the method was coded as follows:

def readKey(keyname): keyfile = open(keyname, 'r') key = keyfile.readline() lines = keyfile.readlines() keyfile = open(keyname, 'w') keyfile.writelines(lines[0:]) # this omits the first line keyfile.close() return key

After the ciphertext is sent to the other party and then decrypted, it must use the string of bits to map to the letters. Although a dictionary is thought to match keys to a value, it was also possible to get all the possible values and then find the corresponding key when a match between the values is found. The required Python syntax to accomplish this was taken from a stackoverflow answer. Considering that the alphabet is coded using an instantaneous code, a buffer is filled with bits until it reaches a 0 value, since that would mean it already is a match to some letter.
Using the python solution and the instantaneous code’s attribute, the plaintext was parsed back to a letter representation in the following way:

def parseBits(bits): buffer = '' msg = '' for l in bits: buffer += l if l is '0': msg += alphabet.keys()[list(alphabet.values()).index(int(buffer))] buffer = '' return msg

The message is then read, although in uppercase and without blank spaces, since the current alphabet doesn’t take into account those two things.
This implementation could be improved by using the ASCII set of characters as an alphabet to allow for more readable messages, but it would require to think as how to design an efficient coding, as there are way more characters than the classical 26-letter alphabet.

a. Before writing or reading messages, the set of keys must be generated first, as follows:

jesus@spica:~/crypto$ python otp.py -g 2 4

This will result in two text files, namely, alicekeys and bobkeys. The content of both files are exactly the same, two keys of 4-byte (32 bits) length each:

b. Alice sends a message to Bob, which must of a short length considering the pad generated previously:

jesus@spica:~/crypto$ python otp.py -b ‘hola’
Alice envia ciphertext: 01010000010101110111010000
Bob lee mensaje: HOLA

Looking at the code, this is what’s happening:

  1. Alice reads her own key from her pad file, which is deleted immediately.
  2. The plaintext from the command-line argument is parsed into a binary coding due to the defined alphabet.
  3. The plaintext is encrypted using her secret key.
  4. Bob receives the ciphertext and reads the secret key from his own pad (which is then deleted immediately).
  5. Bob decrypts the ciphertext and, using the resulting string of bits, parses it back to the defined alphabet.
akey = readKey('alicekeys') p = args[2] pbits = plaintextToBits(p) c = encrypt(pbits, akey) print 'Alice envia ciphertext: ', c bkey = readKey('bobkeys') pd = decrypt(c, bkey) msg = parseBits(pd) print 'Bob lee mensaje: ', msg

After running the above code, the remaining content of both pads is:

Hence, only the second key that was originally generated remains.

c. The last use case is when Bob sends a message to Alice, though it’s not worth mentioning the details since it’s very similar to Alice sending the message.

Code in repository

https://github.com/antoniosv/crypto/blob/master/otp.py
Instructions to run are printed whenever the program is executed without the proper parameters.

CRYPTOGRAPHY AND NETWORK SECURITY: PRINCIPLES AND PRACTICE. FIFTH EDITION. William Stallings. Prentice Hall.

Elson, Stenio. get value by key in a dictionary. http://stackoverflow.com/questions/8023306/get-key-by-value-in-dictionary/13149770#13149770

Knowledge regarding the uniquely decodable and instantenous B Code is acknowledged to the lecture notes from the Information Theory and Coding Methods course taught by Dr. Sergio Alcaráz.

Источник

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

A hacky implementation of one-time-pad

License

jailuthra/onetimepad

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Sign In Required

Please sign in to use Codespaces.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.rst

One-Time-Pad Python is a command-line encryption tool, which uses an encryption mechanism very similar to One-time Pad (Duh. Thanks for telling that)

To use it from the command-line, run:

Or, import the onetimepad module in your script:

#!/usr/bin/env python3 import onetimepad cipher = onetimepad.encrypt('some text', 'a_random_key') msg = onetimepad.decrypt(cipher, 'a_random_key')
  1. The crypted message is very easy to crack if the length of key is less than the length of message.
  2. In any case, the key is not necessarily random, which makes this tool as good as a toy.
  3. Thus, do not encrypt any real private stuff, it won’t protect you from the NSA. It is just a hack.

This project is licensed under the terms of MIT LICENSE, please see LICENSE file for more details.

About

A hacky implementation of one-time-pad

Источник

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

Implementation of one-time pad encryption in Python.

License

rsmith-nl/onepad

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Sign In Required

Please sign in to use Codespaces.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.rst

The onepad.py script is a program to use binary one-time pads. This is a port and simplification of a previous version written in C.

The onepad.py program reads a file and a key and then combines them using the exclusive-or operation. The resulting data is written to standard output.

Key files and encrypted files are stored as base64 encoded text.

Plaintext is compressed with bzip2 before encryption. Ciphertext is likewise decompressed after decryption.

Keep in mind that this program was written as an exercise. In theory, one-time pads offer perfect security if:

  • The used keys are really random.
  • Each key is only used only once.
  • The keys are only known to the sender and recipient.

In practice using e.g. public key cryptography is much more convenient and probably more secure.

The genpad.py program gets the random data for the one-time pads from os.urandom . So whether the keys are usable depends on the underlying implementation. If implemented correctly operating systems gather randomness from unpredictable events like keystrokes, mouse movements and arriving network packets. This can be used to (re-)seed a cryptographically secure pseudo-random number generator. (CSPRNG) But you should investigate the quality of the keys before trusting them!

The tests now include a randomness test of a large key.

If a key is re-used, the one-time pad is transformed into a running key cipher, which is much less secure. Keys should be destroyed by e.g. overwriting them with zeroes after use.

Since the keys are as long as the message, transporting them securely is a problem. You could e.g. generate a lot of keys, burn them on a DVD and courier that to the recipient. But this is only secure if the keys aren't intercepted. So in practice, using public key cryptography is much easier.

About

Implementation of one-time pad encryption in Python.

Источник

Оцените статью