|
import math |
|
|
|
class RandSeq: |
|
POS_BOX = [ |
|
[0x1, 0xb, 0x4, 0x9, 0xd, 0x8, 0xc, 0xa, 0xf, 0xe, 0x2, 0x7, 0x6, 0x0, 0x5, 0x3], |
|
[0x7, 0xd, 0x9, 0x1, 0xf, 0xe, 0x8, 0xb, 0x6, 0xc, 0x3, 0x0, 0x2, 0x4, 0xa, 0x5], |
|
] |
|
def __init__ (self, key, start, stop, next_seq=0): |
|
self.key = key |
|
self.key_len = len(key) |
|
self.start = start |
|
self.stop = stop |
|
diff = stop - start |
|
bit_size = math.log2(diff + 1) |
|
self.diff = diff |
|
self.byte_size = math.ceil (bit_size / 8) |
|
self.next_seq = next_seq |
|
self.end_seq = 2 ** (self.byte_size * 8) - 1 |
|
|
|
def next(self): |
|
while self.next_seq <= self.end_seq: |
|
plain_num = self.next_seq.to_bytes( |
|
self.byte_size, byteorder='little') |
|
new_num = self._encrypt(plain_num) |
|
self.next_seq += 1 |
|
if new_num >= self.start and new_num <= self.stop: |
|
return new_num + self.start |
|
return None |
|
|
|
def shift_cir(self, val, shift_val, bit_size): |
|
upper = (val << shift_val) % (1 << bit_size) |
|
lower = val >> (bit_size - shift_val) |
|
return upper | lower |
|
|
|
def _encrypt(self, plain_bytes): |
|
length = len(plain_bytes) |
|
bit_size = len(plain_bytes) * 8 |
|
mask = 2**bit_size - 1 |
|
key_idx = 0 |
|
for i in range(8): |
|
new_plain_bytes = [] |
|
for plain_byte in plain_bytes: |
|
key = self.key[key_idx%self.key_len] |
|
upper = plain_byte >> 4 |
|
lower = plain_byte & 0x0f |
|
new_plain = self.POS_BOX[0][upper] << 4 | self.POS_BOX[1][lower] |
|
new_plain ^= key |
|
key_idx += 1 |
|
new_plain_bytes.append(new_plain) |
|
plain_num = int.from_bytes(new_plain_bytes, byteorder="little") |
|
plain_num += self.key_len |
|
plain_num &= mask |
|
plain_num = self.shift_cir(plain_num, 5, bit_size) |
|
plain_bytes = plain_num.to_bytes(length, byteorder="little") |
|
|
|
new_plain_bytes = [] |
|
for plain_byte in reversed(plain_bytes): |
|
key = self.key[key_idx%self.key_len] |
|
upper = plain_byte >> 4 |
|
lower = plain_byte & 0x0f |
|
new_plain = self.POS_BOX[0][upper] << 4 | self.POS_BOX[1][lower] |
|
new_plain ^= key |
|
key_idx += 1 |
|
new_plain_bytes.append(new_plain) |
|
plain_num = int.from_bytes(new_plain_bytes, byteorder="little") |
|
plain_num += self.key_len |
|
plain_num &= mask |
|
plain_num = self.shift_cir(plain_num, 5, bit_size) |
|
plain_bytes = plain_num.to_bytes(length, byteorder="little") |
|
return plain_num |
|
|
|
|
|
def main01(): |
|
randseq = RandSeq(b"Test", start=0, stop=2**4-1) |
|
num_set = set() |
|
for _ in range(2**8 - 1): |
|
new_number = randseq.next() |
|
if new_number is None: |
|
break |
|
if new_number in num_set: |
|
print("error") |
|
print(new_number) |
|
num_set.add(new_number) |
|
|
|
if __name__ == "__main__": |
|
print("======== Start ========") |
|
main01() |
|
print("======== End ========") |