Python 3 os.urandom - python

Where can I find a complete tutorial or documentation on os.urandom? I need to get get a random int to choose a char from a string of 80 characters.

If you just need a random integer, you can use random.randint(a, b) from the random module.
If you need it for crypto purposes, use random.SystemRandom().randint(a, b), which makes use of os.urandom().
Example
import random
r = random.SystemRandom()
s = "some string"
print(r.choice(s)) # print random character from the string
print(s[r.randrange(len(s))]) # same

Might not exactly be on topic, but I want to help those coming here from a search engine. To convert os.urandom to an integer I'm using this:
import os
rand = int(int(str(os.urandom(4), encoding="UTF-8")).encode('hex'), 16)
# You can then 'cycle' it against the length.
rand_char = chars_list[rand % 80] # or maybe '% len(chars_list)'
Note: The range of the index here is up to that of a 4-byte integer. If you want more, change the 4 to a greater value.
The idea was taken from here: https://pythonadventures.wordpress.com/2013/10/04/generate-a-192-bit-random-number/

Related

How to use Hashlib to MD5 hash a number?

It seems everyone is doing this:
import hashlib
# initializing string
str = "GeeksforGeeks"
# encoding GeeksforGeeks using encode()
# then sending to md5()
result = hashlib.md5(str.encode())
However, I want to hash plain numbers. Something like
result = hashlib.md5(0)
#or
var = 5
result = hashlib.md5(var)
isn't working, and I've tried lots of other variations. What's the right syntax?
Hashes operate on a sequence of bytes.
An integer in Python is just simply a logical value; it has no definite size or byte-wise representation. If you want to hash numbers, you need to decide what form to put the number in before hashing it.
The simplest option would be to hash the string representation of the number. Do this by calling str and hashing that result. E.g.
var = 5
hash_input = str(var)
result = hashlib.md5(hash_input)
Another option would be to choose a fixed size, and hash the binary representation of the number:
var = 5
hash_input = struct.pack('<I', var) # Little-endian 32-bit unsigned
result = hashlib.md5(hash_input)
The correct way to do this totally depends on what exactly you're trying to accomplish, which you haven't told us.
Hashing plain numbers is ambiguous, to say the least.
The number should be converted to bytes before being fed to the digest algorithm. The first problem that you'll run into is how much byte size the number occupies, could be 4 byte, 8 byte or whatever. Then comes endianness, the order of bytes in memory. All these would result in different digest for seemingly the same number. (For simplicity, I've assumed the number is int)
>>> hashlib.md5(b'4').hexdigest()
'a87ff679a2f3e71d9181a67b7542122c'
>>> i = 4
>>> hashlib.md5(i.to_bytes(2, 'big')).hexdigest()
'c244b9cdf7853b5693a295e384c07367'
>>> hashlib.md5(i.to_bytes(4, 'big')).hexdigest()
'ea4959eb64a1f09be580d950964f3843'
>>> hashlib.md5(i.to_bytes(8, 'big')).hexdigest()
'59cff542fae7e0c4267e45740a12c9a0'
So, your solution would be to convert the int to str and encode it so you can get a digest from it.
# either this
>>> hashlib.md5(b'4').hexdigest()
# or
>>> hashlib.md5(str(4).encode()).hexdigest()
Hope that helps.

Why does using this code can generate a random password?

Here a snippet for generating password code,
I have 2 questions about this, Could you please share how to understand?
urandom(6), help from urandom said,return n random bytes suitable for cryptographic use, it is say, it will return 6 bytes, is it 6 of ASCII ?
ord(c) , get the decimal base for above bytes, why here transfer to decimal base?
Help for urandom:
def urandom(n): # real signature unknown; restored from __doc__
"""
urandom(n) -> str
Return n random bytes suitable for cryptographic use.
"""
return ""
Python script:
from os import urandom
letters = "ABCDEFGHJKLMNPRSTUVWXYZ"
password = "".join(letters[ord(c) % len(letters)] for c in urandom(6))
urandom will return a byte (i.e. a value between 0 and 255). The sample code uses that value and the modulo operator (%) to convert it into a value between 0 and 22, so that it can return one of the 23 letters (I, O, and Q are excluded not to be confused with numbers).
Note that it is not a perfectly balanced algorithm as it would favour the first 3 letters (A, B, and C) more, because 256 is not divisible by 23 and 256 % 23 is 3.
ord() function takes in a string containing a single character, and returns its Unicode index.
ex.
ord("A") => 65
ord("£") => 163
It is not used to get the decimal base of a byte as you mentioned, but rather its Unicode Index (its place in the Unicode Table).
P.S. :- Even though it returns the Unicode index but that doesn't mean its, range = len(Unicode Table) , the reason being that your python compiler may not support such long character sets under normal circumstances.

