Remove ed25519, add pynacl, documentation updates and preparation for PyPI

This commit is contained in:
= 2019-09-14 02:38:56 -05:00
parent f000e564f9
commit fff2d3e244
Signed by: kiichan
GPG key ID: 619DFD67F0976616
24 changed files with 404 additions and 82 deletions

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
__author__ = 'Miroslav Shubernetskiy | Keaton Brown'
__email__ = 'miroslav@miki725.com | kii-chan@tutanota.com'
__version__ = '0.1.0'
__author__ = 'Keaton Brown'
__email__ = 'kii-chan@tutanota.com'
__version__ = '0.2.0'

View file

@ -3,7 +3,8 @@
from collections import OrderedDict
import os
import ed25519
from nacl import signing
from nacl.exceptions import BadSignatureError
from django.utils.crypto import constant_time_compare, salted_hmac
from .utils import Base64, Encoder
@ -89,6 +90,8 @@ class Ed25519(object):
def __init__(self, public_key, private_key, msg):
self.public_key = public_key
self.private_key = private_key
if private_key and type(private_key) == bytes:
self.private_key = private_key[:32]
self.msg = msg
def is_signature_valid(self, other_signature):
@ -101,10 +104,10 @@ class Ed25519(object):
Boolean indicating whether validation has succeeded.
"""
try:
vk = ed25519.VerifyingKey(self.public_key)
vk.verify(other_signature, self.msg)
vk = signing.VerifyKey(self.public_key)
vk.verify(self.msg, other_signature)
return True
except (AssertionError, ed25519.BadSignatureError):
except (AssertionError, BadSignatureError) as e:
return False
def sign_data(self):
@ -116,8 +119,8 @@ class Ed25519(object):
bytes
ed25519 signature
"""
sk = ed25519.SigningKey(self.private_key)
return sk.sign(self.msg)
sk = signing.SigningKey(self.private_key)
return sk.sign(self.msg).signature
def generate_randomness(size=32):

View file

@ -1,46 +0,0 @@
{% load static %}
<!doctype html>
<html lang="en">
<head>
<title>{% block title %}SQRL Test{% endblock %}</title>
</head>
<body>
<header>
{% block header %}
<div>SQRL Test Server</div>
<nav>
{% if user.is_authenticated %}
Logged in as {{ user.username }}
{% endif %}
<ul>
{% if user.is_authenticated %}
<li>
<a href="{% url 'logout' %}">Log out</a>
</li>
<li>
<a href="{% url 'sqrl:manage' %}">Manage SQRL</a>
</li>
{% else %}
<li>
<a href="{% url 'sqrl:login' %}">Log In</a>
</li>
{% endif %}
</ul>
</nav>
{% endblock %}
</header>
<div id="content">
{% block content %}
{% endblock content %}
</div>
{% block scripts %}
{% endblock %}
</body>
</html>

View file

@ -12,7 +12,7 @@
</p>
{% sqrl as sqrl_session %}
{% sqrl_login_dropin sqrl_session login %}
{% sqrl_login_dropin sqrl_session "sqrl:login" %}
{% endblock %}
{% comment %}
@ -23,5 +23,6 @@ All necessary data should already be in the context.
Please note again that this template is for SQRL-exclusive logins.
If you would like to add SQRL login to an existing login page,
you should rather adjust that template as it is probably way more involved.
you should rather adjust that template as it is probably way more involved
to add that here.
{% endcomment %}

View file

