How to use a variable as an attribute in python - python

I wanted to write a Python script to bruteforce hashes that permits the user to insert the hashing algorithm as a string (Result: algorithm = "md5"), but when I tried to use it like this in the hashlib library: guess_hash = hashlib.algorithm(bytes(guess)).hexdigest(), it obviously gave me this error: AttributeError: module 'hashlib' has no attribute 'algorithm'
So I did a quick research and I tried using getattr like this: getattr(hashlib,guess(bytes(guess1))).hexdigest() (probably really wrong) and it gave me this error: TypeError: string argument without an encoding.
What should I do? Thanks in advance and sorry for the noobiness :)

You missed passing the actual algorithm name to the getattr call.
Try this:
getattr(hashlib, 'md5')(bytes(guess)).hexdigest()

That's actually bytes complaining (which it will with Python 3 but not Python 2). It would appear that you've also swapped the meanings of algorithm and guess in your getattr, and you'll want to do something like
getattr(hashlib, algorithm)(bytes(guess, 'utf-8')).hexdigest()

Simple is better than complex. You can just have a bunch of if statements and do the correct call in those. If there are too many, you could use a hashmap where the key is a string and the value a function.
getattr is, however, the correct call to fetch an attribute with a variable, but the error tells you that you cannot convert a string to a bytestring without specifying the encoding. The bytes function allows you to specify encoding like this:
a_byte_string = bytes(a_regular_string, encoding='utf8')

Related

Concatenate string to dictionary path when using print in Python

