Python XOR operation - python

I want XOR of characters but getting Type error:
sign value is - \xc5\x06\x92\xd0\x02k=\x91
How do I solve this?
def xor(str1, str2):
print(str1)
print(str2)
for i, j in zip(str1, str2):
value[i] = chr(ord(str[i]) ^ ord(str[j])) # Doing character by character XOR here
return value
user = xor("admin\00\00\00", sig)
print(user)
Getting Error:
Traceback (most recent call last):
File "exploit.py", line 36, in <module>
username2 = xor("rator\00\00\00", signature1)
File "exploit.py", line 32, in xor
value[i] = chr(ord(str[i]) ^ ord(str[j]))
TypeError: 'type' object is not subscriptable

As GZ0 notes, you tried to index str itself (the type), not str1 or str2 (your arguments).
As it happens, you don't need to index at all; you're already iterating the characters themselves, so all you need to do is actually declare value, and use i and j directly:
value = []
for i, j in zip(str1, str2):
value.append(chr(ord(i) ^ ord(j))) # Doing character by character XOR here
return ''.join(value)

This statement chr(ord(str[i]) ^ ord(str[j])) is indexing the built-in function str, causing the error.

value = []
for i, j in zip(str1, str2):
value.append(chr(ord(i) ^ ord(j))) # Doing character by character XOR here
return ''.join(value)
As #ShadowRanger showed above, this worked

Related

Converting a list of tuples into a string

I'm new to run-length coding and need help. I've been given a run-length string of a series of integer followed by characters that include letters/characters.
For example, I have a string:
1-4c8k2)
And I need to convert it into:
-cccckkkkkkkk))
What I've done is convert the run-length string into a list of tuples:
[('1','-'),('4','c'),('8','k'),('2','c')]
And tried creating a function which would convert it into a string however I get a TypeError: can't multiply sequence by non-int of type 'str'.
def decode(lst):
q = ''
for count, character in lst:
q += count * character
return q
I'm trying to think of a way to improve space complexity instead of creating a new list of tuples and more so, trying to resolve this TypeError.
I suspect that what has happened is you forgot to convert the counts into ints:
>>> 3 * 'a'
'aaa'
>>> '3' * 'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't multiply sequence by non-int of type 'str'
>>> int('3') * 'a'
'aaa'
You try through this way :
lst = [('1','-'),('4','c'),('8','k'),('2','c')]
def decode(lst):
q = ''
for count, character in lst:
q += int(count) * character
return q
print(decode(lst))
Output :
-cccckkkkkkkkcc
Check this code here

How to XOR two strings in Python

