I'm failry new to cryptography and programming as a whole ( mabey a few months) and i started the cryptopal challenges. I got the first 2 done correctly with alot of reading into how to convert things in python.
I'm getting stuck on the code for the 3rd one, "Single-Byte XOR" where they give you a hex string and tell you to write a program to find the key they used to XOR the string.
I am aware of how i would go about doing this (without looking solutions):
1) convert the string to binary
2) loop through all character values XORing them individually with the given ciphertext
3) checking these XORd results to see which one looks "the most english"
I guess im just confused on the way bytes behave in python.
here is my code:
my_ciphertext = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736"
binary_rep_of_ciphertext = binascii.unhexlify(my_ciphertext)
array_of_ciphertext = bytearray(binary_rep_of_ciphertext)
def xor_string_and_char(my_char_value):
result = array_of_ciphertext ^ my_char_value
return '{:x}'.format(result) # convert back to hexadecimal
x = 0
assert x==0
while x in range(255):
my_plaintext = xor_string_and_char(x)
print('b' + my_plaintext)
x=x+1
Related
I'm fairly new to Python,
I'm trying to check if the user input can be checked in a range of integers
The following is the code I have already written
#LL DD LLL
#where L is a letter
#where D is a digit
#eg SG 61 ABC
area_codes = ["SG", "PV", "LJ", "EX"]
reg = input("Enter registration: ")
if reg[0:2] in area_codes:
print(reg[0:2])
if reg[2:3] in range(0,18):
print(reg[2:3])
else:
print("nope")
And this is the response I am given,
Enter registration: SG15
SG
nope
How do I check this properly?
I have tried a few things but I don't even know if this is possible.
Thank you in advance,
Donberry.
reg[2:3] is a slice of your input string. So it's a number, but stored as string.
When you do:
if reg[2:3] in range(0,18):
you're checking if the string in contained in the range object (python 3) or list object (python 2) which contains integers. So the test fails every time.
Had you done
if 0 <= reg[2:3] < 18:
you'd have gotten an explicit error in python 3. Besides, it avoids to build a range or list object just for the sake of testing. Chained comparison like this is way faster.
So I'm suggesting:
if 0 <= int(reg[2:3]) < 18:
You should convert the string to an integer before checking it's in the range. Also, (and I don't know if you did this), but you should verify that you want numbers between 0 and 17, which is what your code does.
That is, range(0, 18) - equivalent to range(18), by the way - generates the list of numbers starting at 0 and ending at 17, including both 0 and 17.
Anyway, you would check it like this:
if int(reg[2:3]) in range(0,18):
print(reg[2:3])
I am trying to write an RSA code in python3. I need to turn user input strings (containing any characters, not only numbers) into integers to then encrypt them. What is the best way to turn a sting into an integer in Python 3.6 without 3-rd party modules?
how to encode a string to an integer is far from unique... there are many ways! this is one of them:
strg = 'user input'
i = int.from_bytes(strg.encode('utf-8'), byteorder='big')
the conversion in the other direction then is:
s = int.to_bytes(i, length=len(strg), byteorder='big').decode('utf-8')
and yes, you need to know the length of the resulting string before converting back. if length is too large, the string will be padded with chr(0) from the left (with byteorder='big'); if length is too small, int.to_bytes will raise an OverflowError: int too big to convert.
The #hiro protagonist's answer requires to know the length of the string. So I tried to find another solution and good answers here: Python3 convert Unicode String to int representation. I just summary here my favourite solutions:
def str2num(string):
return int(binascii.hexlify(string.encode("utf-8")), 16)
def num2str(number):
return binascii.unhexlify(format(number, "x").encode("utf-8")).decode("utf-8")
def numfy(s, max_code=0x110000):
# 0x110000 is max value of unicode character
number = 0
for e in [ord(c) for c in s]:
number = (number * max_code) + e
return number
def denumfy(number, max_code=0x110000):
l = []
while number != 0:
l.append(chr(number % max_code))
number = number // max_code
return ''.join(reversed(l))
Intersting: testing some cases shows me that
str2num(s) = numfy(s, max_code=256) if ord(s[i]) < 128
and
str2num(s) = int.from_bytes(s.encode('utf-8'), byteorder='big') (#hiro protagonist's answer)
I have a simple question that I need help on. My code,I believe, is almost complete but im having trouble with the a specific line of code.
I have an assignment question (2 parts) that asks me to find whether a protein (string), has the specified motif (substring) at that particular location (location). This is the first part, and the function and code looks like this:
function output = Motif_Match(motif,protein,location)
%This code wil print a '1' if the motif occurs in the protein starting
at the given location, else it wil print a '0'
for k = 1:location %Iterates through specified location
if protein(1, [k, k+1]) == motif; % if the location matches the protein and motif
output = 1;
else
output = 0;
end
end
This part I was able to get correctly, and example of this is as follows:
p = 'MGNAAAAKKGN'
m = 'GN'
Motif_Match(m,p,2)
ans =
1
The second part of the question, which I am stuck on, is to take the motif and protein and return a vector containing the locations at which the motif occurs in the protein. To do this, I am using calls to my previous code and I am not supposed to use any functions that make this easy such as strfind, find, hist, strcmp etc.
My code for this, so far, is:
function output = Motif_Find(motif,protein)
[r,c] = size(protein)
output = zeros(r,c)
for k = 1:c-1
if Motif_Match(motif,protein,k) == 1;
output(k) = protein(k)
else
output = [];
end
end
I belive something is wrong at line 6 of this code. My thinking on this is that I want the output to give me the locations to me and that this code on this line is incorrect, but I can't seem to think of anything else. An example of what should happen is as follows:
p = 'MGNAAAAKKGN';
m = 'GN';
Motif_Find(m,p)
ans =
2 10
So my question is, how can I get my code to give me the locations? I've been stuck on this for quite a while and can't seem to get anywhere with this. Any help will be greatly appreciated!
Thank you all!
you are very close.
output(k) = protein(k)
should be
output(k) = k
This is because we want just the location K of the match. Using protien(k) will gives us the character at position K in the protein string.
Also the very last thing I would do is only return the nonzero elements. The easiest way is to just use the find command with no arguments besides the vector/matrix
so after your loop just do this
output = find(output); %returns only non zero elements
edit
I just noticed another problem output = []; means set output to an empty array. this isn't what you want i think what you meant was output(k) = 0; this is why you weren't getting the result you expected. But REALLY since you already made the whole array zeros, you don't need that at all. all together, the code should look like this. I also replaced your size with length since your proteins are linear sequences, not 2d matricies
function output = Motif_Find(motif,protein)
protein_len = length(protein)
motif_len = length(motif)
output = zeros(1,protein_len)
%notice here I changed this to motif_length. think of it this way, if the
%length is 4, we don't need to search the last 3,2,or 1 protein groups
for k = 1:protein_len-motif_len + 1
if Motif_Match(motif,protein,k) == 1;
output(k) = k;
%we don't really need these lines, since the array already has zeros
%else
% output(k) = 0;
end
end
%returns only nonzero elements
output = find(output);
For a Python 3 programming assignment I have to work with Huffman coding. It's simple enough to generate the correct codes which result in a long string of 0's and 1's.
Now my problem is actually writings this string of as binary and not as text. I attempted to do this:
result = "01010101 ... " #really long string of 0's and 1's
filewrt = open(output_file, "wb") #appending b to w should write as binary, should it not?
filewrt.write(result)
filewrt.close()
however I'm still geting a large text file of 0 and 1 characters. How do I fix this?
EDIT: It seems as if I just simply don't understand how to represent an arbitrary bit in Python 3.
Based on this SO question I devised this ugly monstrosity:
for char in result:
filewrt.write( bytes(int(char, 2)) )
Instead of getting anywhere close to working, it outputted a zero'd file that was twice as large as my input file. Can someone please explain to me how to represent binary arbitrarily? And in the context of creating a huffman tree, how do I go about concatinating or joining bits based on their leaf locations if I should not use a string to do so.
def intToTextBytes(n, stLen=0):
bs = b''
while n>0:
bs = bytes([n & 0xff]) + bs
n >>= 8
return bs.rjust(stLen, b'\x00')
num = 0b01010101111111111111110000000000000011111111111111
bs = intToTextBytes(num)
print(bs)
open(output_file, "wb").write(bs)
EDIT: A more complicated, but faster (about 3 times) way:
from math import log, ceil
intToTextBytes = lambda n, stLen=0: bytes([
(n >> (i<<3)) & 0xff for i in range(int(ceil(log(n, 256)))-1, -1, -1)
]).rjust(stLen, b'\x00')
I am trying to create a function that will use brute force for an academic python project. The password can be limited I want to pass in the password and the function iterate through a set of characters(a-z,A-Z,0-9) trying combinations till the password is found. I know this will be inefficient so for testing lets assume the password is 4 characters long. Any help getting started on writing this function would be appreciated.
gen = itertools.combinations_with_replacement(characters,password_length) #1
for password in gen: #2
check_password(password) #3
here's how it works:
line 1: this creates a generator. it's like a function that remembers where it left off. Check this out for more info: http://getpython3.com/diveintopython3/generators.html. This particular generator goes through all possible combinations of the given characters of the given length.
line 2: for each iteration of the for loop next(gen) is called. This yields the next value
line 3: Do what you need to do
for example if characters = '01234567890' and password_length = 2 then the loop will run through the combinations: ('0','0'), ('0','1'), ('0','2')...('0','9'),('1','0'),('1','1')...('9','9').
For a pre-known length :
import random
a_z = "abcdefghijklmnopqrstuvwxyz_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
while password != curtry:
currenttry = random.choice(a_z)+random.choice(a_z)+random.choice(a_z)+random.choice(a_z)
For a random length :
import random
a_z = "abcdefghijklmnopqrstuvwxyz_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
while password != curtry:
leng = random.randint(4,12) #random int between 4 and 12
i = 0
curtry = "lol"
for i<leng:
curtry += random.choice(a_z)