pseudo fallback
This commit is contained in:
parent
ca812c06c5
commit
5bcfd63d11
2 changed files with 88 additions and 16 deletions
|
|
@ -1,4 +1,8 @@
|
|||
import requests
|
||||
import random
|
||||
import secrets
|
||||
import base64
|
||||
import os
|
||||
|
||||
try:
|
||||
from urllib.parse import urlencode
|
||||
|
|
@ -13,31 +17,99 @@ URL = 'https://qrng.randonautica.com/api/json/'
|
|||
typeS = {
|
||||
'int32' : 'randint32',
|
||||
'hex16' : 'randhex',
|
||||
'uniform' : 'randuniform',
|
||||
'uniform': 'randuniform',
|
||||
'normal' : 'randnormal',
|
||||
'base64' : 'randbase64'
|
||||
}
|
||||
|
||||
DEVICE_ID = 'QWR70154'
|
||||
|
||||
def get(length=10, type='hex16'):
|
||||
def get(length=10, type='hex16', timeout=1.5):
|
||||
"""
|
||||
Fetch data from the Randonautica Quantum Random Numbers JSON API
|
||||
|
||||
length (int): length of bytes to get from the QRNG when `type=hex16`
|
||||
type (string): type of random number data to fetch.
|
||||
Valid choices are `hex16`, `int32`, `uniform`, `normal`, `base64`
|
||||
Fetch data from the Randonautica Quantum Random Numbers JSON API.
|
||||
Falls back to local randomness if the API is unavailable.
|
||||
|
||||
length (int): number of values/bytes to get
|
||||
type (str): one of {'hex16','int32','uniform','normal','base64'}
|
||||
timeout (float): HTTP timeout in seconds
|
||||
"""
|
||||
if type not in typeS.keys():
|
||||
raise Exception("type must be one of %s" % typeS.keys())
|
||||
if type not in typeS:
|
||||
raise Exception("type must be one of %s" % list(typeS.keys()))
|
||||
|
||||
# Try QRNG first
|
||||
url = URL + typeS[type] + '?' + urlencode({
|
||||
'device_id': DEVICE_ID,
|
||||
'length': length,
|
||||
})
|
||||
data = __get_json(url)
|
||||
try:
|
||||
data = __get_json(url, timeout=timeout)
|
||||
# Validate expected shape minimally
|
||||
if isinstance(data, dict) and "data" in data and isinstance(data["data"], list):
|
||||
return data
|
||||
# If shape unexpected, fall back
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Fallback path: generate locally with best available primitives
|
||||
return _fallback_response(type=type, length=length)
|
||||
|
||||
def __get_json(url):
|
||||
return requests.get(url, verify=False).json()
|
||||
def __get_json(url, timeout=1.5):
|
||||
resp = requests.get(url, verify=False, timeout=timeout)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def _fallback_response(type: str, length: int):
|
||||
"""
|
||||
Produce a response object that mirrors the QRNG API:
|
||||
{
|
||||
"type": <type>,
|
||||
"length": <length>,
|
||||
"data": [...],
|
||||
"success": true,
|
||||
"source": "fallback"
|
||||
}
|
||||
"""
|
||||
if type == 'uniform':
|
||||
# Uniform floats in [0.0, 1.0)
|
||||
data = [random.random() for _ in range(length)]
|
||||
|
||||
elif type == 'normal':
|
||||
# Standard normal N(0,1)
|
||||
data = [random.gauss(0.0, 1.0) for _ in range(length)]
|
||||
|
||||
elif type == 'int32':
|
||||
# 32-bit signed ints (match typical randint32 range: [-2^31, 2^31-1])
|
||||
# secrets is preferable to random for stronger entropy.
|
||||
data = []
|
||||
for _ in range(length):
|
||||
u = secrets.randbits(32)
|
||||
# Convert to signed 32-bit
|
||||
if u & (1 << 31):
|
||||
u = u - (1 << 32)
|
||||
data.append(u)
|
||||
|
||||
elif type == 'hex16':
|
||||
# Hex string of length*2 bytes? The API name suggests 16-bit hex bytes.
|
||||
# Historically this endpoint returns hex bytes; emulate by returning a single hex string
|
||||
# of 2*length characters (each byte -> 2 hex chars). If API returns list, adapt as needed.
|
||||
# Here we return a list of hex byte strings to match "data": [...]
|
||||
data = [secrets.token_hex(1) for _ in range(length)]
|
||||
|
||||
elif type == 'base64':
|
||||
# Return base64-encoded random bytes; match as a list of base64 strings
|
||||
data = []
|
||||
for _ in range(length):
|
||||
b = os.urandom(16) # 16 bytes per element; adjust if your API uses a different size
|
||||
data.append(base64.b64encode(b).decode('ascii'))
|
||||
|
||||
else:
|
||||
# Should never hit due to earlier check
|
||||
data = []
|
||||
|
||||
return {
|
||||
"type": type,
|
||||
"length": length,
|
||||
"data": data,
|
||||
"success": True,
|
||||
"source": "pseudo"
|
||||
}
|
||||
2
setup.py
2
setup.py
|
|
@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
|
|||
|
||||
setuptools.setup(
|
||||
name="randonautentropy",
|
||||
version="1.0.2",
|
||||
version="1.0.3",
|
||||
author="randogoth",
|
||||
author_email="randogoth@posteo.org",
|
||||
description="Python API for interacting with The Randonautica Quantum Random Number Generator",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue