Python逐字节异或解密

4

我有一个被VB.net程序使用以下函数加密的XOR文件:

Public Class Crypter
    ...
    'This Will convert String to bytes, then call the other function.
    Public Function Crypt(ByVal Data As String) As String
        Return Encoding.Default.GetString(Crypt(Encoding.Default.GetBytes(Data)))
    End Function

    'This calls XorCrypt giving Key converted to bytes
    Public Function Crypt(ByVal Data() As Byte) As Byte()
        Return XorCrypt(Data, Encoding.Default.GetBytes(Me.Key))
    End Function

    'Xor Encryption.
    Private Function XorCrypt(ByVal Data() As Byte, ByVal Key() As Byte) As Byte()
        Dim i As Integer
        If Key.Length <> 0 Then
            For i = 0 To Data.Length - 1
                Data(i) = Data(i) Xor Key(i Mod Key.Length)
            Next
        End If
        Return Data
    End Function
End Class

并以这种方式保存:

Dim Crypter As New Cryptic(Key)
'open destination file
Dim objWriter As New StreamWriter(fileName)
'write crypted content
objWriter.Write(Crypter.Crypt(data))

现在我需要使用Python重新打开文件,但我在获取单个字节方面遇到了麻烦,以下是Python中的XOR函数:

def crypto(self, data):
    'crypto(self, data) -> str'
    return ''.join(chr((ord(x) ^ ord(y)) % 256) \
        for (x, y) in izip(data.decode('utf-8'), cycle(self.key))

由于 x 有时会大于 256,即不是单个字节,因此我必须添加 % 256。

传递两个字节的问题不会破坏解密,因为密钥将与以下数据“配对”。

问题在于转换中某些已解密字符是错误的。 这些字符都是带重音的字母,如 à、è、ì,但是只有少数带重音的字母。 其他字母都恢复正确了。

我猜这可能是由于 256 取模的原因,但如果没有它,我当然会得到 chr 异常...

感谢您的支持


1
我希望你并不真正期望从这里获得实际的安全保障。 - Glenn Maynard
我所需要的只是获取整数数据,以这种方式获取文件会被加密,安全不是我的职责。 - neurino
4个回答

3

你的解码数据似乎包含了值大于256的Unicode字符。在Python 2.x中,chr只能处理小于256的值。使用unichr代替chr,应该可以解决这个问题:

return ''.join(unichr((ord(x) ^ ord(y))) \
    for (x, y) in izip(data.decode('utf-8'), cycle(self.key))

我没有更多的异常,但数据不正确。 在文档中有很多"m²",大部分被还原为"m\xc2\xb2",但有些是"m\xe2\x80\xaa"。 我认为数据已经损坏,但使用VB.net所有的"m²"都被正确还原了。(当然,这也涉及到重音字母:大部分是正确的,有些不是) - neurino

2

使用StreamWriter将混淆数据保存为字符串(即重新编码为默认编码)是否正确?直接保存字节不是更正确吗?或者这两种方法是一样的吗?

Dim objWriter As New StreamWriter(fileName)
objWriter.Write(Crypter.Crypt(data))

StreamWriter.Write调用哪个Crypter.Crypt函数?

这个问题的答案是

Public Function Crypt(ByVal Data() As Byte) As Byte()

这个还是那个?
Public Function Crypt(ByVal Data As String) As String

我不擅长Vb.net...


我运行了这个程序来查看哪些字符涉及到正确/错误的"²"转换

for (x, y) in izip(data.decode('utf-8'), cycle(self.key.decode('utf-8'))):
    if (ord(x) ^ ord(y)) > 255 or chr(ord(x) ^ ord(y)) == '\xb2':
        print (x, y, chr((ord(x) ^ ord(y)) % 256),
               unichr(ord(x) ^ ord(y)), ord(x), ord(y))

我收到了这个信息:
ù K ² ² 249 75
 p ² ² 194 112
Æ t ² ² 198 116
‚ 0 * ‪ 8218 48

最后一段是错误的,因为使用了双字节...但如果只传递一个可能会导致其余解密结果失步

如果数据类型为字符串,则使用 Crypt 的第一个重载(但其实现是不正确的,正如我所回答的那样)。如果数据类型为 Byte(),则使用第二个重载。如果它是其他类型,则取决于数据是否可以隐式转换为 String 或 Byte()。 - Damien_The_Unbeliever

1

如果您以文本模式打开文件,则可能会将其解释为Unicode文本。尝试以二进制模式打开它,以将所有字符转换为字节。这应该可以避免您在使用chr时遇到的问题。如果您正在使用Python 3.x,请记住,在二进制模式下工作时,应使用字节文字而不是字符串文字,后者是按设计进行的Unicode字符串。


我在Python 2.5中以'rb'模式打开文件,但不得不添加data.decode('utf-8'),即使这样似乎仍然无法逐个获取字节。 - neurino

1

事实上,以下这行是错误的:

Return Encoding.Default.GetString(Crypt(Encoding.Default.GetBytes(Data)))

不能保证从 Crypt 返回的字节是有效的字符串解码。最好使用 Convert.ToBase64String,然后将 字符串传递到您的 Python 代码中(显然,您需要能够对字节进行 Base-64 解码)。

正如其他人指出的那样,异或提供的安全级别足以保护您的数据免受您的妹妹之类的人的侵害。


谢谢你,你几乎是正确的。VB.net函数并不完全是我发布的那个,它使用一个函数来生成“正256模”以“防止非字节值。结果始终>=0且<=255”。将vb.net代码中的所有反字符串转换删除,并直接保存为Byte到文件中,我已经让Python正确读取了字符。我已经接近解决方案。正如我已经回答过的,这不是我的异或加密想法,如果有人能够破解它并造成一些伤害,我会很感激,因为我正在透露它,但没有人在意... <_< - neurino

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接