/
bytes_to_int.py
47 lines (37 loc) · 1.3 KB
/
bytes_to_int.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
"""
Demonstration of how `int.from_bytes()` converts a Python bytes obj to int.
Used in random module's `SystemRandom.random()` to generate a float in
[0.0, 1.0) from `os.urandom()`:
https://github.com/python/cpython/blob/c6040638aa1537709add895d24cdbbb9ee310fde/Lib/random.py#L676
An example: the number 1984 can be "decomposed" in the decimal system (base 10)
as (1 * 10 ** 3)
+ (9 * 10 ** 2)
+ (8 * 10 ** 1)
+ (4 * 10 ** 0)
`int.from_bytes()` (with big endianness) uses a base-256 numbering system
Given b = b'\xe6\x04\x00\x00',
>>> list(b)
[230, 4, 0, 0]
And the int is then
(230 * 256 ** 3)
+ (4 * 256 ** 2)
+ (0 * 256 ** 1)
+ (0 * 256 ** 0) == 3859021824
"""
import os
import random
def bytes_to_int(b: bytes, byteorder: str = "big") -> int:
if byteorder == "big":
return sum(j * 256 ** i for i, j in enumerate(b[::-1]))
elif byteorder == "little":
return sum(j * 256 ** i for i, j in enumerate(b))
else:
raise ValueError("byteorder must be either 'little' or 'big'.")
def test(seed=None):
for _ in range(10):
b = os.urandom(random.randint(0, 100))
assert bytes_to_int(b, "big") == int.from_bytes(b, "big"), b
assert bytes_to_int(b, "little") == int.from_bytes(b, "little"), b
if __name__ == "__main__":
import sys
sys.exit(test())