这是这 one的后续问题.
我试着在答案中实现所有推荐的内容(除了注释,而且不是操作系统特定的)。再次,如果你看到任何需要改进,或会使它更快,请告诉我!
这是密码。这次只有222行:)。
#!/usr/bin/env python
# not sure if I did this right
import base64
import random
import os
def add_padding(plain_text, block_size=128):
plain_text = plain_text.encode()
padding = -(len(plain_text) + 1) % block_size # Amount of padding needed to fill block
padded_text = plain_text + b'=' * padding + bytes([padding + 1])
return decimal_to_binary(padded_text)
def xor_string(key, secret):
xored_secret = ''
for i in range(len(secret) // len(key)):
if i > 0:
key = get_round_key(key)
xored_secret += decimal_to_binary([bin_to_decimal(key, len(key))[0] ^ bin_to_decimal(secret[i * len(key):len(key) + (i * len(key))], len(key))[0]], len(key))
return xored_secret
def generate_key(key):
if len(key) >= 128:
key = decimal_to_binary(key.encode())
return key[:1024]
elif len(key) < 128:
key = key.encode()
for i in range(128 - len(key)):
b = decimal_to_binary([key[i]])
b = xor_string(decimal_to_binary([sum(key) // len(key)]), b[::-1])
key += bytes([int(b, 2)])
new_key = ''.join(str(i) for i in key)
half1 = new_key[:len(new_key) // 2]
half2 = new_key[len(new_key) // 2:]
new_key = decimal_to_binary([int(half1 + half2)])
new_key = new_key[:1024]
return new_key
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 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]
return decimal
def decimal_to_binary(decimal, length=8):
return ''.join(str(bin(num)[2:].zfill(length)) for num in decimal)
def base64_to_bin(base):
decoded = ''
for letter in base64.b64decode(base):
decoded += bin(letter)[2:].zfill(8)
return decoded
def matrix_to_str(m):
return ''.join(str(m[i][j]) for i in range(32) for j in range(32))
def obfuscate(binary, key, encrypting, loops):
shuffled_binary = ''
round_key = key
for i in range(len(binary) // 1024):
if i > 0:
round_key = get_round_key(round_key)
if encrypting:
m = [list(binary[j * 32 + i * 1024:j * 32 + i * 1024 + 32]) for j in range(32)]
m = shuffle(m, bin_to_decimal(round_key, 1024)[0], loops)
shuffled_binary += xor_string(round_key, matrix_to_str(m))
else:
xor = xor_string(round_key, 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(round_key, 1024)[0], loops)
shuffled_binary += matrix_to_str(m)
return xor_string(key, shuffled_binary)
def shuffle(m, key, loops):
for j in range(loops):
# 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(key)):
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, key, loops):
for j in range(loops):
# 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(key)):
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(seed):
random.seed(seed)
lst = list(range(1024))
random.shuffle(lst)
return lst
def get_round_key(key):
key = [[key[(j * 32 + n)] for n in range(32)] for j in range(32)]
# get the last column
col = [i[-1] for i in key]
# 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 key:
cols += row[i]
cols = cols[16:] + cols[:16]
new_key += xor_string(''.join(str(ele) for ele in col), cols)
return new_key
def bin_to_bytes(binary):
return int(binary, 2).to_bytes(len(binary) // 8, byteorder='big')
def encrypt(password, secret, loops):
key = generate_key(password)
secret = add_padding(secret)
secret = xor_string(key, secret)
secret = obfuscate(secret, key, True, loops)
secret = bin_to_base64(secret)
return secret
def decrypt(password, base, loops):
key = generate_key(password)
binary = base64_to_bin(base)
binary = xor_string(key, binary)
binary = obfuscate(binary, key, False, loops)
binary = bin_to_bytes(binary)
pad = binary[-1]
binary = binary[:-pad]
return binary.decode()
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)}')
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-27 22:03:13
cls的调用具有可疑的安全价值,如果您认为它具有这样的价值,最好调用一个跨平台库来完成同样的任务。目前,您是与Windows挂钩,这是不好的。你离拥有一个交叉兼容的应用程序如此之近;如果让这仍然是你唯一的障碍,那将是一件遗憾的事。现在,在这个示例中,我只是删除了您的cls调用。如果它们只是为了美学的目的,你应该保持它的方式。getpass而不是input,以防止密码的过度使用。obfuscate不是一个特别好的名称;只有当encrypting=True出现时,它才会“混淆”。名字很难命名;也许叫这个process_crypto或者一些名字。bytes数组(在不可变数据的情况下)或bytearray() (在可变数据的情况下)是至关重要的。bytes是一种更好的表示形式。我看到其中至少有三个不同的表达式,它们应该在一个单独的行上接收它们自己的独立的临时变量。
key重新分配到不同类型的值( str到bytes )是不可取的;请创建不同的变量名。__main__保护不足以创建作用域。要将主要变量放入函数范围,需要一个实际的函数。random对您的密码的安全性是有害的,而且可能是每个密码新手都会犯的错误之一。代之以调用secrets。涵盖上述一些(当然不是全部):
#!/usr/bin/env python
# not sure if I did this right
import base64
import random
from getpass import getpass
from typing import List
def add_padding(plain_text: str, block_size: int = 128) -> str:
plain_text = plain_text.encode()
padding = -(len(plain_text) + 1) % block_size # Amount of padding needed to fill block
padded_text = plain_text + b'=' * padding + bytes([padding + 1])
return decimal_to_binary(padded_text)
def xor_string(key: str, secret: str) -> str:
xored_secret = ''
for i in range(len(secret) // len(key)):
if i > 0:
key = get_round_key(key)
some_decimals = bin_to_decimal(secret[i * len(key):len(key) + (i * len(key))], len(key))
some_values = [
bin_to_decimal(key, len(key))[0] ^ some_decimals[0]
]
xored_secret += decimal_to_binary(some_values, len(key))
return xored_secret
def generate_key(key: str) -> str:
if len(key) >= 128:
key = decimal_to_binary(key.encode())
return key[:1024]
elif len(key) < 128:
key = key.encode()
for i in range(128 - len(key)):
b = decimal_to_binary([key[i]])
b = xor_string(decimal_to_binary([sum(key) // len(key)]), b[::-1])
key += bytes([int(b, 2)])
new_key = ''.join(str(i) for i in key)
half1 = new_key[:len(new_key) // 2]
half2 = new_key[len(new_key) // 2:]
new_key = decimal_to_binary([int(half1 + half2)])
new_key = new_key[:1024]
return new_key
def bin_to_base64(binary: str) -> str:
ints = [
int(binary[i * 8:8 + i * 8], 2)
for i in range(len(binary) // 8)
]
return base64.b64encode(bytes(ints)).decode()
def bin_to_decimal(binary: str, length: int = 8) -> List[int]:
b = [binary[i * length:length + (i * length)] for i in range(len(binary) // length)]
decimal = [int(i, 2) for i in b]
return decimal
def decimal_to_binary(decimal: List[int], length: int=8) -> str:
return ''.join(
str(bin(num)[2:].zfill(length))
for num in decimal
)
def base64_to_bin(base: str) -> str:
decoded = ''
for letter in base64.b64decode(base):
decoded += bin(letter)[2:].zfill(8)
return decoded
def matrix_to_str(m: List[List[str]]) -> str:
return ''.join(
str(m[i][j])
for i in range(32) for j in range(32)
)
def obfuscate(binary: str, key: str, encrypting: bool, loops: int) -> str:
shuffled_binary = ''
round_key = key
for i in range(len(binary) // 1024):
if i > 0:
round_key = get_round_key(round_key)
if encrypting:
m = [list(binary[j * 32 + i * 1024:j * 32 + i * 1024 + 32]) for j in range(32)]
m = shuffle(m, bin_to_decimal(round_key, 1024)[0], loops)
shuffled_binary += xor_string(round_key, matrix_to_str(m))
else:
xor = xor_string(round_key, 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(round_key, 1024)[0], loops)
shuffled_binary += matrix_to_str(m)
return xor_string(key, shuffled_binary)
def shuffle(m: List[List[str]], key: int, loops: int) -> List[List[str]]:
for j in range(loops):
# 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(key)):
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: List[List[str]], key: int, loops: int) -> List[List[str]]:
for j in range(loops):
# 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(key)):
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(seed: int) -> List[int]:
random.seed(seed)
lst = list(range(1024))
random.shuffle(lst)
return lst
def get_round_key(key):
key = [[key[(j * 32 + n)] for n in range(32)] for j in range(32)]
# get the last column
col = [i[-1] for i in key]
# 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 key:
cols += row[i]
cols = cols[16:] + cols[:16]
new_key += xor_string(''.join(str(ele) for ele in col), cols)
return new_key
def bin_to_bytes(binary: str) -> bytes:
return int(binary, 2).to_bytes(len(binary) // 8, byteorder='big')
def encrypt(password: str, secret: str, loops: int = 1) -> str:
key = generate_key(password)
secret = add_padding(secret)
secret = xor_string(key, secret)
secret = obfuscate(secret, key, True, loops)
secret = bin_to_base64(secret)
return secret
def decrypt(password: str, base: str, loops: int = 1) -> str:
key = generate_key(password)
binary = base64_to_bin(base)
binary = xor_string(key, binary)
binary = obfuscate(binary, key, False, loops)
binary = bin_to_bytes(binary)
pad = binary[-1]
binary = binary[:-pad]
return binary.decode()
def main():
while True:
com = input(
'1) Encrypt Text\n'
'2) Decrypt Text\n'
'3) Exit\n'
)
input_text = input('Enter the text: ')
key = getpass('Enter your key: ')
if com == '1':
print(f'Encrypted text: {encrypt(key, input_text)}')
elif com == '2':
print(f'Decrypted text: {decrypt(key, input_text)}')
elif com == '3':
break
print()
if __name__ == '__main__':
main()一般说来,为了教育和娱乐目的,编写这样的代码是很有趣的。然而,密码实现很难得到正确的实现,有时甚至更难证明它们是正确的。在真实的生产世界中,请不要使用这个,只需调用一个库。
https://codereview.stackexchange.com/questions/260077
复制相似问题