brent s
d7d85c7d9d
since print() was made a function in py3, i can predict at some point that return will be made a func as well. sure, good. but "return()" *currently* returns an empty tuple. We want to explicitly return None for testing purposes.
83 lines
3.6 KiB
Python
Executable File
83 lines
3.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import binascii
|
|
import getpass
|
|
import sys
|
|
##
|
|
# from passlib.utils import pbkdf2 # deprecated
|
|
from passlib.crypto.digest import pbkdf2_hmac
|
|
|
|
|
|
def pskGen(ssid, passphrase):
|
|
# raw_psk = pbkdf2.pbkdf2(str(passphrase), str(ssid), 4096, 32) # deprecated
|
|
raw_psk = pbkdf2_hmac('sha1', str(passphrase), str(ssid), 4096, 32)
|
|
hex_psk = binascii.hexlify(raw_psk)
|
|
str_psk = hex_psk.decode('utf-8')
|
|
return(str_psk)
|
|
|
|
|
|
def parseArgs():
|
|
def essidchk(essid):
|
|
essid = str(essid)
|
|
if len(essid) > 32:
|
|
raise argparse.ArgumentTypeError('The maximum length of an ESSID is 32 characters')
|
|
return(essid)
|
|
|
|
def passphrasechk(passphrase):
|
|
if passphrase:
|
|
is_piped = False
|
|
passphrase = str(passphrase)
|
|
if passphrase == '-':
|
|
if sys.stdin.isatty():
|
|
raise argparse.ArgumentTypeError(('[STDIN] You specified a passphrase to be entered but did not '
|
|
'provide one via a pipe.'))
|
|
else:
|
|
is_piped = True
|
|
try:
|
|
# WPA-PSK only accepts ASCII for passphrase.
|
|
raw_pass = sys.stdin.read().encode('utf-8').decode('ascii').strip('\r').strip('\n')
|
|
except UnicodeDecodeError:
|
|
raise argparse.ArgumentTypeError('[STDIN] WPA-PSK passphrases must be an ASCII string')
|
|
if not 7 < len(passphrase) < 64:
|
|
raise argparse.ArgumentTypeError(('{0}WPA-PSK passphrases must be no shorter than 8 characters'
|
|
' and no longer than 63 characters. '
|
|
'Please ensure you have provided the '
|
|
'correct passphrase.').format(('[STDIN] ' if is_piped else '')))
|
|
return(passphrase)
|
|
|
|
args = argparse.ArgumentParser(description = 'Generate a PSK from a passphrase')
|
|
args.add_argument('-p', '--passphrase',
|
|
dest = 'passphrase',
|
|
default = None,
|
|
type = passphrasechk,
|
|
help = ('If specified, use this passphrase (otherwise securely interactively prompt for it). '
|
|
'If "-" (without quotes), read from stdin (via a pipe). '
|
|
'WARNING: THIS OPTION IS INSECURE AND MAY EXPOSE THE PASSPHRASE GIVEN '
|
|
'TO OTHER PROCESSES ON THIS SYSTEM'))
|
|
args.add_argument('ssid',
|
|
metavar = 'ESSID',
|
|
type = essidchk,
|
|
help = ('The ESSID (network name) to use for this passphrase. '
|
|
'(This is required because WPA-PSK uses it to salt the key derivation)'))
|
|
return(args)
|
|
|
|
|
|
def main():
|
|
args = parseArgs().parse_args()
|
|
if not args.passphrase:
|
|
args.passphrase = getpass.getpass(('Please enter the passphrase for '
|
|
'network "{0}" (will NOT echo back): ').format(args.ssid))
|
|
args.passphrase = args.passphrase.encode('utf-8').decode('ascii').strip('\r').strip('\n')
|
|
if not 7 < len(args.passphrase) < 64:
|
|
raise ValueError(('WPA-PSK passphrases must be no shorter than 8 characters'
|
|
' and no longer than 63 characters. '
|
|
'Please ensure you have provided the correct passphrase.'))
|
|
psk = pskGen(args.ssid, args.passphrase)
|
|
print('PSK for network "{0}": {1}'.format(args.ssid, psk))
|
|
return(None)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|