使用密码加密字符串,无需外部模块

时间:2018-01-27 21:18:13

标签: python encryption

我希望在Python中加密字符串(使用密码或密钥),而无需安装任何模块。我可以使用下载Python(2.7)时包含的默认模块,但是我无法安装像PyCrypto这样的东西。

我已经尝试过查看Simple way to encode a string according to a password?,但Base64的答案看起来并不安全,而其他人则需要外部模块。有人可以提供任何帮助吗?我没有任何代码可以展示,因为我还没有找到任何可以尝试的东西。

1 个答案:

答案 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_dummy0encrypt_dummy0):
    • encrypt_dummy1 / decrypt_dummy1
      1. 封装以前的 algo
      2. 向每个char添加一个额外的随机数(加密常量)(完成一些环绕特定操作(+%)以确保生成的char位于中[0..255] 范围)
      3. 撤消结果
      4. 将随机数存储在字符串的末尾(待恢复并用于解密)
      5. 正如预期的那样,解密以相反的顺序完成相同的事情
    • 我还保留了@StefanPochmann ZipFile的建议(但它被注释掉了),因为在运行时,尝试从文件中读取(使用错误的密码)会产生相同的(好的)结果

      • 这是我未能仔细 RTFM (正如@Artyer所指出的那样)根据[Python]: ZipFile.setpassword(pwd)

        的结果
          

        的ZipFile。的 setpassword PWD
          将 pwd 设置为解压缩加密文件的默认密码。

             

        2.6版中的新功能。

  • test - 它只是一个包装器:

    1. 使用密码加密文本:在1 st 和2 nd args上调用加密函数(3 rd arg)
    2. 尝试使用相同的密码解密(先前)加密的文本:在上一步的结果上调用解密函数(4 th arg)和2 nd arg < / LI>
    3. 尝试使用反向密码解密(先前)加密文本:在上一步和2 的结果上调用解密函数(4 th arg) nd arg颠倒了
  • 程序可以无限期地重复(至少受到计算能力的限制),但最终它是一个 matryoska娃娃(матрёшка,IPA) - 可以递归打开。

<强>输出

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