@ -15,7 +15,7 @@ def sqrl(context):
@register.inclusion_tag('sqrl/sqrl-dropin.html')
def sqrl_login_dropin(sqrl_session, redir=""):
def sqrl_login_dropin(sqrl_session, redir="sqrl:login"):
"""
Creates a drop-in SQRL element in your template pages.
Add it to your login template to make it SQRL-aware.

View file

@ -4,7 +4,8 @@ from collections import OrderedDict
from django.conf import settings
import os
import ed25519
from nacl import signing
from nacl.exceptions import BadSignatureError
import mock
from ..crypto import HMAC, Ed25519, generate_randomness
@ -111,11 +112,11 @@ class TestEd25519(unittest.TestCase):
b'\x97\x145\x90N[\xb9\xfc\x8e\x8a\x9e\xd2=\xad\x84\xcd\xf1\x93\x06'
)
@mock.patch('ed25519.SigningKey')
@mock.patch('nacl.signing.SigningKey')
def test_sign_data_mock(self, mock_signing_key):
signature = self.sig.sign_data()
self.assertEqual(signature, mock_signing_key.return_value.sign.return_value)
self.assertEqual(signature, mock_signing_key.return_value.sign.return_value.signature)
mock_signing_key.assert_called_once_with(self.sig.private_key)
mock_signing_key.return_value.sign.assert_called_once_with(self.sig.msg)
@ -125,17 +126,17 @@ class TestEd25519(unittest.TestCase):
self.assertTrue(self.sig.is_signature_valid(signature))
self.assertFalse(self.sig.is_signature_valid(b'a' + signature[:-1]))
@mock.patch('ed25519.VerifyingKey')
@mock.patch('nacl.signing.VerifyKey')
def test_is_signature_mock(self, mock_verifying_key):
is_valid = self.sig.is_signature_valid(mock.sentinel.signature)
self.assertTrue(is_valid)
mock_verifying_key.assert_called_once_with(self.sig.public_key)
mock_verifying_key.return_value.verify.assert_called_once_with(
mock.sentinel.signature, self.data
self.data, mock.sentinel.signature
)
@mock.patch('ed25519.VerifyingKey')
@mock.patch('nacl.signing.VerifyKey')
def test_is_signature_mock_assertion_error(self, mock_verifying_key):
mock_verifying_key.return_value.verify.side_effect = AssertionError
@ -144,19 +145,19 @@ class TestEd25519(unittest.TestCase):
self.assertFalse(is_valid)
mock_verifying_key.assert_called_once_with(self.sig.public_key)
mock_verifying_key.return_value.verify.assert_called_once_with(
mock.sentinel.signature, self.data
self.data, mock.sentinel.signature
)
@mock.patch('ed25519.VerifyingKey')
def test_is_signature_mock_bas_signature_error(self, mock_verifying_key):
mock_verifying_key.return_value.verify.side_effect = ed25519.BadSignatureError
@mock.patch('nacl.signing.VerifyKey')
def test_is_signature_mock_bad_signature_error(self, mock_verifying_key):
mock_verifying_key.return_value.verify.side_effect = BadSignatureError
is_valid = self.sig.is_signature_valid(mock.sentinel.signature)
self.assertFalse(is_valid)
mock_verifying_key.assert_called_once_with(self.sig.public_key)
mock_verifying_key.return_value.verify.assert_called_once_with(
mock.sentinel.signature, self.data
self.data, mock.sentinel.signature
)

View file

@ -2,7 +2,7 @@
import unittest
from collections import OrderedDict
import ed25519
from nacl import signing
import mock
from django import forms, test
from django.contrib.auth import SESSION_KEY, get_user_model
@ -19,9 +19,10 @@ TESTING_MODULE = 'sqrl.forms'
class TestRequestForm(test.TestCase):
def get_key_pair(self):
signing_key, verifying_key = ed25519.create_keypair()
signing_key = signing_key.to_bytes()
verifying_key = verifying_key.to_bytes()
signing_key = signing.SigningKey.generate()
verifying_key = signing_key.verify_key
signing_key = signing_key._signing_key
verifying_key = verifying_key._key
return signing_key, verifying_key

View file

@ -59,7 +59,7 @@ class TestSQRLStatusView(test.TestCase):
def test_get_success_url_complete_registration(self):
self.view.request.GET['url'] = '?next={}'.format(reverse('sqrl:login'))
self.view.request.user.is_authenticated.return_value = False
self.view.request.user.is_authenticated = False
self.view.request.session = {SQRL_IDENTITY_SESSION_KEY: ''}
self.assertEqual(

View file

@ -16,7 +16,7 @@ urlpatterns = [
path("auth/", SQRLAuthView.as_view(), name="auth"),
path("login/", SQRLLoginView.as_view(), name="login"),
path("manage/", SQRLIdentityManagementView.as_view(), name='manage'),
path("register/",SQRLCompleteRegistrationView.as_view(), name='complete-registration'),
path("register/", SQRLCompleteRegistrationView.as_view(), name='complete-registration'),
re_path(r"^status/(?P<transaction>[A-Za-z0-9_-]{43})/$", SQRLStatusView.as_view(), name='status'),
path('admin/sqrl_manage/', AdminSiteSQRLIdentityManagementView.as_view(), name='admin-sqrl_manage'),
]