H, I'm trying to XOR two strings (which should become hex first) in Python.
I know one way will work:
def xor_two_str(str1, str2):
return hex(int(str1,16) ^ int(str2,16))
But I tried sth like this:
def change_to_be_hex(str):
return hex(int(str,base=16))
def xor_two_str(str1,str2):
a = change_to_be_hex(str1)
b = change_to_be_hex(str2)
return hex(a ^ b)
print xor_two_str("12ef","abcd")
This will return TypeError: ^ shouldn't be used between str, str.
I don't know why.
And also this function won't work:
bcd = change_to_be_hex("12ef")
def increment_hex(hex_n):
return hex_n + 1
result = increment_hex(bcd)
print result
The error message is : TypeError: cannot concatenate 'str' and 'int' objects
I feel this is so strange:(
Thank you!
Hi,
The following function is returning the result of hex() which returns a string.
def change_to_be_hex(s):
return hex(int(s,base=16))
You should use the ^ operator on integers.
def change_to_be_hex(s):
return int(s,base=16)
def xor_two_str(str1,str2):
a = change_to_be_hex(str1)
b = change_to_be_hex(str2)
return hex(a ^ b)
print xor_two_str("12ef","abcd")
I'm not sure though that's the result you're looking for. If you want to XOR two strings, it means you want to XOR each character of one string with the character of the other string. You should then XOR ord() value of each char or str1 with ord() value of each char of str2.
def xor_two_str(a,b):
xored = []
for i in range(max(len(a), len(b))):
xored_value = ord(a[i%len(a)]) ^ ord(b[i%len(b)])
xored.append(hex(xored_value)[2:])
return ''.join(xored)
print xor_two_str("12ef","abcd")
Or in one line :
def xor_two_str(a,b):
return ''.join([hex(ord(a[i%len(a)]) ^ ord(b[i%(len(b))]))[2:] for i in range(max(len(a), len(b)))])
print xor_two_str("12ef","abcd")
hex returns a string, so you're trying to xor two strings.
def change_to_be_hex(s):
return int(s,base=16)
Should fix this.
when you initially return hex, like in change_to_be_hex, you explicitly convert it to int. you need to do that throughout your code to add something to it - so, change increment_hex to:
return (int(hex_n) + 1)

Using str.replace to replace letters in a string at different placeholders of the string

I have a problem that I am working on. The goal of the problem is to take the string placeholder i. If i is an even placeholder, replace the letter at i with the letter at i -1. If the i place holder is odd, then replace the letter i with the letter at i +1.
Here is my code so far:
def easyCrypto (s):
for i in range (0,len(s)-1):
if i % 2 == 0:
str(s).replace(i,((i-1)))
if i % 2 != 0:
str(s).replace(i,((i+2)))
print (s)
My error:
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
easyCrypto('abc')
File "C:/Python/cjakobhomework7.py", line 4, in easyCrypto
str(s).replace(i,((i-1)))
TypeError: Can't convert 'int' object to str implicitly
update!!
New code based on answers:
def easyCrypto (s):
for i in range (0,len(s)-1):
if i % 2 == 0:
s = str(s).replace(s(i),(s(i-1)))
else:
s = s.replace(s(i), s(i + 1))
print (s)
However I still have the following errors:
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
easyCrypto('abc')
File "C:/Python/cjakobhomework7.py", line 4, in easyCrypto
s = str(s).replace(s(i),(s(i-1)))
TypeError: 'str' object is not callable
Any ideas? thank you
Use s[i] instead of s(i), and likewise for the other indexes.
There are two things here:
str.replace does not automatically stringify its arguments. You need to manually convert them into strings. Remember that: "Explicit is better than implicit."
str.replace does not work in-place because strings are immutable in Python. You need to reassign s to the new string object returned by str.replace.
Your code should be:
s = s.replace(str(i), str(i-1))
Also, you can replace if i % 2 != 0: with else: since the condition of the second if-statement can only be true if the first is false:
if i % 2 == 0:
s = s.replace(str(i), str(i-1))
else:
s = s.replace(str(i), str(i+1))
Regarding your edited question, you are trying to call the string s as a function by placing parenthesis after it. You need to use square brackets to index the string:
>>> 'abcde'[0]
'a'
>>> 'abcde'[3]
'd'
>>>
In your case it would be:
s = s.replace(s[i], s[i-1])
As a general rule of thumb, parenthesis (...) are for calling functions while square brackets [...] are for indexing sequences/containers.

How to use the strip() function efficiently

Can you please tell me why the strip() function does not work?
str1= 'aaaadfffdswefoijeowji'
def char_freq():
for x in range (0, len(str1)):
sub = str1[x]
print 'the letter',str1[x],'appearence in the sentence=', str1.count(sub, 0,len(str1))
str1.strip(str1[x])
def main():
char_freq()
main()
.strip() is working just fine, but strings are immutable. str.strip() returns the new stripped string:
>>> str1 = 'foofoof'
>>> str1.strip('f')
'oofoo'
>>> str1
'foofoof'
You are ignoring the return value. If you do store the altered string, however, your for loop will run into an IndexError, as the string will be shorter the next iteration:
>>> for x in range (0, len(str1)):
... str1 = str1.strip(str1[x])
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
IndexError: string index out of range
To count strings, don't str.strip(); that just removes characters from the start and end of a string, not in the middle. You could use str.replace(character, '') but that would be inefficient too; but combined with a while loop to avoid the IndexError problem that'd look like:
while str1:
c = str1[0]
print 'the letter {} appearence in the sentence={}'.format(c, str1.count(c))
str1 = str1.replace(c, '')
Much easier would be to just use a collections.Counter() object:
from collections import Counter
freq = Counter(str1)
for character, count in freq.most_common():
print '{} appears {} times'.format(character, count)
Without a dedicated Counter object, you could use a dictionary to count characters instead:
freq = {}
for c in str1:
if c not in freq:
freq[c] = 0
freq[c] += 1
for character, count in freq.items():
print '{} appears {} times'.format(character, count)
where freq then holds character counts after the loop.

Python encoding key, minus one character if too long

Here is my code so far:
def code_block(text, key):
itext = int(text)
rkey = int(key)
res= itext + rkey
def last():
return res[-1:]
if res>=11111111:
last()
return res
Here is the task I've been set:
Now we need a function to take a block of code and a key as input, where both are assumed to be 8 digits long, and encrypts each digit of the number with the corresponding digit of the key:
>>> code_block('12341234','12121212')
'24462446'
>>> code_block('66554433','44556677')
'00000000'
Where am I going wrong? Could you point me in the right direction and indicate me how I was wrong?
You are going about this the wrong way. Treat this character by character:
def code_block(text, key):
res = [str(int(c) + int(k))[-1:] for c, k in zip(text, key)]
return ''.join(res)
which gives me:
>>> code_block('12341234','12121212')
'24462446'
>>> code_block('66554433','44556677')
'00000000'
The code sums each and every character separately, turning it back into a string and only using the last character of the result; 9 + 9 is 18, but the result would be '8'.
Your code would sum the whole numbers, but that would result in:
>>> 66554433 + 44556677
111111110
which is not the correct result. Neither did you ever turn your sum back into a string again, so your code, attempting to treat the sum result as a string by slicing it, gave an exception:
>>> code_block('12341234', '12121212')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 8, in code_block
File "<stdin>", line 6, in last
TypeError: 'int' object has no attribute '__getitem__'

Categories