-
-
Save ZenulAbidin/ac00845048c36ceb81df6bc47cbcb4e5 to your computer and use it in GitHub Desktop.
Birthday problem but applied to randomly generated OpenSSL keys.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# First, run this in shell: | |
# j=1000 # Sample size, feel free to change. | |
# for ((i=0; $i<$j; i++)); do openssl rand -hex 32 >> ~/Documents/randalysis.txt; echo -en "\n" >> ~/Documents/randalysis.txt; done | |
# sed -i '/^\s*$/d' ~/Documents/randalysis.txt | |
# pip install bitarray | |
import bitarray | |
import bitarray.util | |
from os.path import expanduser | |
sample=1000 # This is the number of example private keys you have generated above. | |
nkeys = 260 # This is the number of keys you want, change it accordingly. | |
home = expanduser("~") | |
with open(home+"/Documents/randalysis.txt", "r") as fp: | |
s = fp.read() | |
l = s.split("\n") | |
l = l[:-1] # Remove extraneous blank element | |
cl = [0]*256 | |
delta = [0]*256 | |
# Values closer to zero - more likely to be zero, values closer to one - more likely to be one | |
for i in l: | |
ba = bitarray.util.hex2ba(i) | |
ba.reverse() | |
for j in range(0, 256): | |
cl[j] += ba[j] | |
delta[j] = cl[j]/sample | |
# Values negative - more likely to be zero, values positive - more likely to be one | |
# Because values will be between -0.5 and 0.5, we must "explode" this | |
# (by two to get values from -1 to 1) | |
# to get percentages between 0% and 100% for likely zero and likely one. | |
deltat = [((delta[t] - 0.5)*2, t) for t in range(0,256)] | |
deltat = sorted(deltat, key=lambda x: abs(x[0]), reverse=True) | |
#deltat.sort(key=lambda x: x[0]) | |
#deltatmin = [t for t in deltat if t[0] < 0.5] | |
#deltatmax = [t for t in deltat if t[0] > 0.5] | |
#deltatmax.sort(key=lambda x: x[0], reverse=True) | |
#deltateq = [t for t in deltat if t[0] == 0.5] | |
#delta = [d - 0.5 for d in delta] | |
import itertools | |
lz = [] | |
# Adjust this value to return the combinations of probabilities for larger groups of bits. | |
# Warning: you should experiment with this setting, because setting this too high will | |
# make so many combinations, it will finish your RAM. | |
# Probability theory means that the probability of multiple bits having some specific values is | |
# __MUCH LESS__ than the probability of one bit having a aprticular value. | |
maxcomb = 2 | |
for i in range(1,maxcomb+1): | |
cdt = itertools.combinations(deltat, i) | |
for c in cdt: | |
total_prob = 1 | |
bit_configs = [] | |
for it in c: | |
if it[0] < 0: | |
# Zero | |
bit_configs.append((it[1], 0)) | |
elif it[0] < 1: | |
# One | |
bit_configs.append((it[1], 1)) | |
else: | |
# perfectly even, no bias here so skip to next one | |
continue | |
total_prob *= abs(it[0]) | |
lz.append((total_prob*100, bit_configs)) | |
lz.sort(key = lambda x: x[0], reverse=True) | |
import pprint | |
print("========== TOP {} MOST LIKELY BIT CONFIGURATIONS (Highest probability first) ==========".format(nkeys)) | |
print("Output format: <probability> [(<bit number between 0-255>, <0 or 1>), ...]") | |
pprint.pprint(lz[0:nkeys]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment