TriviumTrivium is a Light Weight Stream Cipher and wascreated Christophe De Cannière and Bart Preneel [1], and has a low footprint for hardware. It has a relatively low gate count, power consumption and memory. Trivium has an 80-bit key, and has two shift registers and a nonlinear output function [paper][2]. Trivium I. It uses an 80-bit key, and generates up to 264 bits of output, with an 80-bit IV. TheoryOur cryptography methods are often block based which require memory storage and have a considerable gate footprint for their implementation. For devices with limited storage space and processing requirements, the requirements of many block-based symmetric encryption methods cannot be feasibly implement. We thus get light-weight cryptography method, and which have a lower processing requirement, and memory and gate footprint. With this, for symmetric key encryption, we often replace block cipher with stream ciphers. For this we generate an almost infinitely long key stream based on a key value and an IV (initialisation vector). The incoming bit stream is then EX-ORed with the key stream, and this is sent with the IV. On the other side, the key stream is recreated, and EX-OR with the cipher stream. This created the original data. Trivium is a Light Weight Stream Cipher and was created Christophe De Cannière and Bart Preneel, and has a low footprint for hardware. It uses an 80-bit key, and generates up to 2⁶⁴ bits of output, with an 80-bit IV. The Trivium cryptography method has 288 bit states and uses three registers (A, B and C), of 93, 84 and 111 bits. The method for each state is: The key and IV are loaded up initially as: We initially run through four 288 bit shifts before we take an output (this is defined as the warm up phase). The following gives an example of the cipher: Trivium has low requirements in hardware and only requires a 288-bit shift register, seven 3-input EX-OR gates, and three AND gates. We also created 64-bits of output for every clock cycle. TestsSome test vectors are [here]. Codefrom trivium import Trivium import binascii import sys def _hex_to_bytes(s): return [_allbytes[s[i:i+2].upper()] for i in range(0, len(s), 2)] def bits_to_hex(b): return "".join(["%02X" % sum([b[i + j] << j for j in range(8)]) for i in range(0, len(b), 8)]) def hex_to_bits(s): return [(b >> i) & 1 for b in _hex_to_bytes(s) for i in range(8)] _allbytes = dict([("%02X" % i, i) for i in range(256)]) def get_next_stream_byte(): rtn = 0 for j in range(8): rtn+=int(next_key_bit()) << j; return rtn _allbytes = dict([("%02X" % i, i) for i in range(256)]) message=b"hello" k1="0F62B5085BAE0154A7FA" i1="288FF65DC42B92F960C7" print ("Key: "+k1) print ("IV: "+i1) if (len(sys.argv)>1): k1=str(sys.argv[1]) if (len(sys.argv)>2): i1=str(sys.argv[2]) if (len(sys.argv)>3): message=str(sys.argv[3]).encode() KEY = hex_to_bits(k1)[::-1] IV = hex_to_bits(i1)[::-1] trivium = Trivium(KEY, IV) next_key_bit = trivium.keystream().__next__ keystream = [] for j in range(128): keystream.append(next_key_bit()) print ("Key stream: "+bits_to_hex(keystream)) trivium = Trivium(KEY, IV) next_key_bit = trivium.keystream().__next__ buffer=bytearray() for mybyte in message: c=get_next_stream_byte() newbyte = (mybyte ^ c ) & 0xFF buffer.append(newbyte) # Reset key stream trivium = Trivium(KEY, IV) next_key_bit = trivium.keystream().__next__ decrypt='' print ("\nPlaintext: ",message.decode()) print ("Cipher: ",binascii.hexlify(buffer)) for mybyte in buffer: c=get_next_stream_byte() newbyte = (mybyte ^ c) & 0xFF decrypt+=chr(newbyte) print (f"Decrypted: {decrypt}") A version which reads from a file and writes the output is: from trivium import Trivium def get_bytes_from_file(filename): return open(filename, "rb").read() def _hex_to_bytes(s): return [_allbytes[s[i:i+2].upper()] for i in range(0, len(s), 2)] def bits_to_hex(b): return "".join(["%02X" % sum([b[i + j] << j for j in range(8)]) for i in range(0, len(b), 8)]) def hex_to_bits(s): return [(b >> i) & 1 for b in _hex_to_bytes(s) for i in range(8)] _allbytes = dict([("%02X" % i, i) for i in range(256)]) def get_next_stream_byte(): rtn = 0 for j in range(8): rtn+=int(next_key_bit()) << j; return rtn k1="0F62B5085BAE0154A7FA" i1="288FF65DC42B92F960C7" print ("Key: "+k1) print ("IV: "+i1) KEY = hex_to_bits(k1)[::-1] IV = hex_to_bits(i1)[::-1] trivium = Trivium(KEY, IV) next_key_bit = trivium.keystream().__next__ b=get_bytes_from_file("1.txt") print ("Writing to cipher file") with open("cipher.txt", "wb") as binary_file: for mybyte in b: buffer=bytearray() # print (mybyte,get_next_stream_byte()) newbyte = (mybyte ^ get_next_stream_byte()) & 0xFF buffer.append(newbyte) binary_file.write(buffer) # Reset key stream trivium = Trivium(KEY, IV) next_key_bit = trivium.keystream().__next__ print ("Reading from cipher file") b=get_bytes_from_file("cipher.txt") with open("decipter.txt", "wb") as binary_file: for mybyte in b: buffer=bytearray() # print (mybyte,get_next_stream_byte()) newbyte = (mybyte ^ get_next_stream_byte()) & 0xFF buffer.append(newbyte) binary_file.write(buffer) |
References
[1] Cannière, C. D., & Preneel, B. (2008). Trivium. In New stream cipher designs (pp. 244-266). Springer, Berlin, Heidelberg.
[2] Tian, Y., Chen, G., & Li, J. (2009). On the design of Trivium. Cryptology ePrint Archive.