Generate a random number of len(10) containing digits only 0-1s

The question is self-explanatory.
I've tried this.
import random
number = "".join([str(random.randint(0,1)) for i in xrange(0,10)])
print number
Is there any in-built functionality for the same?
Either use:
''.join(random.choice('01') for _ in xrange(10))
Which avoids the int->str, or otherwise use randrange (to exclude a full bit set) with a range that's 2**10, then format as a binary string.
format(random.randrange(2**10), '010b')
Also, to avoid overflow, you can use getrandbits and specify 10 as the amount, eg:
format(random.getrandbits(10), '010b')
Choose a random int in the range 0 ti 1023 inclusive and format it in base 2 with a minimum width of 10 with leading 0s filled in.
format(random.randint(0,1023), '010b')
I’m going to throw in another solution that creates an actual (decimal) number containing only ones and zeros:
>>> import random, functools
>>> functools.reduce(lambda x, i: 10 * x + random.randrange(2), range(10), 0)
1011001010
OR, to skip the decimal-binary transition :
from random import randint
def repeat(n):
if(n<=0):
return ''
n -= 1
return str(randint(0,1))+repeat(n)
and at the end just call repeat(10) or whatever number of bits you want.

Is there a way to pad to an even number of digits?

I'm trying to create a hex representation of some data that needs to be transmitted (specifically, in ASN.1 notation). At some points, I need to convert data to its hex representation. Since the data is transmitted as a byte sequence, the hex representation has to be padded with a 0 if the length is odd.
Example:
>>> hex2(3)
'03'
>>> hex2(45)
'2d'
>>> hex2(678)
'02a6'
The goal is to find a simple, elegant implementation for hex2.
Currently I'm using hex, stripping out the first two characters, then padding the string with a 0 if its length is odd. However, I'd like to find a better solution for future reference. I've looked in str.format without finding anything that pads to a multiple.
def hex2(n):
x = '%x' % (n,)
return ('0' * (len(x) % 2)) + x
To be totally honest, I am not sure what the issue is. A straightforward implementation of what you describe goes like this:
def hex2(v):
s = hex(v)[2:]
return s if len(s) % 2 == 0 else '0' + s
I would not necessarily call this "elegant" but I would certainly call it "simple."
Python's binascii module's b2a_hex is guaranteed to return an even-length string.
the trick then is to convert the integer into a bytestring. Python3.2 and higher has that built-in to int:
from binascii import b2a_hex
def hex2(integer):
return b2a_hex(integer.to_bytes((integer.bit_length() + 7) // 8, 'big'))
Might want to look at the struct module, which is designed for byte-oriented i/o.
import struct
>>> struct.pack('>i',678)
'\x00\x00\x02\xa6'
#Use h instead of i for shorts
>>> struct.pack('>h',1043)
'\x04\x13'

Integer to Unique String

There's probably someone else who asked a similar question, but I didn't take much time to search for this, so just point me to it if someone's already answered this.
I'm trying to take an integer (or long) and turn it into a string, in a very specific way.
The goal is essentially to split the integer into 8-bit segments, then take each of those segments and get the corresponding ASCII character for that chunk, then glue the chunks together.
This is easy to implement, but I'm not sure I'm going about it in the most efficient way.
>>> def stringify(integer):
output = ""
part = integer & 255
while integer != 0:
output += chr(part)
integer = integer >> 8
return output
>>> stringify(10)
'\n'
>>> stringify(10 << 8 | 10)
'\n\n'
>>> stringify(32)
' '
Is there a more efficient way to do this?
Is this built into Python?
EDIT:
Also, as this will be run sequentially in a tight loop, is there some way to streamline it for such use?
>>> for n in xrange(1000): ## EXAMPLE!
print stringify(n)
...
struct can easily do this for integers up to 64 bits in size. Any larger will require you to carve the number up first.
>>> struct.pack('>Q', 12345678901234567890)
'\xabT\xa9\x8c\xeb\x1f\n\xd2'

Categories