From 3fe9472d27b1475a9030441c7d229eab012f4c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 3 Mar 2017 14:16:29 +0100 Subject: [PATCH] Python 3.6 compatibility: random bits & bcrypt Switched from Sybren's RSA library to the new stdlib module 'secrets' to generate secret tokens. This also means that the rsa library was demoted to secondary requirement. --- pillar/api/local_auth.py | 8 ++++++-- pillar/api/nodes/__init__.py | 15 ++++++++++----- requirements.txt | 4 ++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/pillar/api/local_auth.py b/pillar/api/local_auth.py index 091c521b..19da1f84 100644 --- a/pillar/api/local_auth.py +++ b/pillar/api/local_auth.py @@ -5,7 +5,6 @@ import typing import bcrypt import datetime -import rsa.randnum from bson import tz_util from flask import abort, Blueprint, current_app, jsonify, request from pillar.api.utils.authentication import create_new_user_document @@ -77,7 +76,12 @@ def generate_and_store_token(user_id, days=15, prefix=b''): :return: the token document. """ - random_bits = rsa.randnum.read_random_bits(256) + if not isinstance(prefix, bytes): + raise TypeError('prefix must be bytes, not %s' % type(prefix)) + + import secrets + + random_bits = secrets.token_bytes(32) # Use 'xy' as altargs to prevent + and / characters from appearing. # We never have to b64decode the string anyway. diff --git a/pillar/api/nodes/__init__.py b/pillar/api/nodes/__init__.py index fab323fa..f2e65db6 100644 --- a/pillar/api/nodes/__init__.py +++ b/pillar/api/nodes/__init__.py @@ -4,7 +4,6 @@ import logging import urllib.parse import pymongo.errors -import rsa.randnum import werkzeug.exceptions as wz_exceptions from bson import ObjectId from flask import current_app, g, Blueprint, request @@ -150,13 +149,19 @@ def make_world_gettable(node): node_id) -def create_short_code(node): +def create_short_code(node) -> str: """Generates a new 'short code' for the node.""" + import secrets + length = current_app.config['SHORT_CODE_LENGTH'] - bits = rsa.randnum.read_random_bits(32) - short_code = base64.b64encode(bits, altchars='xy').rstrip('=') - short_code = short_code[:length] + + # Base64 encoding will expand it a bit, so we'll cut that off later. + # It's a good idea to start with enough bytes, though. + bits = secrets.token_bytes(length) + + short_code = base64.b64encode(bits, altchars=b'xy').rstrip(b'=') + short_code = short_code[:length].decode('ascii') return short_code diff --git a/requirements.txt b/requirements.txt index fea38733..84adc51a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ attrs==16.2.0 algoliasearch==1.8.0 -bcrypt==2.0.0 +bcrypt==3.1.3 blinker==1.4 bugsnag==2.3.1 bleach==1.4.3 @@ -27,7 +27,6 @@ pycrypto==2.6.1 pyOpenSSL==0.15.1 python-dateutil==2.5.3 requests==2.9.1 -rsa==3.4.2 simplejson==3.8.2 WebOb==1.5.0 wheel==0.29.0 @@ -52,5 +51,6 @@ pyasn1-modules==0.0.8 pymongo==3.2.2 pyparsing==2.1.10 requests-oauthlib==0.7.0 +rsa==3.4.2 six==1.10.0 WTForms==2.1