feat: RSA key management for ActivityPub signing
- keys.py: Generate/load RSA-2048 keypairs, sign activities - setup_keys.py: CLI to generate keys - Real RsaSignature2017 signing (falls back to placeholder if no keys) - Public key included in actor profile - Private keys gitignored 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
42
server.py
42
server.py
@@ -117,13 +117,8 @@ def save_activities(activities: list):
|
||||
|
||||
|
||||
def load_actor() -> dict:
|
||||
"""Load actor data."""
|
||||
path = DATA_DIR / "actor.json"
|
||||
if path.exists():
|
||||
with open(path) as f:
|
||||
return json.load(f)
|
||||
# Return default actor
|
||||
return {
|
||||
"""Load actor data with public key if available."""
|
||||
actor = {
|
||||
"id": f"https://{DOMAIN}/users/{USERNAME}",
|
||||
"type": "Person",
|
||||
"preferredUsername": USERNAME,
|
||||
@@ -134,6 +129,17 @@ def load_actor() -> dict:
|
||||
"following": f"https://{DOMAIN}/users/{USERNAME}/following",
|
||||
}
|
||||
|
||||
# Add public key if available
|
||||
from keys import has_keys, load_public_key_pem
|
||||
if has_keys(DATA_DIR, USERNAME):
|
||||
actor["publicKey"] = {
|
||||
"id": f"https://{DOMAIN}/users/{USERNAME}#main-key",
|
||||
"owner": f"https://{DOMAIN}/users/{USERNAME}",
|
||||
"publicKeyPem": load_public_key_pem(DATA_DIR, USERNAME)
|
||||
}
|
||||
|
||||
return actor
|
||||
|
||||
|
||||
def load_followers() -> list:
|
||||
"""Load followers list."""
|
||||
@@ -153,15 +159,21 @@ def save_followers(followers: list):
|
||||
|
||||
# ============ Signing ============
|
||||
|
||||
from keys import has_keys, load_public_key_pem, create_signature
|
||||
|
||||
|
||||
def sign_activity(activity: dict) -> dict:
|
||||
"""Sign an activity (placeholder - real impl uses RSA)."""
|
||||
# In production, use artdag.activitypub.signatures
|
||||
activity["signature"] = {
|
||||
"type": "RsaSignature2017",
|
||||
"creator": f"https://{DOMAIN}/users/{USERNAME}#main-key",
|
||||
"created": datetime.now(timezone.utc).isoformat(),
|
||||
"signatureValue": "placeholder-implement-real-signing"
|
||||
}
|
||||
"""Sign an activity with RSA private key."""
|
||||
if not has_keys(DATA_DIR, USERNAME):
|
||||
# No keys - use placeholder (for testing)
|
||||
activity["signature"] = {
|
||||
"type": "RsaSignature2017",
|
||||
"creator": f"https://{DOMAIN}/users/{USERNAME}#main-key",
|
||||
"created": datetime.now(timezone.utc).isoformat(),
|
||||
"signatureValue": "NO_KEYS_CONFIGURED"
|
||||
}
|
||||
else:
|
||||
activity["signature"] = create_signature(DATA_DIR, USERNAME, DOMAIN, activity)
|
||||
return activity
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user