Python逐字节XOR解密

4 投票
4 回答
4869 浏览
提问于 2025-04-15 22:34

我有一个用VB.net程序加密的文件,使用了这个函数来进行混淆:

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))

我不得不加上% 256,因为有时候x会大于256,也就是说不是单个字节

传递两个字节并不会破坏解密,因为密钥会和后面的数据“配对”在一起。

问题是,有些解密后的字符转换得不对。这些字符都是带重音的字母,比如à、è、ì,但只是少数几个带重音的字母。其他的都恢复得很好。

我猜这可能和256的取模有关,但如果不加的话,我当然会遇到字符异常...

谢谢你的支持

4 个回答

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

最后一个是错的,因为用了双字节...但如果只传一个的话,可能解密的其余部分会导致不同步

3

你解码的数据似乎包含了一些unicode字符,它们的值超过了256。在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))
1

确实,下面这行代码是错的:

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

没有什么保证说从Crypt返回的字节可以直接解码成字符串。你最好使用Convert.ToBase64String,然后把这个字符串传给你的Python代码(当然,你需要能够对这些字节进行Base-64解码)。

而且正如其他人提到的,XOR加密提供的安全性可能只够保护你的数据不被你的小妹妹看到。

撰写回答