Python byte per byte XOR decryption
I have an XOR encypted file by a VB.net program using this function to scramble:
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
and saved this way:
Dim Crypter As New Cryptic(Key)
'open destination file
Dim objWriter As New StreamW开发者_如何学编程riter(fileName)
'write crypted content
objWriter.Write(Crypter.Crypt(data))
Now I have to reopen the file with Python but I have troubles getting single bytes, this is the XOR function in python:
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))
I had to add the % 256 since sometimes x is > 256 i.e. not a single byte.
This thing of two bytes being passed does not break the decryption because the key keeps "paired" with the following data.
The problem is some decrypted character in the conversion is wrong. These chars are all accented letters like à, è, ì but just a few of the overall accented letters. The others are all correctly restored.
I guess it could be due to the 256 mod but without it I of course get a chr exception...
Thanks for your support
Your decoded data appears to contain unicode characters with values above 256. In Python 2.x chr
can only handle values below 256. Use unichr
instead of chr
and it should work:
return ''.join(unichr((ord(x) ^ ord(y))) \
for (x, y) in izip(data.decode('utf-8'), cycle(self.key))
is it correct to save scrambled data as string (i.e. re-encoded with default encoding) with StreamWriter? Wouldn't be correct to save bytes directly? Or is it the same thing?
Dim objWriter As New StreamWriter(fileName)
objWriter.Write(Crypter.Crypt(data))
Which Crypter.Crypt is called by StreamWriter.Write?
This
Public Function Crypt(ByVal Data() As Byte) As Byte()
or this?
Public Function Crypt(ByVal Data As String) As String
I'm not handy with Vb.net...
I've run this to get what chars are involved in the right/wrong "²" conversion
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))
I got this:
ù K ² ² 249 75
 p ² ² 194 112
Æ t ² ² 198 116
‚ 0 * 8218 48
the last one is wrong because a double byte is used... but if just one would be passed probably the rest of the decryption would result outh of phase
Indeed, the following line is wrong:
Return Encoding.Default.GetString(Crypt(Encoding.Default.GetBytes(Data)))
There's no general guarantee that the bytes being returned from Crypt are valid to decode as a string. You'd be better using Convert.ToBase64String, and then passing that string to your Python code (where obviously, you'd need to be able to Base-64 decode the bytes.
And as others have pointed out, the level of security XORing provides is adequate to protect your data from, maybe, your little sister.
If you're opening the file in text mode, it might be interpreted as Unicode text. Try opening it in binary mode to make all characters into bytes. That should avoid your issues with chr
. If you're using Python 3.x, do remember that when working in binary mode you should be using bytes literals rather than string literals, the latter of which are Unicode strings by design.
精彩评论