我希望在Python中加密字符串(使用密码或密钥),而无需安装任何模块。我可以使用下载Python(2.7)时包含的默认模块,但是我无法安装像PyCrypto这样的东西。
我已经尝试过查看Simple way to encode a string according to a password?,但Base64的答案看起来并不安全,而其他人则需要外部模块。有人可以提供任何帮助吗?我没有任何代码可以展示,因为我还没有找到任何可以尝试的东西。
答案 0 :(得分:1)
考虑到目的是学校项目而不是生产(理论上它应该对抗无数攻击),我将发布一个解决方案。
code.py :
import sys
from itertools import cycle, izip
# from zipfile import ZipFile
from random import randint, seed
"""
try:
from StringIO import cStringIO as StringIO
except ImportError:
from StringIO import StringIO
"""
#DUMMY_ARCHIVED_FILE_NAME = "dummy_archived_file_name"
def encrypt_dummy0(text, password):
if len(text) > len(password):
pwd_iterable = cycle(password)
else:
pwd_iterable = password
ret = [chr(ord(i) ^ ord(j)) for i, j in izip(text, pwd_iterable)]
return "".join(ret)
decrypt_dummy0 = encrypt_dummy0
def encrypt_dummy1(text, password):
addition_char = randint(0, 0x100)
if len(text) > len(password):
pwd_iterable = cycle(password)
else:
pwd_iterable = password
ret = [chr(((ord(i) ^ ord(j)) + addition_char) % 0x100) for i, j in izip(text, pwd_iterable)]
return "".join(reversed(ret)) + chr(addition_char)
def decrypt_dummy1(encrypted_text, password):
addition_char = ord(encrypted_text[-1])
if len(encrypted_text) > len(password):
pwd_iterable = cycle(password)
else:
pwd_iterable = password
ret = [chr((((ord(i) - addition_char) + 0x100) % 0x100) ^ ord(j)) for i, j in izip(reversed(encrypted_text[:-1]), pwd_iterable)]
return "".join(ret)
"""
def encrypt_zipfile(text, password):
buf = StringIO()
with ZipFile(buf, "w") as zip_file:
zip_file.setpassword(password)
zip_file.writestr(DUMMY_ARCHIVED_FILE_NAME, text)
buf.seek(0)
return buf.read()
def decrypt_zipfile(encrypted_text, password):
buf = StringIO(encrypted_text)
with ZipFile(buf) as zip_file:
return zip_file.read(DUMMY_ARCHIVED_FILE_NAME, password)
"""
def test(text, password, encrypt_func, decrypt_func):
print("\nText: ({:d}) [{:s}] will be encrypted ({:s}) with password: ({:d}) [{:s}]".format(len(text), repr(text), encrypt_func.__name__, len(password), password))
encrypted = encrypt_func(text, password)
print("Encrypted text: ({:d}) [{:s}]".format(len(encrypted), repr(encrypted)))
decrypted = decrypt_func(encrypted, password)
print("Decrypted ({:s}) using password: ({:d}) [{:s}]: ({:d}) [{:s}]\n Same as original: {}".format(decrypt_func.__name__, len(password), password, len(decrypted), repr(decrypted), decrypted == text))
password_wrong = password[::-1]
decrypted_wrong = decrypt_func(encrypted, password_wrong)
print("Decrypted ({:s}) using password [{:s}]: [{:s}]\n Same as original: {}".format(decrypt_func.__name__, password_wrong, repr(decrypted_wrong), decrypted_wrong == text))
def main():
print("{:s} on {:s}".format(sys.version, sys.platform))
seed()
text = "The quick brown fox jumps over the lazy dog! :d \t+ digits [bonus!!!]: 0123456789\t + others: \xff\x23\xa9\n"
while not text:
text = input("Enter (non empty) text to encrypt: ")
password = "#2minutes2midnite"
while not password:
password = input("Enter (non empty) password to encrypt with: ")
func_pairs = [
(encrypt_dummy0, decrypt_dummy0),
(encrypt_dummy1, decrypt_dummy1),
#(encrypt_zipfile, decrypt_zipfile),
]
for func_pair in func_pairs:
test(text, password, *func_pair)
if __name__ == "__main__":
main()
备注强>:
使用自定义实现的“算法”:
encrypt_dummy0
/ decrypt_dummy0
(encrypt_dummy0
):
xor
([Wikipedia]: Exclusive or)encrypt_dummy1
/ decrypt_dummy1
+
,%
)以确保生成的char位于中[0..255] 范围)我还保留了@StefanPochmann ZipFile
的建议(但它被注释掉了),因为在运行时,尝试从文件中读取(使用错误的密码)会产生相同的(好的)结果
这是我未能仔细 RTFM (正如@Artyer所指出的那样)根据[Python]: ZipFile.setpassword(pwd)
的结果的ZipFile。的 setpassword 强>( PWD )
将 pwd 设置为解压缩加密文件的默认密码。2.6版中的新功能。
test
- 它只是一个包装器:
<强>输出强>:
E:\Work\Dev\StackOverflow\q048480667>"c:\Install\x64\Python\Python\2.7\python.exe" code.py 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:53:40) [MSC v.1500 64 bit (AMD64)] on win32 Text: (96) ['The quick brown fox jumps over the lazy dog! :d \t+ digits [bonus!!!]: 0123456789\t + others: \xff#\xa9\n'] will be encrypted (encrypt_dummy0) with password: (17) [#2minutes2midnite] Encrypted text: (96) ['wZ\x08I\x1f\x00\x1d\x06\x18\x12\x0f\x1b\x0b\x19\x07T\x03LJM\x03\x1b\x18\x04\x16S]\x1b\x0c\x16N\x1d\x1c\x00\x03^\x0c\x13\x17U\x10\n\x14\x13MS\x00N`_EG[\n\x00\x1a\x06T>\x11]\x03\x1c\x17OHU8\x19\x12]X\\F@PE\x05UPmNBT\nWZ\x08\x1b\x1dOT\x9aP\x9bg'] Decrypted (encrypt_dummy0) using password: (17) [#2minutes2midnite]: (96) ['The quick brown fox jumps over the lazy dog! :d \t+ digits [bonus!!!]: 0123456789\t + others: \xff#\xa9\n'] Same as original: True Decrypted (encrypt_dummy0) using password [etindim2setunim2#]: ['\x12.a\'{ip4kw{nepjf )>$m\x7fqi$ 8oyx\'p.#f*e}s<}8gv9&n\'\rmf"/cn~o9\x0cb8wiy&%g\x1b|f468/-b6`!%\x03\'/f)2.auy&9\xa8#\xfe\x13'] Same as original: False Text: (96) ['The quick brown fox jumps over the lazy dog! :d \t+ digits [bonus!!!]: 0123456789\t + others: \xff#\xa9\n'] will be encrypted (encrypt_dummy1) with password: (17) [#2minutes2midnite] Encrypted text: (97) ['R\x86;\x85?:\x08\x06\xf3EB\xf5?-9X;@\xf00;+1GCH\xfd\x04#@3:\x02\x07\xeeH\xfc)?\xf1\x05\xeb\xf5F20JK9\xeb>8\xfe\xff\xf5\xfb@\x02\xfe\xf7I\xee\xeb\x07\x089\x01\xf7\x06H>\x01\xef\x03\x06\xee857\xee?\xf2\x04\xf6\x06\xfa\xfd\x03\xf1\x08\xeb\n4\xf3Eb\xeb'] Decrypted (decrypt_dummy1) using password: (17) [#2minutes2midnite]: (96) ['The quick brown fox jumps over the lazy dog! :d \t+ digits [bonus!!!]: 0123456789\t + others: \xff#\xa9\n'] Same as original: True Decrypted (decrypt_dummy1) using password [etindim2setunim2#]: ['\x12.a\'{ip4kw{nepjf )>$m\x7fqi$ 8oyx\'p.#f*e}s<}8gv9&n\'\rmf"/cn~o9\x0cb8wiy&%g\x1b|f468/-b6`!%\x03\'/f)2.auy&9\xa8#\xfe\x13'] Same as original: False