Skip to main content

apsig is collection of signature implemention used in ActivityPub.

Project description

apsig

PyPI CodeQL

apsig is collection of signature implemention used in ActivityPub.

This library implements the creation/verification of signatures for HTTP Signatures (draft-cavage-http-signatures-12), Linked Data Signatures 1.0, and Object Integrity Proofs (FEP-8b32).

RFC9421 implementation is progress.

Installation

# pip
pip install apsig

# uv
uv add apsig

# pdm
pdm add apsig

Example

First, prepare the keys for signing and verification. apsig uses the cryptography library.

from cryptography.hazmat.primitives.asymmetric import rsa, ed25519
from cryptography.hazmat.primitives import serialization

# For HTTP Signatures (RSA)
private_key_rsa = rsa.generate_private_key(public_exponent=65537, key_size=3092)
public_key_rsa_pem = private_key_rsa.public_key().public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo,
)

# For Object Integrity Proofs (Ed25519)
private_key_ed = ed25519.Ed25519PrivateKey.generate()
public_key_ed = private_key_ed.public_key()

HTTP Signature (draft)

This is used for signing HTTP requests.

import email.utils
from apsig.draft import Signer, Verifier

# === Signing ===
method = "POST"
url = "https://example.com/api/resource"
headers = {
    "Content-Type": "application/json",
    "Date": email.utils.formatdate(usegmt=True),
}
body = '{"key": "value"}'
key_id = "https://example.com/users/johndoe#main-key"

signer = Signer(
    headers=headers,
    private_key=private_key_rsa,
    method=method,
    url=url,
    key_id=key_id,
    body=body.encode("utf-8"),
)
signed_headers = signer.sign()

print(signed_headers)

# === Verifying ===
verifier = Verifier(
    public_pem=public_key_rsa_pem.decode("utf-8"),
    method=method,
    url=url,
    headers=signed_headers,
    body=body.encode("utf-8"),
)
verified_key_id = verifier.verify(raise_on_fail=True)

print(f"Verified with key: {verified_key_id}")

Object Integrity Proofs (proof)

This is used for signing JSON objects (like ActivityStreams objects).

from apsig import ProofSigner, ProofVerifier

# === Signing ===
json_object = {
    "@context": [
        "https://www.w3.org/ns/activitystreams",
        "https://w3id.org/security/data-integrity/v1",
    ],
    "id": "https://server.example/objects/1",
    "type": "Note",
    "content": "Hello world",
}
proof_options = {
    "type": "DataIntegrityProof",
    "cryptosuite": "eddsa-jcs-2022",
    "verificationMethod": "https://example.com/keys/1",
    "created": "2024-01-01T09:00:00Z",
}

signer = ProofSigner(private_key_ed)
signed_object = signer.sign(json_object, proof_options)

print(signed_object)

# === Verifying ===
verifier = ProofVerifier(public_key_ed)
verified_key_id = verifier.verify(signed_object, raise_on_fail=True)

print(f"Verified with key: {verified_key_id}")

Linked Data Signature (LD-Signature)

This is another method for signing JSON-LD objects, often used in older ActivityPub implementations.

from apsig import LDSignature

# === Signing ===
ld_signer = LDSignature()
json_ld_object = {
    "@context": [
        "https://www.w3.org/ns/activitystreams",
        "https://w3id.org/security/v1",
    ],
    "type": "Note",
    "content": "Hello, Linked Data!",
}
creator = "https://example.com/users/johndoe#main-key"

signed_ld_object = ld_signer.sign(
    doc=json_ld_object,
    creator=creator,
    private_key=private_key_rsa
)

print(signed_ld_object)

# === Verifying ===
# The public key can be passed directly.
public_key_rsa = private_key_rsa.public_key()
verified_creator = ld_signer.verify(
    doc=signed_ld_object,
    public_key=public_key_rsa,
    raise_on_fail=True
)

print(f"Verified with creator: {verified_creator}")

Documents

The document can be viewed here.

Thanks

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

apsig-0.6.0.tar.gz (151.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

apsig-0.6.0-py3-none-any.whl (20.2 kB view details)

Uploaded Python 3

File details

Details for the file apsig-0.6.0.tar.gz.

File metadata

  • Download URL: apsig-0.6.0.tar.gz
  • Upload date:
  • Size: 151.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for apsig-0.6.0.tar.gz
Algorithm Hash digest
SHA256 9bf17c7978ff45f21313a40f0255dd1fae35cca61ef7e613fb70274ca64ec823
MD5 2a30c2dfa00ecef2c0ee1d6ce8691874
BLAKE2b-256 9f9968ed305078b58b2f79539f9e4fce210b2b63318cf6ea56821490a259a7c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for apsig-0.6.0.tar.gz:

Publisher: publish.yml on fedi-libs/apsig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file apsig-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: apsig-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 20.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for apsig-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1a4d742f13deb0b3a344ee69e3edbdc3c091a03d0b47a40ce70966b2e637ceb5
MD5 6556e8e9c3fe00a92f2cca1a34a288ef
BLAKE2b-256 bf6f7f4293cdfc39a2869bd95402ae4d680ea42e3578c6064e32700c918e7647

See more details on using hashes here.

Provenance

The following attestation bundles were made for apsig-0.6.0-py3-none-any.whl:

Publisher: publish.yml on fedi-libs/apsig

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page