I want to create a variable such as 'path' and use it to get the same result when getting data from the dictionary. Is this concatenation possible by doing some type of conversions?
print(dict['detect'][1]['ssh'][0]['Server']) #Result
path = "['ssh'][0]['Server']"
print(dict['detect'][1]{path}) #...should give same result
To answer your immediate question, you can use eval() to treat the string data as code:
print(eval(f"dict['detect'][1]{path}")
That being said, be very careful when using eval(), as it introduces major security risks. I don't see a way to use ast.literal_eval() here, so if at all possible I would suggest avoiding this appoach entirely.

Can I use integers to use a unicode in python?

I have a slight problem that may be unsolvable in python.
Can you use an integer variable to type unicode in python? For example, let's say you have a variable: `variable = 0041`. Can you do something like (without having to manually type it) get `\u0041` (`a`)?
I have not really tried anything because nothing comes to mind when I try to solve this problem. If there is a possible solution, what is it?
Sorry if the answer is painfully obvious or I did not provide enough information, I'm new to this.
This is what the chr function is for.
>>> chr(int('0041', 16))
'A'

Writing unicode symbols to files (as opposed to unicode code)

I'm new to python and unicode is starting to give me headaches.
Currently I write to file like this:
my_string = "马/馬"
f = codecs.open(local_filepath, encoding='utf-8', mode='w+')
f.write(my_string)
f.close()
And when I open file with i.e. Gedit, I can see something like this:
\u9a6c/\u99ac\tm\u01ce
While I'd like to see exactly what I've written:
马/馬
I've tried a few different variations, like writing my_string.decode() or my_string.encode('utf-8') instead of just my_string, I know those two methods are the opposites but I was not sure which one I needed. Neither worked anyway.
If I manually write these symbols to text file, then with python read the file, re-write what I've just read back to the same file and save, symbols get turned to the code \u9a6c. Not sure if this is importat, figured I'd just mention it to help identify the problem.
Edit: the strings came from SQL Alchemy objects repr method, which turned out to be where the problem lied. I didn't mention it because it just didn't occur to me it can be related to the problem somehow. Thanks again for your help!
From the comments it is now clear you are using either the repr() function or calling the object.__repr__() method directly.
Don't do that. You are writing debugging information to your file:
>>> my_string = u"马/馬"
>>> print repr(my_string)
u'\u9a6c/\u99ac'
The value produced is meant to be pastable back into a Python session so you can re-produce the exact same value, and as such it is ASCII-safe (so it can be used in Python 2 source code without encoding issues).
From the repr() documentation:
For many types, this function makes an attempt to return a string that would yield an object with the same value when passed to eval(), otherwise the representation is a string enclosed in angle brackets that contains the name of the type of the object together with additional information often including the name and address of the object.
Write the Unicode objects to your file directly instead, codecs.open() handles encoding to UTF-8 correctly if you do.

Python: base64.b64decode() vs .decode?

The Code Furies have turned their baleful glares upon me, and it's fallen to me to implement "Secure Transport" as defined by The Direct Project. Whether or not we internally use DNS rather than LDAP for sharing certificates, I'm obviously going to need to set up the former to test against, and that's what's got me stuck. Apparently, an X509 cert needs some massaging to be used in a CERT record, and I'm trying to work out how that's done.
The clearest thing I've found is a script on Videntity's blog, but not being versed in python, I'm hitting a stumbling block. Specifically, this line crashes:
decoded_clean_pk = clean_pk.decode('base64', strict)
since it doesn't seem to like (or rather, to know) whatever 'strict' is supposed to represent. I'm making the semi-educated guess that the line is supposed to decode the base64 data, but I learned from the Debian OpenSSL debacle some years back that blindly diddling with crypto-related code is a Bad Thing(TM).
So I turn the illustrious python wonks on SO to ask if that line might be replaced by this one (with the appropriate import added):
decoded_clean_pk = base64.b64decode(clean_pk)
The script runs after that change, and produces correct-looking output, but I've got enough instinct to know that I can't necessarily trust my instincts here. :)
This line should've work if you would've called like this:
decoded_clean_pk = clean_pk.decode('base64', 'strict')
Notice that strict has to be a string, otherwise python interpreter would try to search for a variable named strict and if it didn't find it or otherwise has other value than: strict, ignore, and replace, it'll probably would've complain about it.
Take a look at this code:
>>>b=base64.b64encode('hello world')
>>>b.decode('base64')
'hello world'
>>>base64.b64decode(b)
'hello world'
Both decode and b64decode works the same when .decode is passed the base64 argument string.
The difference is that str.decode will take a string of bytes as arguments and will return it's Unicode representation depending on the encoding argument you pass as first parameter. In this case, you're telling it to handle a bas64 string so it will do it ok.
To answer your question, both works the same, although b64decode/encode are meant to work only with base64 encodings and str.decode can handle as many encodings as the library is aware of.
For further information take a read at both of the doc sections: decode and b64decode.
UPDATE: Actually, and this is the most important example I guess :) take a look at the source code for encodings/base64_codec.py which is that decode() uses:
def base64_decode(input,errors='strict'):
""" Decodes the object input and returns a tuple (output
object, length consumed).
input must be an object which provides the bf_getreadbuf
buffer slot. Python strings, buffer objects and memory
mapped files are examples of objects providing this slot.
errors defines the error handling to apply. It defaults to
'strict' handling which is the only currently supported
error handling for this codec.
"""
assert errors == 'strict'
output = base64.decodestring(input)
return (output, len(input))
As you may see, it actually uses base64 module to do it :)
Hope this clarify in some way your question.

Why use str(id)?

My SDK comes with code appearing with rows like this
id=str(profile["id"])
It makes me wonder why something like the following shouldn't work
id=profile["id"]
Casting I believe is expensive so either the same type can be used or polymorphism at the method called. Can you tell why I must cast the id to a string?
Thank you
There is no casting in Python. Str(67) does not cast. It calls the __str__ method on the integer object, which generates a string representation of itself.
This is necessary to make sure that profile['id'] is a string.
It turns profile[id] into a string, python doesn't do this automatically, and further along in the code, the program probably checks profile[id] against a string. Without this conversion, you would get a typeerror: Trying to compare a string with an integer.
Python does not do arbitrary run time type conversion. You can't use an integer as a string.
It turns profile[id] into a string

Categories

Resources