Verified Commit aa7365b7 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Basic logic for signing/verifying requests

parent ae651903
......@@ -89,6 +89,7 @@ LOCAL_APPS = (
'funkwhale_api.music',
'funkwhale_api.requests',
'funkwhale_api.favorites',
'funkwhale_api.federation',
'funkwhale_api.radios',
'funkwhale_api.history',
'funkwhale_api.playlists',
......
import factory
import requests
import requests_http_signature
from funkwhale_api.factories import registry
from . import signing
registry.register(signing.get_key_pair, name='federation.KeyPair')
@registry.register(name='federation.SignatureAuth')
class SignatureAuthFactory(factory.Factory):
algorithm = 'rsa-sha256'
key = factory.LazyFunction(lambda: signing.get_key_pair()[0])
key_id = factory.Faker('url')
class Meta:
model = requests_http_signature.HTTPSignatureAuth
@registry.register(name='federation.SignedRequest')
class SignedRequestFactory(factory.Factory):
url = factory.Faker('url')
method = 'get'
auth = factory.SubFactory(SignatureAuthFactory)
class Meta:
model = requests.Request
from cryptography.hazmat.primitives import serialization as crypto_serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend as crypto_default_backend
def get_key_pair(size=2048):
key = rsa.generate_private_key(
backend=crypto_default_backend(),
public_exponent=65537,
key_size=size
)
private_key = key.private_bytes(
crypto_serialization.Encoding.PEM,
crypto_serialization.PrivateFormat.PKCS8,
crypto_serialization.NoEncryption())
public_key = key.public_key().public_bytes(
crypto_serialization.Encoding.PEM,
crypto_serialization.PublicFormat.PKCS1
)
return private_key, public_key
......@@ -60,3 +60,5 @@ channels_redis>=2.1,<2.2
django-cacheops>=4,<4.1
daphne==2.0.4
cryptography>=2,<3
requests-http-signature==0.0.3
......@@ -31,7 +31,11 @@ def cache():
def factories(db):
from funkwhale_api import factories
for v in factories.registry.values():
v._meta.strategy = factory.CREATE_STRATEGY
try:
v._meta.strategy = factory.CREATE_STRATEGY
except AttributeError:
# probably not a class based factory
pass
yield factories.registry
......@@ -39,7 +43,11 @@ def factories(db):
def nodb_factories():
from funkwhale_api import factories
for v in factories.registry.values():
v._meta.strategy = factory.BUILD_STRATEGY
try:
v._meta.strategy = factory.BUILD_STRATEGY
except AttributeError:
# probably not a class based factory
pass
yield factories.registry
......
import cryptography.exceptions
import io
import pytest
import requests_http_signature
from funkwhale_api.federation import signing
def test_can_sign_and_verify_request(factories):
private, public = factories['federation.KeyPair']()
auth = factories['federation.SignatureAuth'](key=private)
request = factories['federation.SignedRequest'](
auth=auth
)
prepared_request = request.prepare()
assert 'date' in prepared_request.headers
assert 'authorization' in prepared_request.headers
assert prepared_request.headers['authorization'].startswith('Signature')
assert requests_http_signature.HTTPSignatureAuth.verify(
prepared_request,
key_resolver=lambda **kwargs: public
) is None
def test_verify_fails_with_wrong_key(factories):
wrong_private, wrong_public = factories['federation.KeyPair']()
request = factories['federation.SignedRequest']()
prepared_request = request.prepare()
with pytest.raises(cryptography.exceptions.InvalidSignature):
requests_http_signature.HTTPSignatureAuth.verify(
prepared_request,
key_resolver=lambda **kwargs: wrong_public
)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment