Add CSPRNG option: --securerandom

This commit is contained in:
Kevin Cathcart
2020-06-26 20:12:30 -04:00
parent 90d1353ae6
commit 4ad31d641b
11 changed files with 62 additions and 11 deletions

View File

@@ -1,5 +1,5 @@
import logging import logging
import random import RaceRandom as random
from BaseClasses import Boss from BaseClasses import Boss
from Fill import FillError from Fill import FillError

View File

@@ -1,4 +1,4 @@
import random import RaceRandom as random
from BaseClasses import Dungeon from BaseClasses import Dungeon
from Bosses import BossFactory from Bosses import BossFactory

View File

@@ -2,7 +2,7 @@
import argparse import argparse
import os import os
import logging import logging
import random import RaceRandom as random
import textwrap import textwrap
import sys import sys
@@ -255,6 +255,7 @@ def start():
parser.add_argument('--shufflepalette', default=False, action='store_true') parser.add_argument('--shufflepalette', default=False, action='store_true')
parser.add_argument('--shufflepots', default=False, action='store_true') parser.add_argument('--shufflepots', default=False, action='store_true')
parser.add_argument('--multi', default=1, type=lambda value: min(max(int(value), 1), 255)) parser.add_argument('--multi', default=1, type=lambda value: min(max(int(value), 1), 255))
parser.add_argument('--securerandom', default=False, action='store_true')
parser.add_argument('--outputpath') parser.add_argument('--outputpath')
args = parser.parse_args() args = parser.parse_args()

View File

@@ -1,4 +1,4 @@
import random import RaceRandom as random
# ToDo: With shuffle_ganon option, prevent gtower from linking to an exit only location through a 2 entrance cave. # ToDo: With shuffle_ganon option, prevent gtower from linking to an exit only location through a 2 entrance cave.
from collections import defaultdict from collections import defaultdict

View File

@@ -1,4 +1,4 @@
import random import RaceRandom as random
import logging import logging
from BaseClasses import CollectionState from BaseClasses import CollectionState

2
Gui.py
View File

@@ -2,7 +2,7 @@
from argparse import Namespace from argparse import Namespace
from glob import glob from glob import glob
import json import json
import random import RaceRandom as random
import os import os
import shutil import shutil
from tkinter import Checkbutton, OptionMenu, Toplevel, LabelFrame, PhotoImage, Tk, LEFT, RIGHT, BOTTOM, TOP, StringVar, IntVar, Frame, Label, W, E, X, BOTH, Entry, Spinbox, Button, filedialog, messagebox, ttk from tkinter import Checkbutton, OptionMenu, Toplevel, LabelFrame, PhotoImage, Tk, LEFT, RIGHT, BOTTOM, TOP, StringVar, IntVar, Frame, Label, W, E, X, BOTH, Entry, Spinbox, Button, filedialog, messagebox, ttk

View File

@@ -1,6 +1,6 @@
from collections import namedtuple from collections import namedtuple
import logging import logging
import random import RaceRandom as random
from BaseClasses import Region, RegionType, Shop, ShopType, Location from BaseClasses import Region, RegionType, Shop, ShopType, Location
from Bosses import place_bosses from Bosses import place_bosses

View File

@@ -4,7 +4,7 @@ from itertools import zip_longest
import json import json
import logging import logging
import os import os
import random import RaceRandom as random
import time import time
from BaseClasses import World, CollectionState, Item, Region, Location, Shop from BaseClasses import World, CollectionState, Item, Region, Location, Shop
@@ -23,6 +23,9 @@ __version__ = '0.6.3-pre'
def main(args, seed=None): def main(args, seed=None):
start = time.perf_counter() start = time.perf_counter()
if args.securerandom:
random.use_secure()
# initialize the world # initialize the world
world = World(args.multi, args.shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, not args.nodungeonitems, args.accessibility, args.shuffleganon, args.quickswap, args.fastmenu, args.disablemusic, args.keysanity, args.retro, args.custom, args.customitemarray, args.shufflebosses, args.hints) world = World(args.multi, args.shuffle, args.logic, args.mode, args.swords, args.difficulty, args.item_functionality, args.timer, args.progressive, args.goal, args.algorithm, not args.nodungeonitems, args.accessibility, args.shuffleganon, args.quickswap, args.fastmenu, args.disablemusic, args.keysanity, args.retro, args.custom, args.customitemarray, args.shufflebosses, args.hints)
logger = logging.getLogger('') logger = logging.getLogger('')
@@ -33,6 +36,9 @@ def main(args, seed=None):
world.seed = int(seed) world.seed = int(seed)
random.seed(world.seed) random.seed(world.seed)
if args.securerandom:
world.seed = None
world.crystals_needed_for_ganon = random.randint(0, 7) if args.crystals_ganon == 'random' else int(args.crystals_ganon) world.crystals_needed_for_ganon = random.randint(0, 7) if args.crystals_ganon == 'random' else int(args.crystals_ganon)
world.crystals_needed_for_gt = random.randint(0, 7) if args.crystals_gt == 'random' else int(args.crystals_gt) world.crystals_needed_for_gt = random.randint(0, 7) if args.crystals_gt == 'random' else int(args.crystals_gt)

View File

@@ -3,7 +3,7 @@ import argparse
import hashlib import hashlib
import logging import logging
import os import os
import random import RaceRandom as random
import time import time
import sys import sys

44
RaceRandom.py Normal file
View File

@@ -0,0 +1,44 @@
import random as _random
from functools import update_wrapper
__all__ = ["use_secure"]
_prng_inst = _random.Random()
_cprng_inst = _random.SystemRandom()
_mode = "prng"
def use_secure(secure=True):
# pylint: disable=global-statement
global _mode
_mode = "cprng" if secure else "prng"
def _wrap(name):
def somefunc(*args, **kwargs):
return getattr(_cprng_inst if _mode == "cprng" else _prng_inst, name)(*args, **kwargs)
update_wrapper(somefunc, getattr(_prng_inst, name))
return somefunc
# These are for intellisense purposes only, and will be overwritten below
choice = _prng_inst.choice
gauss = _prng_inst.gauss
getrandbits = _prng_inst.getrandbits
randint = _prng_inst.randint
random = _prng_inst.random
randrange = _prng_inst.randrange
sample = _prng_inst.sample
seed = _prng_inst.seed
shuffle = _prng_inst.shuffle
uniform = _prng_inst.uniform
for func_name in dir(_random):
if not callable(getattr(_random, func_name)):
continue
if not callable(getattr(_prng_inst, func_name, None)):
continue
if func_name.startswith('_'):
continue
globals()[func_name] = _wrap(func_name)
__all__.append(func_name)

4
Rom.py
View File

@@ -3,7 +3,7 @@ import json
import hashlib import hashlib
import logging import logging
import os import os
import random import RaceRandom as random
import struct import struct
import subprocess import subprocess
@@ -1043,7 +1043,7 @@ def patch_rom(world, player, rom):
# set rom name # set rom name
# 21 bytes # 21 bytes
from Main import __version__ from Main import __version__
rom.name = bytearray('ER_{0}_{1:09}\0'.format(__version__[0:7],world.seed), 'utf8') rom.name = bytearray('ER_{0}_{1}\0'.format(__version__[0:7], world.seed), 'utf8')
assert len(rom.name) <= 21 assert len(rom.name) <= 21
rom.write_bytes(0x7FC0, rom.name) rom.write_bytes(0x7FC0, rom.name)