noop identifier renames, key => domain or entity

pull/287/head
Ryan Barrett 2022-11-15 19:12:20 -08:00
rodzic 97088da382
commit e3f1431018
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
6 zmienionych plików z 31 dodań i 31 usunięć

Wyświetl plik

@ -58,8 +58,8 @@ def send(activity, inbox_url, user_domain):
# https://tools.ietf.org/html/draft-cavage-http-signatures-07
# https://github.com/tootsuite/mastodon/issues/4906#issuecomment-328844846
key_id = request.host_url + user_domain
key = Domain.get_or_create(user_domain)
auth = HTTPSignatureAuth(secret=key.private_pem(), key_id=key_id,
domain = Domain.get_or_create(user_domain)
auth = HTTPSignatureAuth(secret=domain.private_pem(), key_id=key_id,
algorithm='rsa-sha256', sign_header='signature',
headers=('Date', 'Digest', 'Host'))
@ -94,9 +94,9 @@ def actor(domain):
if not hcard:
error(f"Couldn't find a representative h-card (http://microformats.org/wiki/representative-hcard-parsing) on {mf2['url']}")
key = Domain.get_or_create(domain)
entity = Domain.get_or_create(domain)
obj = common.postprocess_as2(
as2.from_as1(microformats2.json_to_object(hcard)), key=key)
as2.from_as1(microformats2.json_to_object(hcard)), domain=entity)
obj.update({
'preferredUsername': domain,
'inbox': f'{request.host_url}{domain}/inbox',

Wyświetl plik

@ -242,14 +242,14 @@ def send_webmentions(activity_wrapped, proxy=None, **activity_props):
error(msg, status=int(errors[0][0] or 502))
def postprocess_as2(activity, target=None, key=None):
def postprocess_as2(activity, target=None, domain=None):
"""Prepare an AS2 object to be served or sent via ActivityPub.
Args:
activity: dict, AS2 object or activity
target: dict, AS2 object, optional. The target of activity's inReplyTo or
Like/Announce/etc object, if any.
key: :class:`models.Domain`, optional. populated into publicKey field
domain: :class:`models.Domain`, optional. populated into publicKey field
if provided.
"""
type = activity.get('type')
@ -257,7 +257,7 @@ def postprocess_as2(activity, target=None, key=None):
# actor objects
if type == 'Person':
postprocess_as2_actor(activity)
if not activity.get('publicKey'):
if not activity.get('publicKey') and domain:
# underspecified, inferred from this issue and Mastodon's implementation:
# https://github.com/w3c/activitypub/issues/203#issuecomment-297553229
# https://github.com/tootsuite/mastodon/blob/bc2c263504e584e154384ecc2d804aeb1afb1ba3/app/services/activitypub/process_account_service.rb#L77
@ -266,7 +266,7 @@ def postprocess_as2(activity, target=None, key=None):
'publicKey': {
'id': actor_url,
'owner': actor_url,
'publicKeyPem': key.public_pem().decode(),
'publicKeyPem': domain.public_pem().decode(),
},
'@context': (util.get_list(activity, '@context') +
['https://w3id.org/security/v1']),

Wyświetl plik

@ -36,17 +36,17 @@ class Domain(StringIdModel):
@ndb.transactional()
def get_or_create(domain):
"""Loads and returns a Domain. Creates it if necessary."""
key = Domain.get_by_id(domain)
entity = Domain.get_by_id(domain)
if not key:
if not entity:
# this uses urandom(), and does nontrivial math, so it can take a
# while depending on the amount of randomness available.
pubexp, mod, privexp = magicsigs.generate()
key = Domain(id=domain, mod=mod, public_exponent=pubexp,
entity = Domain(id=domain, mod=mod, public_exponent=pubexp,
private_exponent=privexp)
key.put()
entity.put()
return key
return entity
def href(self):
return 'data:application/magic-public-key,RSA.%s.%s' % (

Wyświetl plik

@ -9,29 +9,29 @@ class DomainTest(testutil.TestCase):
def setUp(self):
super(DomainTest, self).setUp()
self.key = Domain.get_or_create('y.z')
self.domain = Domain.get_or_create('y.z')
def test_magic_key_get_or_create(self):
assert self.key.mod
assert self.key.public_exponent
assert self.key.private_exponent
assert self.domain.mod
assert self.domain.public_exponent
assert self.domain.private_exponent
same = Domain.get_or_create('y.z')
self.assertEqual(same, self.key)
self.assertEqual(same, self.domain)
def test_href(self):
href = self.key.href()
href = self.domain.href()
self.assertTrue(href.startswith('data:application/magic-public-key,RSA.'), href)
self.assertIn(self.key.mod, href)
self.assertIn(self.key.public_exponent, href)
self.assertIn(self.domain.mod, href)
self.assertIn(self.domain.public_exponent, href)
def test_public_pem(self):
pem = self.key.public_pem()
pem = self.domain.public_pem()
self.assertTrue(pem.decode().startswith('-----BEGIN PUBLIC KEY-----\n'), pem)
self.assertTrue(pem.decode().endswith('-----END PUBLIC KEY-----'), pem)
def test_private_pem(self):
pem = self.key.private_pem()
pem = self.domain.private_pem()
self.assertTrue(pem.decode().startswith('-----BEGIN RSA PRIVATE KEY-----\n'), pem)
self.assertTrue(pem.decode().endswith('-----END RSA PRIVATE KEY-----'), pem)

Wyświetl plik

@ -59,7 +59,7 @@ class User(flask_util.XrdOrJrd):
error(f"didn't find a representative h-card (http://microformats.org/wiki/representative-hcard-parsing) on {resp.url}")
logger.info(f'Generating WebFinger data for {domain}')
key = models.Domain.get_or_create(domain)
entity = models.Domain.get_or_create(domain)
props = hcard.get('properties', {})
urls = util.dedupe_urls(props.get('url', []) + [resp.url])
canonical_url = urls[0]
@ -97,7 +97,7 @@ class User(flask_util.XrdOrJrd):
data = util.trim_nulls({
'subject': 'acct:' + acct,
'aliases': urls,
'magic_keys': [{'value': key.href()}],
'magic_keys': [{'value': entity.href()}],
'links': sum(([{
'rel': 'http://webfinger.net/rel/profile-page',
'type': 'text/html',
@ -135,7 +135,7 @@ class User(flask_util.XrdOrJrd):
'href': hub,
}, {
'rel': 'magic-public-key',
'href': key.href(),
'href': entity.href(),
}, {
'rel': 'salmon',
'href': f'{request.host_url}{domain}/salmon',

Wyświetl plik

@ -91,7 +91,7 @@ class Webmention(View):
if not targets:
return None
key = Domain.get_or_create(self.source_domain)
domain = Domain.get_or_create(self.source_domain)
error = None
last_success = None
@ -106,7 +106,7 @@ class Webmention(View):
for resp, inbox in targets:
target_obj = json_loads(resp.target_as2) if resp.target_as2 else None
source_activity = common.postprocess_as2(
as2.from_as1(self.source_obj), target=target_obj, key=key)
as2.from_as1(self.source_obj), target=target_obj, domain=domain)
if resp.status == 'complete':
if resp.source_mf2:
@ -361,10 +361,10 @@ class Webmention(View):
# sign reply and wrap in magic envelope
domain = urllib.parse.urlparse(self.source_url).netloc
key = Domain.get_or_create(domain)
logger.info(f'Using key for {domain}: {key}')
entity = Domain.get_or_create(domain)
logger.info(f'Using key for {domain}: {entity}')
magic_envelope = magicsigs.magic_envelope(
entry, common.CONTENT_TYPE_ATOM, key).decode()
entry, common.CONTENT_TYPE_ATOM, entity).decode()
logger.info(f'Sending Salmon slap to {endpoint}')
common.requests_post(