mirror of
https://github.com/tcsenpai/AmbianceRNG.git
synced 2025-06-02 22:40:02 +00:00
107 lines
3.3 KiB
Python
107 lines
3.3 KiB
Python
# INFO
|
|
# @author: TheCookingSenpai
|
|
# @github: https://github.com/TheCookingSenpai
|
|
# @homepage: https://github.com/TheCookingSenpai/AmbianceRNG
|
|
#
|
|
# @description:
|
|
# This is a very simple proof of concept for generating true random numbers by
|
|
# feeding the python pseudo-random number generator with ambiental noise.
|
|
# While is not enforced, the ambiental noise is expected to be generated by
|
|
# having an input device that is able to capture sound from the environment.
|
|
# A cheap and simple way to generate ambiental noise is to use a simple radio
|
|
# with antenna and headphone out and to connect the headphone to your computer.
|
|
# Be sure to tune your radio into an empty frequency so that the ambiental
|
|
# recording is purely background noise.
|
|
#
|
|
|
|
import pyaudio
|
|
import wave
|
|
from bitstring import BitArray
|
|
import hashlib
|
|
import random
|
|
|
|
class AmbianceRNG:
|
|
|
|
def __init__(self):
|
|
self.CHUNK = 1024
|
|
self.FORMAT = pyaudio.paInt16
|
|
self.CHANNELS = 1
|
|
self.RATE = 44100
|
|
self.RECORD_SECONDS = 2
|
|
self.WAVE_OUTPUT_FILENAME = "seed.wav"
|
|
self.frames = []
|
|
self.stream = None
|
|
self.device = None
|
|
self.bin_bytes = ''
|
|
|
|
|
|
def record_seed(self):
|
|
# Opening our device and setting up the stream for recording
|
|
self.device = pyaudio.PyAudio()
|
|
self.stream = self.device.open(format=self.FORMAT,
|
|
channels=self.CHANNELS,
|
|
rate=self.RATE,
|
|
input=True,
|
|
frames_per_buffer=self.CHUNK)
|
|
print("* detecting ambiental noise...")
|
|
# Recording ambiental noise
|
|
for _ in range(int(self.RATE / self.CHUNK * self.RECORD_SECONDS)):
|
|
data = self.stream.read(self.CHUNK)
|
|
self.frames.append(data)
|
|
print("* done recording ambiental noise")
|
|
self.stream.stop_stream()
|
|
self.stream.close()
|
|
self.device.terminate()
|
|
return self.frames
|
|
|
|
def save_seed(self):
|
|
wf = wave.open(self.WAVE_OUTPUT_FILENAME, 'wb')
|
|
wf.setnchannels(self.CHANNELS)
|
|
wf.setsampwidth(self.device.get_sample_size(self.FORMAT))
|
|
wf.setframerate(self.RATE)
|
|
wf.writeframes(b''.join(self.frames))
|
|
wf.close()
|
|
|
|
def serialize_seed(self):
|
|
print("* serializing ambiental noise... [ ]", end="\b\b", flush=True)
|
|
counter = 1 # Initialized to 1 to avoid unnecessary assignment later
|
|
bin_bytes = ''
|
|
with open(self.WAVE_OUTPUT_FILENAME, 'rb') as f:
|
|
all_bytes = f.read()
|
|
raw_bytes = all_bytes[44:] # Removing the first 44 bytes
|
|
self.bin_bytes = BitArray(raw_bytes)
|
|
print("\b\b\n* done serializing ambiental noise")
|
|
# Logging to file
|
|
with open("seed.txt", "w") as f:
|
|
f.write(str(self.bin_bytes))
|
|
|
|
def get_random_number(self, min, max):
|
|
# Using an hash representation is way faster than using the whole string
|
|
hash_object = hashlib.sha256(str(self.bin_bytes).encode())
|
|
hex_dig = hash_object.hexdigest()
|
|
print(f"* using seed {hex_dig}")
|
|
with open("hash.txt", "a") as f:
|
|
f.write(f"{hex_dig}\n")
|
|
# Seeding the prng
|
|
random.seed(hex_dig, version=2)
|
|
# Getting a random number
|
|
arn = random.randint(min, max)
|
|
with open("random.txt", "a+") as f:
|
|
f.write(f"{arn} ")
|
|
with open("seeds_history.txt", "a+") as f:
|
|
f.write(f"{hex_dig}\n")
|
|
return arn
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
counter = 0
|
|
while True:
|
|
arng = AmbianceRNG()
|
|
arng.record_seed()
|
|
arng.save_seed()
|
|
arng.serialize_seed()
|
|
rn = arng.get_random_number(1, 100)
|
|
counter += 1
|
|
print(f"Produced {counter} random numbers")
|
|
print(rn) |