I have wrote out the function:
print(hashlib.sha256(hashlib.sha256(Encode(s))).hexdigest())
However, there seems to be the following error:
object supporting the buffer API required
I believe this is because when hashing the second time, the input is not a byte form because it has been already hashed.
How can I solve this problem and hash a single string two times?
How about this code (as suggested by james-k-polk)?
print(hashlib.sha256(hashlib.sha256(s.encode('ascii')).digest()).hexdigest())
This works if you want to do it in one line
from hashlib import sha256 as h
print(h(h("your_string".encode()).hexdigest().encode()).hexdigest())
# Gives: c94c01dafc045892773d67dabb3da8feb925e2c48e0373eab922da49f7fd269c
# Encrypted once: e10207f241d66a8c5f8202ed9fc22b94c031850dd54d8b03fdd40db4cbde5bfc
Related
Can you please help me to understand such a simple subject. I need to produce a serie of random hexadecimal strings for which I'm using:
import secrets
x = secrets.token_hex(32)
This gives me something like this:
d6d09acbe78c269147803b8c351214a6e5f39093ca315c47e1126360d0df5369
Which is totally fine. Now I need to pass it through a SHA256 hash for which I'm using:
h = hashlib.new('sha256')
print (h.update(x))
Getting the error:
TypeError: Unicode-objects must be encoded before hashing
I read I need to encode the string before passing the hash using .encode() obtaining a completelly weird:
b'd6d09acbe78c269147803b8c351214a6e5f39093ca315c47e1126360d0df5369'
, and a 'none' result as the hash.
Can you please tell me whats going on here.
Thanks a lot gentls.
You are trying to print the output of h.update(), which will be None as it doesnt return anything. Instead use
h.update(x.encode())
print(h.hexdigest())
to print out a hash string.
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')
I thought that this would be a fairly common and straightforward problem, but I searched and was not able to find it.
I am a novice Python user, mostly self-taught. I'm trying what I thought would be a fairly straightforward exercise: generating a hash value from an input phrase. Here is my code:
import hashlib
target = input("Give me a phrase: ").encode('utf-8')
hashed_target = hashlib.sha256(target)
print(hashed_target)
I execute this and get the prompt:
Give me a phrase:
I entered the phrase "Give me liberty or give me death!" and got the hash output 0x7f8ed43d6a80.
Just to test, I tried again with the same phrase, but got a different output: 0x7f1cc23bca80.
I thought that was strange, so I copied the original input and pasted it in, and got a third, different hash output: 0x7f358aabea80.
I'm sure there must be a simple explanation. I'm not getting any errors, and the code looks straightforward, but the hashes, while similar, are definitely different.
Can someone help?
You are directly printing an object, which returns a memory address in the __repr__ string. You need to use the hexdigest or digest methods to get the hash:
>>> import hashlib
>>> testing=hashlib.sha256(b"sha256 is much longer than 12 hex characters")
>>> testing
<sha256 HASH object # 0x7f31c1c64670>
>>> hashed_testing=testing.hexdigest()
>>> hashed_testing
'a0798cfd68c7463937acd7c08e5c157b7af29f3bbe9af3c30c9e62c10d388e80'
>>>
I’m using Python 2 and am attempting to performing sha256 on binary values using hashlib.
I’ve become a bit stuck as I’m quite new to it all but have cobbled together:
hashlib.sha256('0110100001100101011011000110110001101111’.decode('hex')).hexdigest()
I believe it interprets the string as hex based on substituting the hex value (‘68656c6c6f’) into the above and it returning
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
And comparing to this answer in which ‘hello’ or ‘68656c6c6f’ is used.
I think the answer lies with the decode component but I can’t find an example for binary only ‘hex’ or ‘utf-8’
Is anyone able to suggest what needs to be changed so that the function interprets as binary values instead of hex?
Here is code that does each of the data conversions you are looking for. These steps can all be combined, but are separated here so you can see each value.
import hashlib
import binascii
binstr = '0110100001100101011011000110110001101111'
hexstr = "{0:0>4X}".format(int(binstr,2)) # '68656C6C6F'
data = binascii.a2b_hex(hexstr) # 'hello'
output = hashlib.sha256(data).hexdigest()
print output
OUTPUT:
2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
I need to create an identifier token from a set of nested configuration values.
The token can be part of a URL, so – to make processing easier – it should contain only hexadecimal digits (or something similar).
The config values are nested tuples with elements of hashable types like int, bool, str etc.
My idea was to use the built-in hash() function, as this will continue to work even if the config structure changes.
This is my first attempt:
def token(config):
h = hash(config)
return '{:X}'.format(h)
This will produce tokens of variable length, but that doesn't matter.
What bothers me, though, is that the token might contain a leading minus sign, since the return value of hash() is a signed integer.
As a way to avoid the sign, I thought of the following work-around, which is adding a constant to the hash value.
This constant should be half the size of the range the value of hash() can take (which is platform-dependent, eg. different for 32-/64-bit systems):
HALF_HASH_RANGE = 2**(sys.hash_info.width-1)
Is this a sane and portable solution?
Or will I shoot myself in the foot with this?
I also saw suggestions for using struct.pack() (which returns a bytes object, on which one can call the .hex() method), but it also requires knowing the range of the hash value in advance (for the choice of the right format character).
Addendum:
Encryption strength or collisions by chance are not an issue.
The drawback of the hashlib library in this scenario is that it requires writing a converter that traverses the input structure and converts everything into a bytes representation, which is cumbersome.
You can use any of hash functions for getting unique string. Right now python support out of the box many algorithms, like: md5, sha1, sha224, sha256, sha384, sha512. You can read more about it here - https://docs.python.org/2/library/hashlib.html
This example shows how to use library hashlib. (Python 3)
>>> import hashlib
>>> sha = hashlib.sha256()
>>> sha.update('somestring'.encode())
>>> sha.hexdigest()
>>> '63f6fe797026d794e0dc3e2bd279aee19dd2f8db67488172a644bb68792a570c'
Also you can try library hashids. But note that it's not a hash algorithm and you (and anyone who knows salt) can decrypt data.
$ pip install hashids
Basic usage:
>>> from hashids import Hashids
>>> hashids = Hashids()
>>> hashids.encode(123)
'Mj3'
>>> hashids.decode('Mj3')
123
I need to create an identifier token from a set of nested configuration values
I came across this question while trying to solve the same problem, and realizing that some of the calls to hash return negative integers.
Here's how I would implement your token function:
import sys
def token(config) -> str:
"""Generates a hex token that identifies a hashable config."""
# `sign_mask` is used to make `hash` return unsigned values
sign_mask = (1 << sys.hash_info.width) - 1
# Get the hash as a positive hex value with consistent padding without '0x'
return f'{hash(config) & sign_mask:#0{sys.hash_info.width//4}x}'[2:]
In my case I needed it to work with a broad range of inputs for the config. It did not need to be particularly performant (it was not on a hot path), and it was acceptable if it occasionally had collisions (more than what would normally be expected from hash). All it really needed to do is produce short (e.g. 16 chars long) consistent outputs for consistent inputs. So for my case I used the above function with a small modification to ensure the provided config is hashable, at the cost of increased collision risk and processing time:
import sys
def token(config) -> str:
"""Generates a hex token that identifies a config."""
# `sign_mask` is used to make `hash` return unsigned values
sign_mask = (1 << sys.hash_info.width) - 1
# Use `json.dumps` with `repr` to ensure the config is hashable
json_config = json.dumps(config, default=repr)
# Get the hash as a positive hex value with consistent padding without '0x'
return f'{hash(json_config) & sign_mask:#0{sys.hash_info.width//4}x}'[2:]
I'd reccomend using hashlib
cast the token to a string, and then cast the hexdigest to a hex integer. Bellow is an example with the sha256 algorithm but you can use any hashing algorithm hashlib supports
import hashlib as hl
def shasum(token):
return int(hl.sha256(str(token).encode('utf-8')).hexdigest(), 16)