diff --git a/api/funkwhale_api/federation/exceptions.py b/api/funkwhale_api/federation/exceptions.py
new file mode 100644
index 0000000000000000000000000000000000000000..96fd24a7ed7eb2962b52aaccb578957911647249
--- /dev/null
+++ b/api/funkwhale_api/federation/exceptions.py
@@ -0,0 +1,4 @@
+
+
+class MalformedPayload(ValueError):
+    pass
diff --git a/api/funkwhale_api/federation/factories.py b/api/funkwhale_api/federation/factories.py
index 29aed4baf728a316cb0398537a7cbbed0bb961ab..f5d612b0dad5133197fb4385b583833539920126 100644
--- a/api/funkwhale_api/federation/factories.py
+++ b/api/funkwhale_api/federation/factories.py
@@ -4,16 +4,16 @@ import requests_http_signature
 
 from funkwhale_api.factories import registry
 
-from . import signing
+from . import keys
 
 
-registry.register(signing.get_key_pair, name='federation.KeyPair')
+registry.register(keys.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 = factory.LazyFunction(lambda: keys.get_key_pair()[0])
     key_id = factory.Faker('url')
 
     class Meta:
diff --git a/api/funkwhale_api/federation/keys.py b/api/funkwhale_api/federation/keys.py
new file mode 100644
index 0000000000000000000000000000000000000000..432560ef7446d5973d23850cff7a2cb253c9fba7
--- /dev/null
+++ b/api/funkwhale_api/federation/keys.py
@@ -0,0 +1,43 @@
+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
+
+import requests
+
+from . import exceptions
+
+
+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
+
+
+def get_public_key(actor_url):
+    """
+    Given an actor_url, request it and extract publicKey data from
+    the response payload.
+    """
+    response = requests.get(actor_url)
+    response.raise_for_status()
+    payload = response.json()
+    try:
+        return {
+            'public_key_pem': payload['publicKey']['publicKeyPem'],
+            'id': payload['publicKey']['id'],
+            'owner': payload['publicKey']['owner'],
+        }
+    except KeyError:
+        raise exceptions.MalformedPayload(str(payload))
diff --git a/api/funkwhale_api/federation/signing.py b/api/funkwhale_api/federation/signing.py
index e8d79097c5bf154e7f6edd4661b0f74d831241b8..87ac82bac0b9a5b599ce7d3721e8f4f876c02e8c 100644
--- a/api/funkwhale_api/federation/signing.py
+++ b/api/funkwhale_api/federation/signing.py
@@ -1,28 +1,6 @@
 import requests
 import requests_http_signature
 
-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
-
 
 def verify(request, public_key):
     return requests_http_signature.HTTPSignatureAuth.verify(
diff --git a/api/tests/federation/test_keys.py b/api/tests/federation/test_keys.py
new file mode 100644
index 0000000000000000000000000000000000000000..1c30c30b17ed6450e7ec133498f3788be16a9ee6
--- /dev/null
+++ b/api/tests/federation/test_keys.py
@@ -0,0 +1,16 @@
+from funkwhale_api.federation import keys
+
+
+def test_public_key_fetching(r_mock):
+    payload = {
+        'id': 'https://actor.mock/users/actor#main-key',
+        'owner': 'test',
+        'publicKeyPem': 'test_pem',
+    }
+    actor = 'https://actor.mock/'
+    r_mock.get(actor, json={'publicKey': payload})
+    r = keys.get_public_key(actor)
+
+    assert r['id'] == payload['id']
+    assert r['owner'] == payload['owner']
+    assert r['public_key_pem'] == payload['publicKeyPem']
diff --git a/api/tests/federation/test_signing.py b/api/tests/federation/test_signing.py
index 5187faa52d02ab4af621f98b3b49295a5b35cd9a..dc678f749bb0d7063ff58842c24de2391261b9ef 100644
--- a/api/tests/federation/test_signing.py
+++ b/api/tests/federation/test_signing.py
@@ -4,6 +4,7 @@ import pytest
 import requests_http_signature
 
 from funkwhale_api.federation import signing
+from funkwhale_api.federation import keys
 
 
 def test_can_sign_and_verify_request(factories):
@@ -45,7 +46,7 @@ def test_verify_fails_with_wrong_key(factories):
 
 
 def test_can_verify_django_request(factories, api_request):
-    private_key, public_key = signing.get_key_pair()
+    private_key, public_key = keys.get_key_pair()
     signed_request = factories['federation.SignedRequest'](
         auth__key=private_key
     )
@@ -61,7 +62,7 @@ def test_can_verify_django_request(factories, api_request):
 
 
 def test_can_verify_django_request_digest(factories, api_request):
-    private_key, public_key = signing.get_key_pair()
+    private_key, public_key = keys.get_key_pair()
     signed_request = factories['federation.SignedRequest'](
         auth__key=private_key,
         method='post',
@@ -81,7 +82,7 @@ def test_can_verify_django_request_digest(factories, api_request):
 
 
 def test_can_verify_django_request_digest_failure(factories, api_request):
-    private_key, public_key = signing.get_key_pair()
+    private_key, public_key = keys.get_key_pair()
     signed_request = factories['federation.SignedRequest'](
         auth__key=private_key,
         method='post',
@@ -102,7 +103,7 @@ def test_can_verify_django_request_digest_failure(factories, api_request):
 
 
 def test_can_verify_django_request_failure(factories, api_request):
-    private_key, public_key = signing.get_key_pair()
+    private_key, public_key = keys.get_key_pair()
     signed_request = factories['federation.SignedRequest'](
         auth__key=private_key
     )