This question already has answers here:
XOR Python Text Encryption/Decryption
(4 answers)
Closed 8 years ago.
I know there is a built in xor operator that can be imported in Python. I'm trying to execute the xor encryption/decryption. So far I have:
def xor_attmpt():
message = raw_input("Enter message to be ciphered: ")
cipher = []
for i in message:
cipher.append(bin(ord(i))[2::])#add the conversion of the letters/characters
#in your message from ascii to binary withoout the 0b in the front to your ciphered message list
cipher = "".join(cipher)
privvyKey = raw_input("Enter the private key: ")
keydecrypt = []
for j in privvyKey:
keydecrypt.append(bin(ord(j))[2::]) #same
keydecrypt = "".join(keydecrypt )#same
print "key is '{0}'" .format(keydecrypt) #substitute values in string
print "encrypted text is '{0}'" .format(cipher)
from operator import xor
for letter in message:
print xor(bool(cipher), bool(keydecrypt))
This:
> for letter in message:
print xor(bool(cipher), bool(keydecrypt))
is where my python starts to go wrong.
The ouput looks like this
Enter message to be ciphered: hello
Enter the private key: \#154>
key is '10111001000000110001110101110100111110'
encrypted text is '11010001100101110110011011001101111'
False
False
False
False
False
What I'm messing up on is trying to get these two binary(key and encrypted) to be compared and give true(1) or false(being 0). The xor should then give me a resulting 1 and 0 binary list from comparing the two. Any input?
The bool() constructor converts any value into either True or False. Since you are passing it a non-empty string in each case bool(cipher) and bool(keydecrypt) each just convert to True and xor(True,True) is `False.
Forget about converting to a string of 0 and 1, all you actually need to do is xor the character codes you get from calling ord() and then convert back to a character with chr(). also, you don't need to import a function, Python has a perfectly functional xor operator ^.
Something like this ought to work:
import itertools
print(''.join(chr(ord(k)^ord(c)) for c,k in zip(cipher,itertools.cycle(keydecrypt))))
You made some mistakes:
cipher and keydecrypt are not binary, they are strings containing 0 and 1 characters.
There is no need to import xor function, you already have the xor operator ^
Converting a string to boolean in python will get you False if string == '' and True in every other case, which is not what you want.
I didn't understand what the last for is supposed to do.
Here is an example about how you could improve you code:
import itertools
import binascii
encrypted = ''
for m, k in itertools.izip(message, itertools.cycle(key)):
encrypted += chr(ord(m) ^ ord(k))
print binascii.hexlify(encrypted)
This would work also if key is smaller than message.
Related
This question already has an answer here:
How can I concatenate str and int objects?
(1 answer)
Closed 1 year ago.
I'm studying python. And I'm a beginner.
Reading a book, I came to look at this code.
for num in range(101):
print('Hello ('+str(num)+')')
num = num + 1
It's the result of this code...
Hello (0)
Hello (1)
Hello (2)
.
.
.
Hello (99)
Hello (100)
Is the code below necessary?
print('Hello ('+str(num)+')')
I don't understand why there's +str(num)+.
You can't add an int (or a numeric) to a string. Thus, once you print a string (here 'Hello'), you only can add a string (or a char) to that word, so you use str(num) to convert num to a string.
num = 3
'Hello' + str(num) => 'Hello 3'
The function str() transforms num into a string. Then, the strings are concatenated using the + operator, and then printed.
A modern and elegant way to do this would be to use f-strings:
for num in range(101):
print(f'Hello ({num})')
will produce the same result.
Side-note : you do not need to do num = num + 1 : num is already automatically incremented in the for loop.
Python, internally, keeps track of your types, which means that the types you use are tracked by python itself without you needing to explicitly declare them. What you are doing by using print('Hello ('+str(num)+')') is saying to the computer: "print on the screen the following value";
but since there is no sum operation between strings and numbers, you need to convert your number into a string, which is what you are doing by using str(num).
This constructs for you a string from the given number; so what you are doing is practically making the value 3 as a number become the value '3' as a string;
then the previous line of code, when num == 3, is equivalent to:
print('Hello (' + '3' + ')' )
which of course now is about a bunch of operations between strings, that are now accepted; here is some more information about python's types handling.
Also, check the answer by Louis-Justin Tallot which provides a solution using f-strings (where f stands for format) that allows you to use the f'{variableName}' syntax, evaluating the value between the curly brackets directly to a string.
The original encryption is as follows (which i've already done):
For every letter in the key and every letter in the plaintext ( they are the same length) you compute the ascii values, find the XOR result, convert that to decimal, add 32 to that value and then convert back to char. The char would be the ciphertext. .
key = this is a cool key
plaintext = Wonderland is cool
ciphertext= C''7e;?a/dc&<lc$*5
def decryption(ciphertext,key):
plaintext = ""
for k in range(len(ciphertext)):
i = ciphertext[k]
j = key[k]
val = xor_calc(chr(ord(i)-32), chr(ord(j)-32))
val = chr(ord(xor)+ 32)
plaintext += val
after decryption im getting:
onderland is cool
obviously should match the original plaintext, additionally with other ciphers and keys im missing letters. My encryption works fine though, as my answers match what the results should be. Any help would be appreciated!
Forgot to mention i have a function xor_calc that takes the cipher and key letters, converts to ascii and computes the XOR results and returns back to char
Simplifying you calculation of xor worked for me:
xor = chr((ord(i)-32) ^ (ord(j)-32) + 32)
In fact, if I run decryption(plaintext,key), I get your ciphertext; if run decryption(ciphertext,key), I get your plaintext. (This makes sense, since xor is reversible.)
I'm trying to solve this challenge and having some trouble. First, I'm not super familiar with XOR. I understand that XOR is symmetric so all I need to do to decrypt this string is encrypt it again with the same key, which I have.
I don't want an answer handed to me, so if possible can someone assist with kickstarting my brain with some pseudocode on how you would create a Python script to take a users input, and decrypt their XOR encrypted string?
Let me explain it this way.
XOR table
=========
0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0
So, imagine a binary number
10110011
And, you have a key
11001100
If you XOR them you get:
01111111
With me? Now, XOR the encrypted number with the key, and you return back to original.
10110011
Here is some pseudo-code as well for this. It is a heavy to demonstrate the work.
Get the input-string from user
Get the encrypt-key from user #Assume it is also a string;
Loop through the input-string character by character
Convert character to its binary representation as a string
Concatenate that to input-string-converted-to-binary string
Loop through the encrypt-key character by character
Convert character to its binary representation as a string
Concatenate that to encrypt-key-converted-to-binary string
Get the length of the encrypt-key-converted-to-binary string
Calculate totalloops by dividing that into the length of the input-string-converted-to-binary string
Loop for totalloops
Loop for each character in the subsection of the input-string-converted-to-binary string
Calculate XOR of the digit
Concatenate into encrypted-value string
You now have the binary string. You can reverse the process of converting the binary string into characters. But, you may get unprintable characters, which is why doing it the long way gives you more to inspect.
user_number = input("Enter your number")
if( user_number. isdigit()):
print("User input is Number ")
else:
print("User input is string ")
because its two inputs cannot be unambiguously reconstructed
from its single output.
I am creating a method in Python whereby it will take a number which will form a byte string that will then get sent to the Arduino. However whenever I try, the escape character is always included in the final byte string.
Here is the snippet of the code I am using:
num = 5
my_str = '\\x4' + str(num)
my_str.encode('utf-8')
Result:
b'\\x45'
I tried another method:
num2 = 5
byte1 = b'\\x4'
byte2 = bytes(str(num2), 'ISO-8859-1')
new_byte = byte1 + byte2
new_byte
Result:
b'\\x45'
Trying yet in a different way:
num = 5
u = chr(92) + 'x4' + str(num)
u.encode('ISO-8859-1')
Result:
b'\\x45'
I would like to get the byte string to be b'\x45' without the escape character but not really sure what I have missed. I will appreciate any pointers on how I can achieve this.
Your problem is that you have already escaped the backslash. It is not recommended to construct a literal using an unknown variable, especially if there's a simpler way, which there is:
def make_into_bytes(n):
return bytes([64 + n])
print(make_into_bytes(5))
This outputs
b'E'
Note that this isn't a bug, as this is simply the value of 0x45:
>>> b'\x45'
b'E'
The way this function works is basically just doing it by hand. Prepending '4' to a hex string (of length 1) is the same as adding 4 * 16 to it, which is 64. I then construct a bytes object out of this. Note that I assume n is an integer, as in your code. If n should be a digit like 'a', this would be the integer 10.
If you want it to work on hex digits, rather than on integer digits, you would need to change it to this:
def make_into_bytes(n):
return bytes([64 + int(n, 16)])
print(make_into_bytes('5'))
print(make_into_bytes('a'))
with output
b'E'
b'J'
This quite simply converts the digit from base 16 first.
You can use the built-in function chr() to convert an integer to the corresponding character:
>>> chr(0x40 + 5)
'E'
Alternatively, if you just one to get the n-th letter of the alphabet, it might be more readable to use str.ascii_uppercase
>>> string.ascii_uppercase[5 - 1]
'E'
Note that the results in this answer are strings in Python 3, not bytes objects. Simply calling .encode() on them will convert them to bytes.
I'm looking for a way to "append '1' bit to message" in Python, in order to recreate the MD5 algorithm mentioned here.
This is what I've done, but the problem is that msg is actually a string:
msg.append(0x01)
while len(msg)%56!=0:
msg.append(0x00)
What should I do?
use chr to convert the byte values to strings. Then you can append them to msg.
msg += chr(0x01 << 8)
while len(msg)%56 != 0:
msg += chr(0x00)
In Python 2.7, each character in an ASCII string is 8 bits large. So with this method, you're not truly adding "1 bit" each time. That's why it's necessary to left-shift the 1 argument eight times. Otherwise you would be adding 0b00000001 to the string instead of the desired 0b10000000.