KLEIN in Python
KLEIN is used to create block-cipher-based hash functions and message authentication codes (MACs), and is well-suited to resource-constrained devices.
It uses a fixed 64-bit block, and has a 64, 80 or 96-bit encryption key (KLEIN64, KLEIN80 and KLEIN96). Within each round, it uses a SubNibbles round, and which has 16 identical s-boxes (substitution boxes), and where each of the bytes in a round are fed into these in parallel. Each of the S-boxes are the same, and help protectagainst side channels, as each of the bytes will go through an identical box.
We start with a KEY and the PLAINTEXT. The method is then:
The method is:
sk <- KEY; STATE <- PLAINTEXT; for i = 1 to NR do AddRoundKey(STATE; sk[i]); SubNibbles(STATE); RotateNibbles(STATE); MixNibbles(STATE); sk[i+1] = KeySchedule(sk[i]; i); end for CIPHERTEXT <- AddRoundKey(STATE; skNR+1);
Each state has 16 bytes (the size of the block). The number of rounds is variable, but it typically 12 rounds for KLEIN64 (64-bit encryption key), 16 rounds for KLEIN80 (80-bit encryption key) and 20 rounds for KLEIN96 (96-bit encryption key):
klein64 = klein.KLEIN(nr=12, size=64) klein80 = klein.KLEIN(nr=16, size=80) klein96 = klein.KLEIN(nr=20, size=96)
The AddRoundKey() method splits the key into 16 bytes chunks for each round, and the RotateNibble() does a bit rotate on the current state:
def rotateNibbles(self, state): return (state << 16) & 0xFFFFFFFFFFFFFFFF | (state >> 48)
And the MixNibbles() does a scrambling function on the state.For limited devices, we could thus use a 64-bit encryption key, and which has 12 rounds, but for increased security we can move up to the 96-bit version. The 4-bit S-box is:
And the 4-bit S-box (subNibbles) is:
Input 0 1 2 3 4 5 6 7 8 9 A B C D E F Output 7 4 A 9 1 F B 0 C 3 2 6 8 E D 5
The following shows a Python version of the code:
import klein import binascii key=0xFFFFFFFFFFFFFFFF key="Test" plaintext="Hello" print ("Message:\t",plaintext) k=int(binascii.hexlify(key.encode()),16) m=int(binascii.hexlify(plaintext.encode()),16) # Test for klein64 # k=0xFFFFFFFFFFFFFFFF # m=0x0000000000000000 # Cipher 0x6456764e8602e154 # Test for klein80 # k=0xFFFFFFFFFFFFFFFFFFFF # m=0x0000000000000000 # Cipher 0x82247502273DCC5F # Test for klein96 # k=0xFFFFFFFFFFFFFFFFFFFFFFFF # m=0x0000000000000000 # Cipher 0x15A3A03386A7FEC6 klein64 = klein.KLEIN(nr=12, size=64) klein80 = klein.KLEIN(nr=16, size=80) klein96 = klein.KLEIN(nr=20, size=96) k64=klein64.encrypt(k, m) k80=klein80.encrypt(k, m) k96=klein96.encrypt(k, m) print ("KLEIN64 (NR=12, Size=64):\t",hex(k64)) print ("KLEIN80 (NR=16, Size=80):\t",hex(k80)) print ("KLEIN96 (NR=20, Size=96):\t",hex(k96))