XOR加密工作*大多数时间*

时间:2011-06-06 23:32:56

标签: python encryption xor

我的任务是密码保护Java应用程序,而对真正的安全性的关注最少。因此,在文本文件中存储用户名/密码对然后加密它似乎是明智的。对于加密,使用XOR密码似乎是合适的,因为它们简单快速(记住 - 它只是不鼓励临时用户,而不是防弹)。

我编写了所有相应的Java,然后意识到我需要一种方法来加密配置文件。我写了一个额外的方法,但使用超过一次或两次(并且似乎仅适用于某些输入)是笨重的,所以我认为最好用Python编写一些内容,以便在REPL中播放。

这就是我最终的结果:

from itertools import izip, cycle

KEY = "stackoverflow"

def encrypt(text):
    return ''.join(chr(ord(x) ^ ord(y)) for (x,y) in izip(text,cycle(KEY)))

def decrypt(text):
    return encrypt(text)

def export(users, file):
    with open(file, "w") as f:
        for user, password in users.items():
            f.write(encrypt('"%s" "%s"'%(user, password)) + "\n")

def import_data(file):
    with open(file) as f:
        return [decrypt(i) for i in f.readlines()]

从表面上看,它有效:

>>> x = encrypt("Hello world!")
>>> x
';\x11\r\x0f\x04O\x01\n\x00\n\x08N'
>>> decrypt(x)
'Hello world!'

但事情开始分崩离析:

>>> export({"foo" : "bar", "baz" : "quux", "spam" : "eggs"}, "users.dat")
>>> import_data("users.dat")
['"foo" "bar"e', '"baz" "quux"}', '"spam" "eggs"y']

以下是vim如何读取它 -

Vim rendition

然后:

>>> export({"what" : "not", "this" : "that", "admin_istrator" : "quux"}, "users2.dat")
>>> import_data("users2.dat")
['"thi', "k97$ma{~'l", '"what" "not"}', '"admin_istrator" "quux', '7~']

的Vim:

Vim rendition of the second set

我想到我可能遇到一个字符的加密形式是换行符的问题,但据我所知,这并不能解释第一个例子中的古怪行为或 all 在第二个中古怪的行为。

关于换行符,我的B计划是加密整个文件 - 换行符和全部 - 然后将其重新填充,解密,将其拆分为“\ n”,然后继续进行基于行的解析。

提前致谢。


更新:这是我对B计划的实施(前两段描述)。

def import2(file):
    with open(file) as f:
        return decrypt(f.read())

然后:

>>> export({"foo" : "bar", "this" : "that", "admin_istrator" : "letmein"}, "users2.dat")
>>> import2("users2.dat")
'"this" "that"y%smg&91uux!}"admin_istrator" "letmein"y'

更新二:二进制。

[代码与上述相同,只是所有open都是open(file, "rb")open(file, "wb")。]

>>> export({"foo" : "bar", "this" : "that", "admin_istrator" : "letmein"}, "users2.dat")
>>> import2("users2.dat")
'"this" "that"y%smg&91uux!}"admin_istrator" "letmein"y'
>>> import_data("users2.dat")
['"t', "k97$ma{~'", '"foo" "bar"', '"admin_istrator" "letmein"']

最终更新:Base 64,其他恶作剧。

def import2(file):
    with open(file, "rb") as f:
        return filter(str.strip, [decrypt(i) for i in f.readlines()])

其中encryptdecrypt encode位于/ decode base 64。

3 个答案:

答案 0 :(得分:1)

您正在尝试将二进制文件存储在文本模式文件中。使用open(file, "wb")进行写入,使用open(file, "rb")进行阅读,以二进制模式打开文件并解决问题。

在文本模式下,每个"\r""\n""\r\n"序列都被视为换行符,因此它们会转换为您的本地操作系统行结束约定("\r\n" for Windows,{ {1}}用于Unix,"\n"用于旧Mac)。如果您从文本文件中读取它们,您将始终获得"\r",如果您编写它们,我不记得实际行为,但您肯定会弄乱而不是数据:)

使用XOR加密,很可能会遇到这种情况:)

如果您被迫使用二进制文件,请尝试使用base64编码(例如"\n")。解码使用"some\0te\n\nxt with bi\x01naries".encode('base64')(谢谢,船长明显!)。

答案 1 :(得分:0)

问题是你没有读取你编纂的相同数据(在加密后添加'\ n'),只需对你读过的数据做一个rstrip():

  def import_data(file):
    with open(file) as f:
       return [decrypt(i.rstrip()) for i in f.readlines()]

答案 2 :(得分:0)

您可以通过加密换行符来修复它,而不是在行之间重置键

from itertools import izip, cycle

KEY = "stackoverflow"

def encrypt(text):
    return ''.join(chr(ord(x) ^ ord(y)) for (x,y) in izip(text,key))

def decrypt(text):
    return encrypt(text)

def export(users, file):
    with open(file, "w") as f:
        for user, password in users.items():
            f.write(encrypt('"%s" "%s"\n'%(user, password)))

def import_data(file):
    with open(file) as f:
        return [decrypt(i) for i in f]


key = cycle(KEY)
export({"foo" : "bar", "baz" : "quux", "spam" : "eggs"}, "users.dat")

key = cycle(KEY)
for row in import_data("users.dat"):
    print row

这应该变成一个类,key将是一个实例变量而不是全局,因为它在这里