我已经做了很长一段时间了,现在我已经有了一个工作计划,我想我会看到其他人对它的看法。
基本上,如果你认为有什么东西能使它更快、更简单,或者让它变得更好,请分享你的想法。至于实际力量,我不知道如何测试。是的,我知道我应该使用AES,但这只是为了练习和娱乐。
总之,这是密码。(255行,对不起)
import base64
import os
import random
# from datetime import datetime
def add_padding(s, i=128):
padding = len(s) % i
for j in range(i - padding):
s += '='
s = ascii_to_bin(s)
# make last byte equal to number of padding bytes
s = s[:len(s) - 8] + decimal_to_binary([i - padding])
return s
def xor_string(k, s):
xored_secret = ''
for i in range(len(s) // len(k)):
if i > 0:
k = round_key(k)
xored_secret += decimal_to_binary([bin_to_decimal(k, len(k))[0] ^ bin_to_decimal(s[i * len(k):len(k) + (i * len(k))], len(k))[0]], len(k))
return xored_secret
def generate_key(k):
if len(k) == 128:
k = ascii_to_bin(k)
return k
elif len(k) < 128:
k = ascii_to_decimal(k)
for i in range(128 - len(k)):
b = decimal_to_binary([k[i]])
b = xor_string(decimal_to_binary([int(sum(k) / len(k))]), b[::-1])
k.append(int(b, 2))
s = ''
for i in k:
s += str(i)
j = str(s[:len(s) // 2])
y = str(s[len(s) // 2:])
s = decimal_to_binary([int(y + j)])
s = s[:1024]
return s
def bin_to_base64(binary):
return base64.b64encode(bytes([int(binary[i * 8:8 + i * 8], 2) for i in range(len(binary) // 8)])).decode()
def ascii_to_bin(string):
return decimal_to_binary(ascii_to_decimal(string))
def bin_to_decimal(binary, length=8):
b = [binary[i * length:length + (i * length)] for i in range(len(binary) // length)]
decimal = [int(i, 2) for i in b]
# returns an list of ints
return decimal
def decimal_to_binary(decimal, length=8):
output = ''
for i in range(len(decimal)):
output += str(bin(decimal[i])[2:].zfill(length))
# returns a string
return output
def ascii_to_decimal(string):
# returns a list of ints
return [ord(i) for i in string]
def bin_to_ascii(binary):
x = bin_to_decimal(binary)
s = ''
for i in x:
s += chr(i)
# returns a string
return s
def base64_to_bin(base):
decoded = ''
for letter in base64.b64decode(base):
# print(letter)
decoded += bin(letter)[2:].zfill(8)
return decoded
def matrix_to_str(m):
s = ''
for i in range(32):
for j in range(32):
s += str(m[i][j])
return s
def obfuscate(binary, k, x, xd):
b = ''
d = k # donkey kong
for i in range(len(binary) // 1024):
if i > 0:
d = round_key(d)
# m = [list(binary[j * 32 + i * 1024:j * 32 + i * 1024 + 32]) for j in range(32)]
if x:
m = [list(binary[j * 32 + i * 1024:j * 32 + i * 1024 + 32]) for j in range(32)]
m = shuffle(m, bin_to_decimal(d, 1024)[0], xd)
b += xor_string(d, matrix_to_str(m))
elif not x:
xor = xor_string(d, binary[i * 1024:i * 1024 + 1024])
m = [list(xor[j * 32:j * 32 + 32]) for j in range(32)]
m = reverse_shuffle(m, bin_to_decimal(d, 1024)[0], xd)
b += matrix_to_str(m)
return xor_string(k, b)
def shuffle(m, d, xd):
for j in range(xd):
# move columns to the right
m = [row[-1:] + row[:-1] for row in m]
# move rows down
m = m[-1:] + m[:-1]
shuffled_m = [[0] * 32 for _ in range(32)]
for idx, sidx in enumerate(test(d)):
shuffled_m[idx // 32][idx % 32] = m[sidx // 32][sidx % 32]
m = shuffled_m
# cut in half and flip halves
m = m[len(m) // 2:] + m[:len(m) // 2]
# test
m = list(map(list, zip(*m)))
return m
def reverse_shuffle(m, d, xd):
for j in range(xd):
# test
m = list(map(list, zip(*m)))
# cut in half and flip halves
m = m[len(m) // 2:] + m[:len(m) // 2]
shuffled_m = [[0] * 32 for _ in range(32)]
for idx, sidx in enumerate(test(d)):
shuffled_m[sidx // 32][sidx % 32] = m[idx // 32][idx % 32]
m = shuffled_m
# move rows up
m = m[1:] + m[:1]
# move columns to the left
m = [row[1:] + row[:1] for row in m]
return m
def test(d):
random.seed(d)
lst = list(range(1024))
random.shuffle(lst)
return lst
def round_key(k):
k = [[k[(j * 32 + n)] for n in range(32)] for j in range(32)]
# get the last column
col = [i[-1] for i in k]
# interweave
col = [x for i in range(len(col) // 2) for x in (col[-i - 1], col[i])]
new_key = ''
for i in range(32):
cols = ''
for row in k:
cols += row[i]
cols = cols[16:] + cols[:16]
new_key += xor_string(''.join(str(ele) for ele in col), cols)
return new_key
def encrypt(p, s, xd):
k = generate_key(p)
s = add_padding(s)
s = xor_string(k, s)
s = obfuscate(s, k, True, xd)
s = bin_to_base64(s)
return s
def decrypt(p, b, xd):
k = generate_key(p)
b = base64_to_bin(b)
b = xor_string(k, b)
b = obfuscate(b, k, False, xd)
pad = b[len(b) - 8:]
b = bin_to_ascii(b)
b = b[:len(b) - bin_to_decimal(pad)[0]]
return b
if __name__ == '__main__':
while True:
os.system('cls')
com = input('1)Encrypt Text \n2)Decrypt Text\n3)Exit\n')
if com == '1':
os.system('cls')
secret = input('Enter the text you wish to encrypt: ')
os.system('cls')
key = input('Enter your key: ')
os.system('cls')
print(f'Encrypted text: {encrypt(key, secret, 1)}') # the 1 is the number of loops, I'm not sure how many I should do :/
input()
elif com == '2':
os.system('cls')
b64 = input('Enter the text you wish to decrypt: ')
os.system('cls')
key = input('Enter your key: ')
os.system('cls')
print(f'Decrypted text: {decrypt(key, b64, 1)}')
input()
elif com == '3':
break如果你需要澄清什么,就问吧。谢谢!
发布于 2021-04-22 05:39:16
def add_padding(s, i=128):
padding = len(s) % i
for j in range(i - padding):
s += '='
...如果s是127个字符,则padding变为127个,但只添加1个=字符。
如果s为128个字符,则padding变为零,这是合理的。但是,128个=字符被添加到字符串中,这确实是出乎意料的。我知道这是必要的,因为你用填充的量代替了最后一个,但它违反了最不惊讶的原则。
用..。
s += '=' * (i - padding)比循环更有效率。
在添加填充并将其转换为位后,可以删除填充的最后8位,用填充的长度替换它。如果一开始不添加额外的填充字符,就可以节省一些工作。
下面是一些重新加工的代码:
def add_padding(message, frame_size=128):
payload_len = len(message) + 1 # Extra character encodes padding length
padding = -payload_len % frame_size # Amount of padding needed to fill frame
frames = message + '=' * padding + chr(padding + 1)
return ascii_to_bin(frames)def ascii_to_decimal(string):
# returns a list of ints
return [ord(i) for i in string]虽然这看起来很简单,但是大部分代码都需要8位字节,而不是整数。字符串中的第一个ā将被转换为257个,随后的bin(letter)[2:].zfill(length)将扩展为'100000001',尽管它的长度超过8个字符。
Python有一个内置函数,它将字符串转换为字节数组。str.encode()。默认情况下,它将使用UTF-8编码,并根据需要将非ASCII字符编码为多个字节:
>>> msg = 'cbā'
>>> msg_bytes = msg.encode()
>>> print(len(msg), len(msg_bytes), type(msg_bytes))
3 4 <class 'bytes'>但是请注意,字节数组的长度(在本例中)大于字符串的长度,这会使填充混乱。最简单的解决方法是将字符串转换为字节数组,然后确定需要填充多少空间,并将其添加到字节数组中。
>>> msg_bytes = msg.encode()
>>> payload_len = len(msg_bytes) + 1
>>> padding = -payload_len % frame_size
>>> frames = msg_bytes + b'=' * padding + bytes([padding + 1])另外,bytes (只读)和bytearray (可变)对象比使用整数列表的效率要高得多,因此通过切换到它们可以获得一定的速度和/或内存效率。
要在解码步骤中逆转这一点,请执行以下步骤:
>>> padding = frames[-1] # amount of padding added
>>> msg_bytes = frames[:-padding] # unpadded message bytes
>>> msg = msg_bytes.decode() # decode bytes back to a string
>>> msg
'cbā'发布于 2021-04-21 23:22:07
欢迎来到代码评审。
if __name__ == '__main__':块使其变得重要https://codereview.stackexchange.com/questions/259814
复制相似问题