{ "info": { "author": "Calvin McCoy", "author_email": "calvin.mccoy@protonmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Security :: Cryptography" ], "description": "# Simon & Speck Block Ciphers in Python 3.x/2.x\n\nPure python implementations of the [Simon and Speck] block ciphers. These are small ciphers designed by the [National Security Agency] for use in constrained hardware and software environments such as micro controllers or small ASICs/FPGAs.\n\n**WARNING** The following implementations are for reference/research/entertainment only and should not be considered 100% free of bugs or side channel attacks. Use in a production environment is discouraged.\n\n## Installation ##\n\nThe Simon/Speck suite can be installed from [PyPi] via `pip`:\n\n```sh\npip install simonspeckciphers\n```\n\nIf `pip` is unavailable, you download or clone this project and run from this directory:\n\n```sh\npython setup.py install\n```\n\nwhere `python` is favorite python interperator\n\nYou can verify the included pytest test suite with:\n```sh\npython setup.py test\n# or\npy.test -xvvv\n```\n\n## Basic Usage ##\nSimon and Speck work identically. Once the code has been copied into your project, the ciphers can be imported:\n```sh\n>>> from speck import SpeckCipher\n>>> from simon import SimonCipher\n```\n\nOnce imported, a ciphers object that store the state of the cipher can be created. The only parameter required to initialize a cipher object is an encryption key.\n```sh\n>>> my_speck = SpeckCipher(0x123456789ABCDEF00FEDCBA987654321)\n>>> my_simon = SimonCipher(0xABBAABBAABBAABBAABBAABBAABBAABBA)\n```\n\nOnce initialized, the cipher can encrypt or decrypt provided plaintext or ciphertext values using the ```encrypt()``` and ```decrypt()``` methods. The object will continue to process encryption/decryption requests as long as the object exists.\n```sh\n>>> my_plaintext = 0xCCCCAAAA55553333\n>>> speck_ciphertext = my_speck.encrypt(my_plaintext)\n>>> speck_plaintext = my_speck.decrypt(speck_ciphertext)\n>>> simon_ciphertext = my_simon.encrypt(0xFFFF0000EEEE1111)\n>>> simon_plaintext = my_simon.decrypt(simon_ciphertext)\n```\nThe encryption key may be read or updated by way of the ```key``` attribute\n```sh\n>>> hex(my_speck.key)\n'0x123456789abcdef00fedcba987654321'\n```\n\n### Block and Key Size ###\nAll valid key and block sizes as described in the specification are supported as optional parameters. Valid block and key sizes in bits are:\n\n| **block size** | **key sizes** |\n|:--------------:|:-------------:|\n| 32 | 64 |\n| 48 | 72,96 |\n| 64 | 96,128 |\n| 96 | 96,144 |\n| 128 | 128,192,256 |\n\nIf not supplied at initialization, both ciphers will default to 128-bit encryption keys and block sizes. If the defaults are not used, it is reccomended to specify both the key size and block explictly. \n\n```sh\n>>> tiny_cipher = SpeckCipher(0x123456789ABCDEF0, key_size=64, block_size=32)\n>>> big_cipher = SimonCipher(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF0000, key_size=256, block_size=128)\n>>> trunc_cipher = SimonCipher(0x111122223333444455556666777788889999, key_size=96, block_size=48)\n>>> hex(trunc_cipher.key)\n'0x444455556666777788889999'\n```\n\nAll inputted values (keys, plaintexts, IVs, etc) will be truncated or padded with zeros to the bit size specified by the block and key sizes. The current key and block sizes can be accessed via the ```key_size``` and ```block_size``` attributes\n\n### Block Modes ###\nFor convenience, both ciphers support the [most common modes] of block cipher operation. \n\n- Electronic Code Book ```ECB``` (Default mode for Speck/Simon)\n- Counter ```CTR```\n- Cipher Block Chaining ```CBC```\n- Propagating Cipher Block Chaining ```PCBC```\n- Cipher Feedback ```CFB```\n- Output Feedback ```OFB```\n\nThese can be enabled at initialization using the ```mode``` optional argument or via the ```mode``` attribute after creation.\nOther than ECB, these modes require an additional Initialization Vector (IV) and possibly a Counter. These values can be set at cipher creation using the ```init``` and ```counter``` optional arguments. \nThe ciphers automatically update or increment the IV and counter values internal between encrypt and decrypt operations. There is no need to manual update them between operations.\n\n```sh\n>>> ofb_cipher = SpeckCipher(1234, mode='OFB', init=0x999999)\n>>> ctr_cipher = SimonCipher(0x525354, mode='CTR', init=0xCABCABCAB, counter=1)\n>>> ctr_cipher.counter\n1\n>>> ofb_cipher.update_iv()\n10066329\n```\n\nThe IV may be may also be altered or read anytime during the cipher objects life using the ```update_iv()``` method. If a new IV is provided, this method returns the current IV, otherwise, it returns the IV that was just updated. The ciphers internal counter value may be read and altered through the ```counter``` attribute.\n\n### Data Types ###\nCurrently, both the Speck and Simon ciphers expect **int** inputs for keys, IVs, counters, plaintexts, and ciphertexts. Any value provided that does not match the bit size for keys, plaintexts, etc, will be truncated down or MSB padded with 0's up to the correct size. If your application requires strings or bytearrays, input and output values can be easily translated to and from ints.\n\n```sh\n>>> key_bytes = bytes([0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00])\n# For Python 3.x Only\n>>> key_int = int.from_bytes(key_bytes, byteorder='big', signed='False')\n# Python 2.x/3.x\n>>> import binascii\n>>> key_int = int(binascii.hexlify(key_bytes),16)\n>>> hex(key_int)\n'0x112233445566778899aabbccddeeff00'\n>>> msg = 'ATTACK AT DAWN!!'\n>>> msg_int = sum([ord(c) << (8 * x) for x, c in enumerate(reversed(msg))])\n>>> hex(msg_int)\n'0x41545441434b204154204441574e2121'\n>>> new_cipher = SimonCipher(key_int, key_size=128, block_size=128)\n>>> my_secret = new_cipher(msg_int)\n>>> my_secret_bytes = bytearray.fromhex('{:032x}'.format(my_secret))\n>>> my_secret_bytes\nbytearray(b'HD\\xbb\\xe4\\xa1\\xed\\x95\\xd8>\\x1bx