Uploaded Test files
This commit is contained in:
parent
f584ad9d97
commit
2e81cb7d99
16627 changed files with 2065359 additions and 102444 deletions
172
venv/Lib/site-packages/notebook/auth/security.py
Normal file
172
venv/Lib/site-packages/notebook/auth/security.py
Normal file
|
@ -0,0 +1,172 @@
|
|||
"""
|
||||
Password generation for the Notebook.
|
||||
"""
|
||||
|
||||
from contextlib import contextmanager
|
||||
import getpass
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import random
|
||||
import traceback
|
||||
import warnings
|
||||
|
||||
from ipython_genutils.py3compat import cast_bytes, str_to_bytes, cast_unicode
|
||||
from traitlets.config import Config, ConfigFileNotFound, JSONFileConfigLoader
|
||||
from jupyter_core.paths import jupyter_config_dir
|
||||
|
||||
# Length of the salt in nr of hex chars, which implies salt_len * 4
|
||||
# bits of randomness.
|
||||
salt_len = 12
|
||||
|
||||
|
||||
def passwd(passphrase=None, algorithm='argon2'):
|
||||
"""Generate hashed password and salt for use in notebook configuration.
|
||||
|
||||
In the notebook configuration, set `c.NotebookApp.password` to
|
||||
the generated string.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
passphrase : str
|
||||
Password to hash. If unspecified, the user is asked to input
|
||||
and verify a password.
|
||||
algorithm : str
|
||||
Hashing algorithm to use (e.g, 'sha1' or any argument supported
|
||||
by :func:`hashlib.new`, or 'argon2').
|
||||
|
||||
Returns
|
||||
-------
|
||||
hashed_passphrase : str
|
||||
Hashed password, in the format 'hash_algorithm:salt:passphrase_hash'.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> passwd('mypassword')
|
||||
'sha1:7cf3:b7d6da294ea9592a9480c8f52e63cd42cfb9dd12'
|
||||
|
||||
"""
|
||||
if passphrase is None:
|
||||
for i in range(3):
|
||||
p0 = getpass.getpass('Enter password: ')
|
||||
p1 = getpass.getpass('Verify password: ')
|
||||
if p0 == p1:
|
||||
passphrase = p0
|
||||
break
|
||||
else:
|
||||
print('Passwords do not match.')
|
||||
else:
|
||||
raise ValueError('No matching passwords found. Giving up.')
|
||||
|
||||
if algorithm == 'argon2':
|
||||
from argon2 import PasswordHasher
|
||||
ph = PasswordHasher(
|
||||
memory_cost=10240,
|
||||
time_cost=10,
|
||||
parallelism=8,
|
||||
)
|
||||
h = ph.hash(passphrase)
|
||||
|
||||
return ':'.join((algorithm, cast_unicode(h, 'ascii')))
|
||||
else:
|
||||
h = hashlib.new(algorithm)
|
||||
salt = ('%0' + str(salt_len) + 'x') % random.getrandbits(4 * salt_len)
|
||||
h.update(cast_bytes(passphrase, 'utf-8') + str_to_bytes(salt, 'ascii'))
|
||||
|
||||
return ':'.join((algorithm, salt, h.hexdigest()))
|
||||
|
||||
|
||||
def passwd_check(hashed_passphrase, passphrase):
|
||||
"""Verify that a given passphrase matches its hashed version.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
hashed_passphrase : str
|
||||
Hashed password, in the format returned by `passwd`.
|
||||
passphrase : str
|
||||
Passphrase to validate.
|
||||
|
||||
Returns
|
||||
-------
|
||||
valid : bool
|
||||
True if the passphrase matches the hash.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from notebook.auth.security import passwd_check
|
||||
>>> passwd_check('argon2:...', 'mypassword')
|
||||
True
|
||||
|
||||
>>> passwd_check('argon2:...', 'otherpassword')
|
||||
False
|
||||
|
||||
>>> passwd_check('sha1:0e112c3ddfce:a68df677475c2b47b6e86d0467eec97ac5f4b85a',
|
||||
... 'mypassword')
|
||||
True
|
||||
"""
|
||||
if hashed_passphrase.startswith('argon2:'):
|
||||
import argon2
|
||||
import argon2.exceptions
|
||||
ph = argon2.PasswordHasher()
|
||||
try:
|
||||
return ph.verify(hashed_passphrase[7:], passphrase)
|
||||
except argon2.exceptions.VerificationError:
|
||||
return False
|
||||
else:
|
||||
try:
|
||||
algorithm, salt, pw_digest = hashed_passphrase.split(':', 2)
|
||||
except (ValueError, TypeError):
|
||||
return False
|
||||
|
||||
try:
|
||||
h = hashlib.new(algorithm)
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
if len(pw_digest) == 0:
|
||||
return False
|
||||
|
||||
h.update(cast_bytes(passphrase, 'utf-8') + cast_bytes(salt, 'ascii'))
|
||||
|
||||
return h.hexdigest() == pw_digest
|
||||
|
||||
@contextmanager
|
||||
def persist_config(config_file=None, mode=0o600):
|
||||
"""Context manager that can be used to modify a config object
|
||||
|
||||
On exit of the context manager, the config will be written back to disk,
|
||||
by default with user-only (600) permissions.
|
||||
"""
|
||||
|
||||
if config_file is None:
|
||||
config_file = os.path.join(jupyter_config_dir(), 'jupyter_notebook_config.json')
|
||||
|
||||
os.makedirs(os.path.dirname(config_file), exist_ok=True)
|
||||
|
||||
loader = JSONFileConfigLoader(os.path.basename(config_file), os.path.dirname(config_file))
|
||||
try:
|
||||
config = loader.load_config()
|
||||
except ConfigFileNotFound:
|
||||
config = Config()
|
||||
|
||||
yield config
|
||||
|
||||
with io.open(config_file, 'w', encoding='utf8') as f:
|
||||
f.write(cast_unicode(json.dumps(config, indent=2)))
|
||||
|
||||
try:
|
||||
os.chmod(config_file, mode)
|
||||
except Exception as e:
|
||||
tb = traceback.format_exc()
|
||||
warnings.warn("Failed to set permissions on %s:\n%s" % (config_file, tb),
|
||||
RuntimeWarning)
|
||||
|
||||
|
||||
def set_password(password=None, config_file=None):
|
||||
"""Ask user for password, store it in notebook json configuration file"""
|
||||
|
||||
hashed_password = passwd(password)
|
||||
|
||||
with persist_config(config_file) as config:
|
||||
config.NotebookApp.password = hashed_password
|
Loading…
Add table
Add a link
Reference in a new issue