##// END OF EJS Templates
Mark passwd doctest example as random output
Nikita Kniazev -
Show More
@@ -1,114 +1,114
1 """
1 """
2 Password generation for the IPython notebook.
2 Password generation for the IPython notebook.
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Imports
5 # Imports
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Stdlib
7 # Stdlib
8 import getpass
8 import getpass
9 import hashlib
9 import hashlib
10 import random
10 import random
11
11
12 # Our own
12 # Our own
13 from IPython.core.error import UsageError
13 from IPython.core.error import UsageError
14 from IPython.utils.py3compat import encode
14 from IPython.utils.py3compat import encode
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Globals
17 # Globals
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 # Length of the salt in nr of hex chars, which implies salt_len * 4
20 # Length of the salt in nr of hex chars, which implies salt_len * 4
21 # bits of randomness.
21 # bits of randomness.
22 salt_len = 12
22 salt_len = 12
23
23
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25 # Functions
25 # Functions
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27
27
28 def passwd(passphrase=None, algorithm='sha1'):
28 def passwd(passphrase=None, algorithm='sha1'):
29 """Generate hashed password and salt for use in notebook configuration.
29 """Generate hashed password and salt for use in notebook configuration.
30
30
31 In the notebook configuration, set `c.NotebookApp.password` to
31 In the notebook configuration, set `c.NotebookApp.password` to
32 the generated string.
32 the generated string.
33
33
34 Parameters
34 Parameters
35 ----------
35 ----------
36 passphrase : str
36 passphrase : str
37 Password to hash. If unspecified, the user is asked to input
37 Password to hash. If unspecified, the user is asked to input
38 and verify a password.
38 and verify a password.
39 algorithm : str
39 algorithm : str
40 Hashing algorithm to use (e.g, 'sha1' or any argument supported
40 Hashing algorithm to use (e.g, 'sha1' or any argument supported
41 by :func:`hashlib.new`).
41 by :func:`hashlib.new`).
42
42
43 Returns
43 Returns
44 -------
44 -------
45 hashed_passphrase : str
45 hashed_passphrase : str
46 Hashed password, in the format 'hash_algorithm:salt:passphrase_hash'.
46 Hashed password, in the format 'hash_algorithm:salt:passphrase_hash'.
47
47
48 Examples
48 Examples
49 --------
49 --------
50 >>> passwd('mypassword')
50 >>> passwd('mypassword')
51 'sha1:7cf3:b7d6da294ea9592a9480c8f52e63cd42cfb9dd12'
51 'sha1:7cf3:b7d6da294ea9592a9480c8f52e63cd42cfb9dd12' # random
52
52
53 """
53 """
54 if passphrase is None:
54 if passphrase is None:
55 for i in range(3):
55 for i in range(3):
56 p0 = getpass.getpass('Enter password: ')
56 p0 = getpass.getpass('Enter password: ')
57 p1 = getpass.getpass('Verify password: ')
57 p1 = getpass.getpass('Verify password: ')
58 if p0 == p1:
58 if p0 == p1:
59 passphrase = p0
59 passphrase = p0
60 break
60 break
61 else:
61 else:
62 print('Passwords do not match.')
62 print('Passwords do not match.')
63 else:
63 else:
64 raise UsageError('No matching passwords found. Giving up.')
64 raise UsageError('No matching passwords found. Giving up.')
65
65
66 h = hashlib.new(algorithm)
66 h = hashlib.new(algorithm)
67 salt = ('%0' + str(salt_len) + 'x') % random.getrandbits(4 * salt_len)
67 salt = ('%0' + str(salt_len) + 'x') % random.getrandbits(4 * salt_len)
68 h.update(encode(passphrase, 'utf-8') + encode(salt, 'ascii'))
68 h.update(encode(passphrase, 'utf-8') + encode(salt, 'ascii'))
69
69
70 return ':'.join((algorithm, salt, h.hexdigest()))
70 return ':'.join((algorithm, salt, h.hexdigest()))
71
71
72
72
73 def passwd_check(hashed_passphrase, passphrase):
73 def passwd_check(hashed_passphrase, passphrase):
74 """Verify that a given passphrase matches its hashed version.
74 """Verify that a given passphrase matches its hashed version.
75
75
76 Parameters
76 Parameters
77 ----------
77 ----------
78 hashed_passphrase : str
78 hashed_passphrase : str
79 Hashed password, in the format returned by `passwd`.
79 Hashed password, in the format returned by `passwd`.
80 passphrase : str
80 passphrase : str
81 Passphrase to validate.
81 Passphrase to validate.
82
82
83 Returns
83 Returns
84 -------
84 -------
85 valid : bool
85 valid : bool
86 True if the passphrase matches the hash.
86 True if the passphrase matches the hash.
87
87
88 Examples
88 Examples
89 --------
89 --------
90 >>> from IPython.lib.security import passwd_check
90 >>> from IPython.lib.security import passwd_check
91 >>> passwd_check('sha1:0e112c3ddfce:a68df677475c2b47b6e86d0467eec97ac5f4b85a',
91 >>> passwd_check('sha1:0e112c3ddfce:a68df677475c2b47b6e86d0467eec97ac5f4b85a',
92 ... 'mypassword')
92 ... 'mypassword')
93 True
93 True
94
94
95 >>> passwd_check('sha1:0e112c3ddfce:a68df677475c2b47b6e86d0467eec97ac5f4b85a',
95 >>> passwd_check('sha1:0e112c3ddfce:a68df677475c2b47b6e86d0467eec97ac5f4b85a',
96 ... 'anotherpassword')
96 ... 'anotherpassword')
97 False
97 False
98 """
98 """
99 try:
99 try:
100 algorithm, salt, pw_digest = hashed_passphrase.split(':', 2)
100 algorithm, salt, pw_digest = hashed_passphrase.split(':', 2)
101 except (ValueError, TypeError):
101 except (ValueError, TypeError):
102 return False
102 return False
103
103
104 try:
104 try:
105 h = hashlib.new(algorithm)
105 h = hashlib.new(algorithm)
106 except ValueError:
106 except ValueError:
107 return False
107 return False
108
108
109 if len(pw_digest) == 0:
109 if len(pw_digest) == 0:
110 return False
110 return False
111
111
112 h.update(encode(passphrase, 'utf-8') + encode(salt, 'ascii'))
112 h.update(encode(passphrase, 'utf-8') + encode(salt, 'ascii'))
113
113
114 return h.hexdigest() == pw_digest
114 return h.hexdigest() == pw_digest
General Comments 0
You need to be logged in to leave comments. Login now