Files
ppgen/ppgen.py
2025-12-10 13:38:11 +11:00

103 lines
2.7 KiB
Python
Executable File

#!/usr/bin/python3
from math import *
import random
import string
import sys
import os
from common import *
from longrandom import LongRandom
from worddict import words
print("Content-Type: text/html")
print()
qs = os.environ.get('QUERY_STRING', None)
if not qs:
minlen = 1
maxlen = 8
numlen = 2
wordcount = 3
extra_symbols = ''
randcaps = 'first'
else:
form = cgi.FieldStorage()
wordcount = form_get(form, 'wordcount', 3, int)
minlen = form_get(form, 'minlen', 2, int)
maxlen = form_get(form, 'maxlen', 8, int)
numlen = form_get(form, 'numlen', 2, int)
randcaps = form_get(form, 'randcaps', 'first', str)
dumpfile('header.html', {'type':'Passphrase'})
dict = EvalDict(vars())
here = os.path.dirname(__file__)
form_path = os.path.join(here, 'ppform.html')
with open(form_path, encoding="utf-8") as f:
sys.stdout.write(f.read() % dict)
usewords = [ ]
totalen = 0
for i in range(minlen, maxlen+1):
totalen += len(words[i]) * i
usewords.extend(words[i])
log_2 = log(2)
wordbits = log(len(usewords)) / log_2
medlen = len(usewords[len(usewords)//2])
avglen = totalen / len(usewords)
if randcaps == 'first':
capbits = 1
capmult = 2
elif randcaps == 'one':
# Use estimate based on average word length
capbits = log(avglen+1) / log_2
capmult = avglen+1
elif randcaps == 'all':
# One bit per average word length
capbits = avglen
capmult = 2**avglen
else:
capbits = 0
capmult = 1
numbits = log(10) * numlen / log_2
numfmt = '{{:0{}}}'.format(numlen)
passbits = (wordbits + capbits) * wordcount + numbits * ((wordcount - 1) or 1)
table_start()
row('Word count', commafy(len(usewords)))
row('Average word length', '%.2f' % avglen)
row('Bits per word', '%.2f' % wordbits)
row('Bits per number', '%.2f' % numbits)
row('Bits for capitalization', '%.2f' % (capbits * wordcount))
row('Effective passphrase bits', int(passbits))
row('Total possible combinations',
commafy(len(usewords)**wordcount * (10**numlen)**((wordcount-1) or 1) * capmult**wordcount))
table_end()
randval = LongRandom()
table_start()
print("<tr><th>Passphrase</th></tr>")
for i in range(10):
passphrase = ''
for j in range(wordcount):
word = usewords[randval.get(len(usewords))]
if randcaps == 'first':
if randval.get(2):
word = word[0].upper() + word[1:]
elif randcaps == 'one':
k = randval.get(len(word)+1)
if k < len(word):
word = word[:k] + word[k].upper() + word[k+1:]
elif randcaps == 'all':
word = ''.join([ randval.get(2) and ch.upper() or ch.lower()
for ch in word ])
passphrase += word
if numlen > 0 and (j < wordcount-1 or wordcount == 1):
passphrase += numfmt.format(randval.get(10 ** numlen))
print("<tr><td><tt>%s</tt></td></tr>" % escape(passphrase))
table_end()
dumpfile('footer.html')