Generate a variable length hash - python

Is there a way in python to generate a short version of hashcode, SHA128 or SHA256
I tried this but its not correct way to get[extracting substring to shorten]
hashlib.sha256(str.encode('utf-8')).hexdigest()[:8]
for example if i have a string, i want 8 character hash
str = "iamtestingastringtogethash"
print(hashlib.sha256(str.encode('utf-8').hexdigest(),8))
Output: some_8char_hash

Ok i found my own fix,
hashlib.shake_256(str.encode("utf-8")).hexdigest(length=8)

As per the hashlib source code hexdigest method looks for integer value as input without a keyword
def hexdigest(self, __length: int) -> str: ...
the following will do the work without the keyword length and double of input number is the total length
hashlib.shake_256(str.encode("utf-8")).hexdigest(4)

Related

hex to int python but get a letter in response

This is pretty well documented but I keep getting output that doesn't make sense. I have a hex value that looks like
\x00\x00\x00\x00\x00\x01\x86\xa0
but I get
>>> b'\x00\x00\x00\x00\x00\x01\x86\xa0'.hex()
'00000000000186a0'
I am expecting a int or at least a readable number. I assume I am using the wrong function.
Advice?
You need to add a base value of 16
For Example
hex_string = "a1"
integer = int(hex_string, 16)
print(integer)
The output of this will be 161
Try this out
Then try this
hex_bytes = b'\x12\x34'
integer= int.from_bytes(hex_bytes,byteorder='big')
print(integer)

Convert Value to 32-bit values

I have a table Widget and user give a number in table, so when I get this value I want to convert 32 bit hex value.
For example user enter number 10, I need to convert this number
Firstly 0x000A (it need to be hex)
And split like this myList = [0x0,0x0,0x0,0xA]
I tried with below command
myNum = 10
value = '0x{0:04X}'.format(myNum)
print(value)
print(list(struct.pack('<H',value)))
I get struct.error: required argument is not an integer
'0x{0:04X}'.format(myNum) value return string so I couldnt split this value correctly.
I expect this value [0x0,0x0,0x0,0xA]
How can I do that ?
You cannot do a strut.pack on a string. It takes integers (as the error describes) and returns a byte string, which you can turn into a list.
import struct
myNum = 10
myHex = '0x{0:04X}'.format(myNum)
print(myHex)
mylist = list(struct.pack('>I',myNum))
print(mylist)
print(list(map(hex, mylist)))
The last line prints them as hex, but they are not integers, they are strings. And you are trying to use little endian in your code, but the expected output is in Big.

How to decrypt blocks encrypted with RSA?

I'm still on my RSA project, and now I can successfully create the keys, and encrypt a string with them
def encrypt(clear_message, public_key):
clear_list = convert_into_unicode (clear_message)
n = public_key[0]
e = public_key[1]
message_chiffre = str()
for i, value in enumerate (clear_list) :
encrypted_value = str( pow (int(value), e, n) )
encrypted_message += (encrypted_value )
return encrypted_message
def convert_into_unicode (clear_message):
str_unicode = ''
for car in clear_message:
str_unicode += str (ord (car))
if len (str_unicode ) % 5 != 0:
str_unicode += (5 - len (str_unicode ) % 5) * '0'
clear_list = []
i = 5
while i <= len (str_unicode ):
clear_list .append (str_unicode [i-5:i])
i += 5
return liste_claire
For example, encrypting the message 'Hello World' returns ['72101', '10810', '81113', '28711', '11141', '08100', '32330'] as clear_list then
'3863 111 1616 3015 1202 341 4096' as encrypted_message
The encrypt () function uses the other function to convert the string into a list of the Unicode values but put in blocks because I've read that otherwise, it would be easy to find the clear message only with frequency analysis.
Is it really that easy?
And as it probably is, I come to my main question. As you know, the Unicode values of a character are either double-digits or triple-digits. Before the encryption, the Unicode values are separated into blocks of 5 digits ('stack' -> '115 116 97 99 107' -> '11511 69799 10700')
But the problem is when I want to decrypt this, how do I know where I have to separate that string so that one number represents one character?
I mean, the former Unicode value could be either 11 or 115 (I know it couldn't really be 11, but that's only as an example). So to decrypt and then get back the character, the problem is, I don't know how much digits I have to take.
I had thought of adding a 0 when the Unicode value is < 100, but
Then it's easy to do the same thing as before with the frequency analysis
Still, when I encrypt it, '087' can result in '467' and '089' can result in '046', so the problem is still here.
You're trying to solve real world problems with a toy RSA problem. The frequency analysis can be performed because no random padding of the plaintext message has been used. Random padding is required to make RSA secure.
For this kind of problem it is enough to directly use the Unicode code point (an integer value) per character as input to RSA. RSA can however only directly encrypt values in the range [0..N) where N is the modulus. If you input a larger value x then value will first be converted into the value x modulus N. In that case you loose information and decryption will not be deterministic anymore.
As for the ciphertext, just make this the string representation of the integer values separated by spaces and split them to read them in. This will take more space, but RSA always has a certain overhead.
If you want to implement secure RSA then please read into PKCS#1 standard and beware of time attacks etc. And, as Wyzard already indicated, please use hybrid cryptography (using a symmetric encryption in addition to RSA).
Or use a standard library, now you understand how RSA works in principle.
Your convert_into_unicode function isn't really converting anything "into" Unicode. Assuming clear_message is a Unicode string (The default string type in Python 3, or u'' in Python 2), it's (naturally) Unicode already, and you're using an awkward way of turning it into a sequence of bytes that you can encrypt. If clear_message is a byte string (the default in Python 2, or b'' in Python 3), all the characters fit in a byte already, so the whole process is unnecessary.
It's true that Unicode string needs to be encoded as a byte sequence before you can encrypt it. The normal way to do that is with an encoding such as UTF-8 or UTF-16. You can do that by calling clear_message.encode('utf-8'). After decrypting, you can turn the decrypted byte string back into a Unicode string with decrypted_bytes.decode('utf-8').
You don't need the convert_into_unicode function at all.

Generate ID from string in Python

I'm struggling a bit to generate ID of type integer for given string in Python.
I thought the built-it hash function is perfect but it appears that the IDs are too long sometimes. It's a problem since I'm limited to 64bits as maximum length.
My code so far: hash(s) % 10000000000.
The input string(s) which I can expect will be in range of 12-512 chars long.
Requirements are:
integers only
generated from provided string
ideally up to 10-12 chars long (I'll have ~5 million items only)
low probability of collision..?
I would be glad if someone can provide any tips / solutions.
I would do something like this:
>>> import hashlib
>>> m = hashlib.md5()
>>> m.update("some string")
>>> str(int(m.hexdigest(), 16))[0:12]
'120665287271'
The idea:
Calculate the hash of a string with MD5 (or SHA-1 or ...) in hexadecimal form (see module hashlib)
Convert the string into an integer and reconvert it to a String with base 10 (there are just digits in the result)
Use the first 12 characters of the string.
If characters a-f are also okay, I would do m.hexdigest()[0:12].
If you're not allowed to add extra dependency, you can continue using hash function in the following way:
>>> my_string = "whatever"
>>> str(hash(my_string))[1:13]
'460440266319'
NB:
I am ignoring 1st character as it may be the negative sign.
hash may return different values for same string, as PYTHONHASHSEED Value will change everytime you run your program. You may want to set it to some fixed value. Read here
encode utf-8 was needed for mine to work:
def unique_name_from_str(string: str, last_idx: int = 12) -> str:
"""
Generates a unique id name
refs:
- md5: https://stackoverflow.com/questions/22974499/generate-id-from-string-in-python
- sha3: https://stackoverflow.com/questions/47601592/safest-way-to-generate-a-unique-hash
(- guid/uiid: https://stackoverflow.com/questions/534839/how-to-create-a-guid-uuid-in-python?noredirect=1&lq=1)
"""
import hashlib
m = hashlib.md5()
string = string.encode('utf-8')
m.update(string)
unqiue_name: str = str(int(m.hexdigest(), 16))[0:last_idx]
return unqiue_name
see my ultimate-utils python library.

CRC32 checksum in Python with hex input

I'm wanting to calculate the CRC32 checksum of a string of hex values in python. I found zlib.crc32(data) and binascii.crc32(data), but all the examples I found using these functions have 'data' as a string ('hello' for example). I want to pass hex values in as data and find the checksum. I've tried setting data as a hex value (0x18329a7e for example) and I get a TypeError: must be string or buffer, not int. The function evaluates when I make the hex value a string ('0x18329a7e' for example), but I don't think it's evaluating the correct checksum. Any help would be appreciated. Thanks!
I think you are looking for binascii.a2b_hex():
>>> binascii.crc32(binascii.a2b_hex('18329a7e'))
-1357533383
>>> import struct,binascii
>>> ncrc = lambda numVal: binascii.crc32(struct.pack('!I', numVal))
>>> ncrc(0x18329a7e)
-1357533383
Try converting the list of hex values to a string:
t = ['\x18', '\x32', '\x9a', '\x7e']
chksum = binascii.crc32(str(t))

Categories

Resources