def resolve_second_round_key_average(plaintext_to_ones, first_round_key): start_key = '0'*64 simon = SimonCipher(0) current_key = start_key for index in range(len(start_key)): vote = 0 print(index, current_key) zero_bucket = [] for plaintext in plaintext_to_ones: # Take plaintext and run through one level of encryption given # the first round key. This allows us to use the same process we # used for finding the first round key to get the next round key ones_for_plaintext = plaintext_to_ones[plaintext] plaintext_binary = str(bin(plaintext))[2:].zfill(128) right = plaintext_binary[len(plaintext_binary)//2:].zfill(64) left = plaintext_binary[:len(plaintext_binary)//2].zfill(64) binary_left = int(left, 2) binary_right = int(right, 2) first_round_ct1, first_round_ct2 = simon.encrypt_round(int(left,2), int(right,2), int(first_round_key, 2)) # do same process as outlined in getting first round key next_round_ct1, _ = simon.encrypt_round(first_round_ct1, first_round_ct2, 0) pre_xor_bin = bin(next_round_ct1)[2:].zfill(64) pre_xor_ones = ones(int(pre_xor_bin, 2)) value = pre_xor_bin[index] if value == '0': zero_bucket.append(ones_for_plaintext) zero_bucket_average = sum(zero_bucket)/max(len(zero_bucket),1) if zero_bucket_average >= 8703/2+.5: current_key = flip_next_one(current_key, index) return current_key
def test_pcbc_mode_single(self): c = SimonCipher(self.key, self.key_size, self.block_size, 'PCBC', init=self.iv) pcbc_out = c.encrypt(self.plaintxt) c = SimonCipher(self.key, self.key_size, self.block_size, 'ECB') pcbc_equivalent = c.encrypt(self.iv ^ self.plaintxt) assert pcbc_out == pcbc_equivalent
def test_simon128_256(self): block_size = 128 key_size = 256 for x in range(self.test_cnt): key = randint(0, (2**key_size) - 1) plaintxt = randint(0, (2**block_size) - 1) c = SimonCipher(key, key_size, block_size, 'ECB') assert c.decrypt(c.encrypt(plaintxt)) == plaintxt, 'Test %r Failed with Random Key %r and Random Plaintext %r' % (x, hex(key), hex(plaintxt))
def verify_key(key, plaintext_to_ones): w = SimonCipher(int(key,2)) wrong = 0 for plaintext in plaintext_to_ones: _, current_ones = w.encrypt(plaintext) offset = abs(current_ones - plaintext_to_ones[plaintext]) if offset != 0: wrong += 1 return wrong
def test_simon128_128(self): key = 0x0f0e0d0c0b0a09080706050403020100 plaintxt = 0x63736564207372656c6c657661727420 ciphertxt = 0x49681b1e1e54fe3f65aa832af84e0bbc block_size = 128 key_size = 128 c = SimonCipher(key, key_size, block_size, 'ECB') assert c.encrypt(plaintxt) == ciphertxt assert c.decrypt(ciphertxt) == plaintxt
def test_simon128_192(self): key = 0x17161514131211100f0e0d0c0b0a09080706050403020100 plaintxt = 0x206572656874206e6568772065626972 ciphertxt = 0xc4ac61effcdc0d4f6c9c8d6e2597b85b block_size = 128 key_size = 192 c = SimonCipher(key, key_size, block_size, 'ECB') assert c.encrypt(plaintxt) == ciphertxt assert c.decrypt(ciphertxt) == plaintxt
def test_simon128_256(self): key = 0x1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100 plaintxt = 0x74206e69206d6f6f6d69732061207369 ciphertxt = 0x8d2b5579afc8a3a03bf72a87efe7b868 block_size = 128 key_size = 256 c = SimonCipher(key, key_size, block_size, 'ECB') assert c.encrypt(plaintxt) == ciphertxt assert c.decrypt(ciphertxt) == plaintxt
def test_simon32_64(self): key = 0x1918111009080100 plaintxt = 0x65656877 ciphertxt = 0xc69be9bb block_size = 32 key_size = 64 c = SimonCipher(key, key_size, block_size, 'ECB') assert c.encrypt(plaintxt) == ciphertxt assert c.decrypt(ciphertxt) == plaintxt
def test_simon96_96(self): key = 0x0d0c0b0a0908050403020100 plaintxt = 0x2072616c6c69702065687420 ciphertxt = 0x602807a462b469063d8ff082 block_size = 96 key_size = 96 c = SimonCipher(key, key_size, block_size, 'ECB') assert c.encrypt(plaintxt) == ciphertxt assert c.decrypt(ciphertxt) == plaintxt
def test_simon96_144(self): key = 0x1514131211100d0c0b0a0908050403020100 plaintxt = 0x74616874207473756420666f ciphertxt = 0xecad1c6c451e3f59c5db1ae9 block_size = 96 key_size = 144 c = SimonCipher(key, key_size, block_size, 'ECB') assert c.encrypt(plaintxt) == ciphertxt assert c.decrypt(ciphertxt) == plaintxt
def test_simon64_96(self): key = 0x131211100b0a090803020100 plaintxt = 0x6f7220676e696c63 ciphertxt = 0x5ca2e27f111a8fc8 block_size = 64 key_size = 96 c = SimonCipher(key, key_size, block_size, 'ECB') assert c.encrypt(plaintxt) == ciphertxt assert c.decrypt(ciphertxt) == plaintxt
def test_simon48_72(self): key = 0x1211100a0908020100 plaintxt = 0x6120676e696c ciphertxt = 0xdae5ac292cac block_size = 48 key_size = 72 c = SimonCipher(key, key_size, block_size, 'ECB') assert c.encrypt(plaintxt) == ciphertxt assert c.decrypt(ciphertxt) == plaintxt
def test_simon48_96(self): key = 0x1a19181211100a0908020100 plaintxt = 0x72696320646e ciphertxt = 0x6e06a5acf156 block_size = 48 key_size = 96 c = SimonCipher(key, key_size, block_size, 'ECB') assert c.encrypt(plaintxt) == ciphertxt assert c.decrypt(ciphertxt) == plaintxt
def test_ctr_mode_equivalent(self): c = SimonCipher(self.key, self.key_size, self.block_size, 'CTR', init=self.iv, counter=self.counter) ctr_out = c.encrypt(self.plaintxt) c = SimonCipher(self.key, self.key_size, self.block_size, 'ECB') ecb_out = c.encrypt(self.iv + self.counter) ctr_equivalent = ecb_out ^ self.plaintxt assert ctr_out == ctr_equivalent
def test_simon64_128(self): key = 0x1b1a1918131211100b0a090803020100 plaintxt = 0x656b696c20646e75 ciphertxt = 0x44c8fc20b9dfa07a block_size = 64 key_size = 128 c = SimonCipher(key, key_size, block_size, 'ECB') assert c.encrypt(plaintxt) == ciphertxt assert c.decrypt(ciphertxt) == plaintxt
def test_ofb_mode_chain(self): plaintxts = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] c = SimonCipher(self.key, self.key_size, self.block_size, 'OFB', init=self.iv) ciphertexts = [c.encrypt(x) for x in plaintxts] c = SimonCipher(self.key, self.key_size, self.block_size, 'OFB', init=self.iv) decryptexts = [c.decrypt(x) for x in ciphertexts] assert plaintxts == decryptexts
def test_simon64_96(key): #key = 0x131211100b0a090803020100 plaintxt = 0x6d564d37426e6e71 ciphertxt = 0xbb5d12ba422834b5 block_size = 64 key_size = 96 c = SimonCipher(key, key_size, block_size, 'ECB') if c.encrypt(plaintxt) == ciphertxt: return hex(key) return 0
def simon128_256_Cipher(k, p): #simon128/256-CTR ctr_cipher = SimonCipher(k, mode='CTR', init=0xCABCABCAB, counter=1, key_size=256, block_size=128) simon_ciphertext = ctr_cipher.encrypt(p) return simon_ciphertext
def test_ctr_mode_single_cycle(self): self.counter = 0x01 c = SimonCipher(self.key, self.key_size, self.block_size, 'CTR', init=self.iv, counter=self.counter) ctr_out = c.encrypt(self.plaintxt) self.counter = 0x01 c = SimonCipher(self.key, self.key_size, self.block_size, 'CTR', init=self.iv, counter=self.counter) output_plaintext = c.decrypt(ctr_out) assert output_plaintext == self.plaintxt
def test_speck64_96(keyi): key = binascii.hexlify(keyi) print key key = int("0x" + key, 16) plaintxt = 0x6d564d37426e6e71 ciphertxt = 0xbb5d12ba422834b5 block_size = 64 key_size = 96 c = SimonCipher(key, key_size, block_size, 'ECB') print hex(c.encrypt(plaintxt)) if c.encrypt(plaintxt) == ciphertxt: print keyi if c.decrypt(ciphertxt) == plaintxt: print keyi
def test_cbc_mode_chain(self): c = SimonCipher(self.key, self.key_size, self.block_size, 'CBC', init=self.iv) cbc_out = 0 for x in range(1000): cbc_out = c.encrypt(self.plaintxt) c = SimonCipher(self.key, self.key_size, self.block_size, 'ECB') cbc_equivalent = self.iv for x in range(1000): cbc_input = self.plaintxt ^ cbc_equivalent cbc_equivalent = c.encrypt(cbc_input) assert cbc_out == cbc_equivalent
def test_ctr_mode_chain(self): c = SimonCipher(self.key, self.key_size, self.block_size, 'CTR', init=self.iv, counter=self.counter) ctr_out = 0 for x in range(1000): ctr_out = c.encrypt(self.plaintxt) c = SimonCipher(self.key, self.key_size, self.block_size, 'ECB') ctr_equivalent = 0 for x in range(1000): ecb_out = c.encrypt(self.iv + self.counter) self.counter += 1 ctr_equivalent = ecb_out ^ self.plaintxt assert ctr_out == ctr_equivalent
def test_ofb_mode_equivalent(self): c = SimonCipher(self.key, self.key_size, self.block_size, 'OFB', init=self.iv) ofb_encrypt = c.encrypt(self.plaintxt) c = SimonCipher(self.key, self.key_size, self.block_size, 'OFB', init=self.iv) ofb_decrypt = c.decrypt(ofb_encrypt) c = SimonCipher(self.key, self.key_size, self.block_size, 'ECB') ecb_out = c.encrypt(self.iv) ofb_equivalent_encrypt = ecb_out ^ self.plaintxt ofb_equivalent_decrypt = ecb_out ^ ofb_equivalent_encrypt assert ofb_encrypt == ofb_equivalent_encrypt assert ofb_decrypt == ofb_equivalent_decrypt
def test_pcbc_mode_chain(self): c = SimonCipher(self.key, self.key_size, self.block_size, 'PCBC', init=self.iv) cbc_out = 0 for x in range(1000): cbc_out = c.encrypt(self.plaintxt) c = SimonCipher(self.key, self.key_size, self.block_size, 'ECB') pcbc_equivalent = 0 for x in range(1000): pcbc_input = self.plaintxt ^ self.iv pcbc_equivalent = c.encrypt(pcbc_input) self.iv = pcbc_equivalent ^ self.plaintxt assert cbc_out == pcbc_equivalent
def SimCTR(ptxt, key1, nonce): counter = 0 temp2 = 0 NonceCount = nonce ^ counter ctxt = [] E = SimonCipher(key1, key_size=128, block_size=64) block = breakup(ptxt, 8) #since block size = 64 only 8 chars for i in range(len(block)): NonceCount = nonce ^ counter counter = counter + 1 temp = E.encrypt(NonceCount) for a in block[ i]: #shift temp2 by 1 byte each time and or it with a new byte temp2 = (temp2 << 8) | ord(a) ctxt.append((temp ^ temp2)) # accumulate onto the ctxt temp2 = 0 return (ctxt)
def argon2_test(): start = time.time() ph = PasswordHasher() hash = ph.hash(password) hashed = hashlib.sha256(hash).digest() end = time.time() print "argon2 : ",(end-start) start = time.time() obj =AES.new(hashed,AES.MODE_CBC, 'This is an IV456') ciphertext = obj.encrypt("The answer is no") end = time.time() print "AES Encrypt: ",(end-start)*1000 start = time.time() obj =AES.new(hashed,AES.MODE_CBC, 'This is an IV456') plaintext = obj.decrypt(ciphertext) end = time.time() print "AES Decrypt: ",(end-start)*1000 my_plaintext = 0xCCCCAAAA55553333 start = time.time() big_cipher = SimonCipher(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF0000, key_size=256, block_size=128) simon = big_cipher.encrypt(my_plaintext) end = time.time() print "Simon Encrypt: ",(end-start)*1000 start = time.time() big_cipher1 = SpeckCipher(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF0000, key_size=256, block_size=128) speck = big_cipher1.encrypt(my_plaintext) end = time.time() print "Speck Encrypt: ",(end-start)*1000 start = time.time() big_cipher = SimonCipher(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF0000, key_size=256, block_size=128) plain = big_cipher.decrypt(simon) end = time.time() print plain print "Simon Decrypt: ",(end-start)*1000 start = time.time() big_cipher1 = SpeckCipher(0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFF0000, key_size=256, block_size=128) plain = big_cipher1.decrypt(speck) end = time.time() print plain print "Speck Decrypt: ",(end-start)*1000
class Simon: def __init__(self, key_size, blocklength): if key_size != 96: raise InvalidKeyLength("Keylength of Simon must be 96 bits!") if blocklength % 64 != 0: raise InvalidCipherBlockLength("Blocklength of Simon should be multiplier of 64") self._key = None self._key_size = key_size self._blocklength = blocklength def set_key(self, key): hex_key = bits_to_hex(key) self._key = SimonCipher(hex_key, key_size=96, block_size=64) def encrypt(self, message): split_message = [message[x:x+64] for x in range(0, len(message), 64)] encrypted_message = [] for single_message in split_message: hex_message = bits_to_hex(single_message) encrypted_hex = self._key.encrypt(hex_message) encrypted_message = encrypted_message + hex_to_bits(encrypted_hex, 64) return encrypted_message def decrypt(self, message): split_message = [message[x:x + 64] for x in range(0, len(message), 64)] decrypted_message = [] for single_message in split_message: hex_message = bits_to_hex(single_message) decrypted_hex = self._key.decrypt(hex_message) decrypted_message = decrypted_message + hex_to_bits(decrypted_hex, 64) return decrypted_message
def EtM(ptxt, key1, key2, nonce): counter = 0 temp2 = 0 NonceCount = nonce ^ counter ctxt = 0 E = SimonCipher(key1, key_size=256, block_size=128) mac = CMAC.new(key=key2.encode(), ciphermod=AES) #Mac block block = breakup(ptxt, 16) for i in range(len(block)): NonceCount = nonce ^ counter counter = counter + 1 temp = E.encrypt(NonceCount) for a in block[ i]: #shift temp2 by 1 byte each time and or it with a new byte temp2 = (temp2 << 8) | ord(a) ctxt = (ctxt << 128) | (temp ^ temp2) # accumulate onto the ctxt temp2 = 0 T = mac.update(str(ctxt).encode()).hexdigest() print("CTXT: ") print(hex(ctxt)) print("T: ") print(T)
def EaM(ptxt, key1, key2, nonce): counter = 0 temp2 = 0 NonceCount = nonce ^ counter ctxt = 0 E = SimonCipher(key1) #encryption block default 128 bit mac = Poly1305.new(key=key2.encode(), cipher=AES) #Mac block block = breakup(ptxt, 16) T = mac.update(ptxt.encode()).hexdigest() for i in range(len(block)): NonceCount = nonce ^ counter counter = counter + 1 temp = E.encrypt(NonceCount) for a in block[ i]: #shift temp2 by 1 byte each time and or it with a new byte temp2 = (temp2 << 8) | ord(a) #print(temp2) #print(temp) ctxt = (ctxt << 128) | (temp ^ temp2) # accumulate onto the ctxt print("CTXT: ") print(hex(ctxt)) print("T: ") print(T)
def resolve_first_round_key_average(plaintext_to_ones): start_key = '0'*64 current_key = start_key simon = SimonCipher(0) for index in range(len(start_key)): print(index, current_key) zero_bucket = [] for plaintext in plaintext_to_ones: # Take plaintext and run through one level of encryption with # a key of all zeros. This allows us to get ct2 (which is just # the left bits) and the pre-xored ct1 (ct1 but has not been # xored with a key yet, we pass in a key of zeros so the xor # does nothing). We then append the number of ones for this # plaintext to the zero bucket only if the pre-xored ct1 at # the current index is zero ones_for_plaintext = plaintext_to_ones[plaintext] plaintext_binary = str(bin(plaintext))[2:].zfill(128) right = plaintext_binary[len(plaintext_binary)//2:].zfill(64) left = plaintext_binary[:len(plaintext_binary)//2].zfill(64) ct1, ct2 = simon.encrypt_round(int(left,2), int(right,2), 0) pre_xor_bin = bin(ct1)[2:].zfill(64) value = pre_xor_bin[index] if value == '0': zero_bucket.append(ones_for_plaintext) # flip the current entry to 1 if this threshold is met # this threshold is derived from (68*128-1)/2 (total number of bits # minus the bit we are fixing in this scenario, we then divide by 2). # This gives us the expected number of ones for all of the other bits # We then consider the case where we set the bit of the key at this # index to 1. This can be modeled similar to part a where we either have # t regular coin flips or t regular coin flips + 1. So now, if we want to know # whether or not we have the t/2 or t/2+1 scenario, we set our threshold to be # in between these two distributions (i.e. t/2 + 0.5) zero_bucket_average = sum(zero_bucket)/max(len(zero_bucket),1) if zero_bucket_average >= 8703/2+.5: current_key = flip_next_one(current_key, index) return current_key
def test_cbc_mode_chain(self): c1 = SimonCipher(self.key, self.key_size, self.block_size, 'CBC', init=self.iv) c2 = SimonCipher(self.key, self.key_size, self.block_size, 'ECB') cbc_iv_equivalent = self.iv for x in range(1000): cbc_input = self.plaintxt ^ cbc_iv_equivalent cbc_iv_equivalent = c2.encrypt(cbc_input) cbc_out = c1.encrypt(self.plaintxt) assert cbc_out == cbc_iv_equivalent
def test_cbc_mode_single(self): c = SimonCipher(self.key, self.key_size, self.block_size, 'CBC', init=self.iv) cbc_out = c.encrypt(self.plaintxt) c = SimonCipher(self.key, self.key_size, self.block_size, 'ECB') cbc_equivalent = c.encrypt(self.iv ^ self.plaintxt) assert cbc_out == cbc_equivalent c = SimonCipher(self.key, self.key_size, self.block_size, 'CBC', init=self.iv) cbc_out = c.decrypt(cbc_out) c = SimonCipher(self.key, self.key_size, self.block_size, 'ECB') cbc_equivalent = c.decrypt(cbc_equivalent) ^ self.iv assert hex(cbc_out) == hex(cbc_equivalent) == hex(self.plaintxt)