def test_AllLengthMessages(self): key = base64.urlsafe_b64encode(os.urandom(16)) fstl = MyFeistel(key, 10) for i in xrange(101): txt = os.urandom(i+1) dtxt = fstl.decrypt(fstl.encrypt(txt)) assert dtxt == txt
def test_Functionality(self): key = base64.urlsafe_b64encode(os.urandom(16)) feistel = MyFeistel(key, 10) # decrypt(encrypt(msg)) == msg for i in xrange(20): msg = os.urandom(6) assert feistel.decrypt(feistel.encrypt(msg)) == msg
def test_padding(self): key = base64.urlsafe_b64encode(os.urandom(16)) feistel = MyFeistel(key, 10) msg = os.urandom(41) h_msg = msg.encode('hex') length = len(msg) L, R = '0' + h_msg[:length], '0' + h_msg[length:] assert feistel._pad_string(msg)[1] == (L + R).decode('hex')
def test_randomnessOfCtx(self): ctxs = [] for i in xrange(100): key = base64.urlsafe_b64encode(os.urandom(16)) feistel = MyFeistel(key, 10) msg = os.urandom(40) ctx = feistel.encrypt(msg) assert ctx not in ctxs ctxs.append(ctx)
def test_randomnessOfMsgAndIV(self): ctxs = [] for i in xrange(100): key = base64.urlsafe_b64encode(os.urandom(16)) feistel = MyFeistel(key, 10) for j in xrange(10): msg = os.urandom(40) ctx = feistel._feistel_round_enc(msg, j) assert ctx not in ctxs ctxs.append(ctx)
def test_msgNotEqualCtx(self): key = base64.urlsafe_b64encode(os.urandom(16)) feistel = MyFeistel(key, 10) for i in xrange(20): msg = os.urandom(40) assert feistel.encrypt(msg) != msg
def test_varyingRoundsFeistel(self): key = base64.urlsafe_b64encode(os.urandom(16)) for i in xrange(4, 14): feistel = MyFeistel(key, i) msg = os.urandom(40) assert feistel.decrypt(feistel.encrypt(msg)) == msg
def test_feistelRoundEncDec(self): key = base64.urlsafe_b64encode(os.urandom(16)) for i in xrange(10): feistel = MyFeistel(key, 10) msg = os.urandom(40) assert feistel._feistel_round_dec(feistel._feistel_round_enc(msg, i), i) == msg
def test_zeroLengthMessage(self): key = base64.urlsafe_b64encode(os.urandom(16)) feistel = MyFeistel(key, 10) msg = os.urandom(0) assert feistel.decrypt(feistel.encrypt(msg)) == msg
def test_Functionality(self): key = base64.urlsafe_b64encode(os.urandom(16)) feistel = MyFeistel(key, 10) for i in xrange(20): msg = os.urandom(40) assert feistel.decrypt(feistel.encrypt(msg)) == msg
def test_paddingAndUnpadding(self): key = base64.urlsafe_b64encode(os.urandom(16)) feistel = MyFeistel(key, 10) msg = os.urandom(41) assert feistel._unpad_string(True, feistel._pad_string(msg)[1]) == msg
def setup(self): key = base64.urlsafe_b64encode('1234567890abcdef') self._feistel = MyFeistel(key, num_rounds=10) self._feistel1 = MyFeistel(key, num_rounds=1) self._feistel2 = MyFeistel(key, num_rounds=2) self._feistel10 = MyFeistel(key,num_rounds=10)
class TestMyFeistel(object): def setup(self): key = base64.urlsafe_b64encode('1234567890abcdef') self._feistel = MyFeistel(key, num_rounds=10) self._feistel1 = MyFeistel(key, num_rounds=1) self._feistel2 = MyFeistel(key, num_rounds=2) self._feistel10 = MyFeistel(key,num_rounds=10) def test_basic(self): txt = b'A great Secret message'*12 # To make it larger than 128-bit self.setup() # round 1 ctx = self._feistel1.encrypt(txt) dtxt = self._feistel1.decrypt(ctx) assert dtxt==txt, "Failed 1-round Feistel test" # round 2 ctx = self._feistel2.encrypt(txt) dtxt = self._feistel2.decrypt(ctx) assert dtxt==txt, "Failed 2-round test" # round 10 ctx = self._feistel10.encrypt(txt) dtxt = self._feistel10.decrypt(ctx) assert dtxt==txt, "Failed 10-round test" def test_round1_LR_msg(self): txt = 'ThemessageisSecret' ctx = self._feistel1.encrypt(txt) n = len(ctx) assert ctx[:n/2] == txt[n/2:] def test_even_length_messages(self): self.setup() for i in range(2, 300, 2): txt = 'a'*i try: ctx = self._feistel.encrypt(txt) except AssertionError: ctx = '' try: dtxt = self._feistel.decrypt(ctx) if len(ctx)>0 else '' except AssertionError: dtxt = '' assert dtxt==txt assert len(ctx) == len(txt) def test_odd_length(self): """ Test: dec(enc(txt)) == txt, and Test: len(ctx) = len(txt) + 8 (8 is for the nonce/IV) (Note, if you use padding disable the length check test """ self.setup() for i in range(1, 300, 2): txt = 'a'*i try: ctx = self._feistel.encrypt(txt) except AssertionError: ctx = '' try: dtxt = self._feistel.decrypt(ctx) if len(ctx)>0 else '' except AssertionError: dtxt = '' assert dtxt==txt assert len(ctx) == len(txt) def test_ctxdist1(self): """Test the frequency of bytes in the cipher text for the same message and different keys. """ self.setup() txt = "Thequickbrownfoxjumpsoverthelazydog" cnt_dict = defaultdict(int) def _count_dict(s): for c in s: cnt_dict[c] += 1 exp_cnt = 10000 for i in xrange(exp_cnt): key = base64.urlsafe_b64encode(os.urandom(16)) ctx = MyFeistel(key, 10).encrypt(txt) _count_dict(ctx) t = sum(cnt_dict.values()) n = len(cnt_dict) assert t == exp_cnt * len(txt) expected_mean = t/256 expected_sd = math.sqrt(t * 255)/256 # Ideally the right hand side of the follwoing equations # shoudl be (mean +- 2 * sigma), but it is too close, and the # test is failing many times. That's why I am making it (4 * # sigma). # I should rather use standard statistical testing # framework for this. assert max(cnt_dict.values()) < expected_mean + 4*expected_sd assert max(cnt_dict.values()) > expected_mean - 4*expected_sd def test_ctxdist2(self): """ Test 1: Cipher text of different messages are different """ self.setup() n = 1000 next_ctx = lambda : self._feistel.encrypt(os.urandom(10)) assert len(set(next_ctx() for i in xrange(n))) == n, "Repeating whole ciphertext for differet messages!" def test_keyvalid(self): """ Wrong key should output junk. """ n = 1000 txt = os.urandom(100) self.setup() ctx = self._feistel.encrypt(txt) def next_ctx(): key = base64.urlsafe_b64encode(os.urandom(16)) feistel = MyFeistel(key, 10) return feistel.decrypt(ctx) output_ptxt = set(next_ctx() for i in xrange(n)) assert txt not in output_ptxt, "Decryption output same for different key!" assert len(output_ptxt) == n, "Repeating whole ciphertext for differet keys!" def test_part_of_the_message_is_not_revealed(self): """ Tests whether part of the message is revealed or not. """ self.setup() for i in xrange(1, 20): n = i*10 txt = os.urandom(n) ctx = self._feistel10.encrypt(txt) assert ctx.find(txt[n/2:]) == -1, "{} <--> {}".format(repr(ctx), repr(txt)) assert ctx.find(txt[:n/2]) == -1, "{} <--> {}".format(repr(ctx), repr(txt))
def next_ctx(): key = base64.urlsafe_b64encode(os.urandom(16)) feistel = MyFeistel(key, 10) return feistel.decrypt(ctx)