Comprehensive Python SDK for the AT Protocol, providing client interfaces, authentication, and real-time streaming for decentralized social networks.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Cryptographic key management, signature verification, multibase encoding/decoding, and DID key generation for secure AT Protocol communications. These operations ensure data integrity, authentication, and secure communication within the AT Protocol ecosystem.
Cryptographic key representation supporting multiple key types and algorithms for AT Protocol operations.
class Multikey:
"""
Cryptographic key representation with algorithm specification.
Attributes:
jwt_alg (str): JWT algorithm identifier (e.g., 'ES256K', 'Ed25519')
key_bytes (bytes): Raw key material
"""
jwt_alg: str
key_bytes: bytes
@classmethod
def from_str(cls, multikey: str) -> 'Multikey':
"""
Parse Multikey from string representation.
Args:
multikey (str): Multikey string (e.g., multibase encoded)
Returns:
Multikey: Parsed key object
Raises:
ValueError: If multikey format is invalid
"""
def to_str(self) -> str:
"""
Format Multikey as string.
Returns:
str: Multikey string representation
"""
@property
def algorithm(self) -> str:
"""Get the cryptographic algorithm."""
@property
def key_type(self) -> str:
"""Get the key type (e.g., 'secp256k1', 'ed25519')."""
def public_key_bytes(self) -> bytes:
"""
Extract public key bytes.
Returns:
bytes: Public key material
"""Usage example:
from atproto import Multikey
# Parse multikey from string
multikey_str = "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
multikey = Multikey.from_str(multikey_str)
print(f"Algorithm: {multikey.jwt_alg}")
print(f"Key type: {multikey.key_type}")
print(f"Key bytes length: {len(multikey.key_bytes)}")
# Convert back to string
key_str = multikey.to_str()
assert key_str == multikey_strGenerate DID keys from cryptographic key material for decentralized identity operations.
def get_did_key(key: Union[Multikey, bytes, str]) -> str:
"""
Generate DID key from cryptographic key material.
Args:
key (Union[Multikey, bytes, str]): Key material in various formats
Returns:
str: DID key string (e.g., "did:key:z6MkhaXgB...")
Raises:
ValueError: If key format is unsupported
"""Usage example:
from atproto import get_did_key, Multikey
# Generate DID key from Multikey
multikey = Multikey.from_str("z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK")
did_key = get_did_key(multikey)
print(f"DID key: {did_key}")
# Generate DID key from raw bytes
key_bytes = b'\x01\x02\x03...' # Your key bytes
did_key = get_did_key(key_bytes)
print(f"DID key from bytes: {did_key}")Multibase provides self-describing base encodings for binary data, enabling interoperability across different encoding schemes.
def bytes_to_multibase(encoding: str, data: bytes) -> str:
"""
Encode bytes to multibase format.
Args:
encoding (str): Multibase encoding character:
- 'z' for base58btc
- 'f' for base16 (hex)
- 'b' for base32
- 'u' for base64url
- 'm' for base64
data (bytes): Data to encode
Returns:
str: Multibase encoded string
Raises:
ValueError: If encoding is unsupported
"""def multibase_to_bytes(data: str) -> bytes:
"""
Decode multibase string to bytes.
Args:
data (str): Multibase encoded string (first character indicates encoding)
Returns:
bytes: Decoded data
Raises:
ValueError: If multibase format is invalid or encoding unsupported
"""Usage examples:
from atproto import bytes_to_multibase, multibase_to_bytes
# Original data
original_data = b"Hello, AT Protocol!"
# Encode to different multibase formats
base58_encoded = bytes_to_multibase('z', original_data)
print(f"Base58: {base58_encoded}")
base32_encoded = bytes_to_multibase('b', original_data)
print(f"Base32: {base32_encoded}")
base64_encoded = bytes_to_multibase('m', original_data)
print(f"Base64: {base64_encoded}")
# Decode back to bytes
decoded_from_base58 = multibase_to_bytes(base58_encoded)
decoded_from_base32 = multibase_to_bytes(base32_encoded)
decoded_from_base64 = multibase_to_bytes(base64_encoded)
# All should equal original data
assert decoded_from_base58 == original_data
assert decoded_from_base32 == original_data
assert decoded_from_base64 == original_data
# The encoding is self-describing
print(f"Base58 prefix: {base58_encoded[0]}") # 'z'
print(f"Base32 prefix: {base32_encoded[0]}") # 'b'
print(f"Base64 prefix: {base64_encoded[0]}") # 'm'Verify cryptographic signatures using DID keys to ensure message authenticity and integrity.
def verify_signature(did_key: str, signing_input: bytes, signature: bytes) -> bool:
"""
Verify cryptographic signature using DID key.
Args:
did_key (str): DID key for verification (e.g., "did:key:z6Mk...")
signing_input (bytes): Original data that was signed
signature (bytes): Signature to verify
Returns:
bool: True if signature is valid, False otherwise
Raises:
ValueError: If DID key format is invalid
UnsupportedAlgorithmError: If key algorithm is not supported
"""Usage example:
from atproto import verify_signature, get_did_key
# Example verification scenario
did_key = "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
message = b"This message was signed"
signature = b"\x01\x02\x03..." # Actual signature bytes
# Verify the signature
is_valid = verify_signature(did_key, message, signature)
if is_valid:
print("✓ Signature is valid - message is authentic")
else:
print("✗ Signature is invalid - message may be tampered")
# Common use case: JWT signature verification
jwt_header = b'{"alg":"ES256K","typ":"JWT"}'
jwt_payload = b'{"iss":"did:plc:alice","sub":"did:plc:alice"}'
jwt_signing_input = base64_encode(jwt_header) + b'.' + base64_encode(jwt_payload)
jwt_signature = b"\x30\x45..." # JWT signature bytes
is_jwt_valid = verify_signature(did_key, jwt_signing_input, jwt_signature)Utilities for converting between different key formats used in AT Protocol.
def multikey_to_did_key(multikey: Union[str, Multikey]) -> str:
"""
Convert Multikey to DID key format.
Args:
multikey (Union[str, Multikey]): Multikey to convert
Returns:
str: DID key string
"""
def did_key_to_multikey(did_key: str) -> Multikey:
"""
Extract Multikey from DID key.
Args:
did_key (str): DID key string
Returns:
Multikey: Extracted multikey
Raises:
ValueError: If DID key format is invalid
"""
def public_key_to_multikey(public_key: bytes, algorithm: str) -> Multikey:
"""
Create Multikey from raw public key bytes.
Args:
public_key (bytes): Raw public key bytes
algorithm (str): Key algorithm ('secp256k1', 'ed25519', etc.)
Returns:
Multikey: Constructed multikey
Raises:
ValueError: If algorithm is unsupported
"""Usage examples:
from atproto import (
Multikey, multikey_to_did_key, did_key_to_multikey,
public_key_to_multikey
)
# Convert between formats
multikey_str = "z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
multikey = Multikey.from_str(multikey_str)
# Multikey to DID key
did_key = multikey_to_did_key(multikey)
print(f"DID key: {did_key}")
# DID key back to Multikey
recovered_multikey = did_key_to_multikey(did_key)
assert recovered_multikey.to_str() == multikey_str
# Create Multikey from raw key bytes
raw_public_key = b'\x04\x01\x02\x03...' # secp256k1 public key
multikey_from_raw = public_key_to_multikey(raw_public_key, 'secp256k1')
print(f"Multikey from raw: {multikey_from_raw.to_str()}")The SDK supports multiple cryptographic algorithms for different use cases:
class SupportedAlgorithms:
"""Supported cryptographic algorithms."""
SECP256K1 = 'secp256k1' # Bitcoin/Ethereum style keys
ED25519 = 'ed25519' # High-performance EdDSA
P256 = 'p256' # NIST P-256 curve
class JWTAlgorithms:
"""JWT algorithm identifiers."""
ES256K = 'ES256K' # ECDSA using secp256k1
EDDSA = 'EdDSA' # EdDSA using Ed25519
ES256 = 'ES256' # ECDSA using P-256Algorithm selection example:
from atproto import Multikey, SupportedAlgorithms, JWTAlgorithms
# Create keys for different algorithms
algorithms = [
(SupportedAlgorithms.SECP256K1, JWTAlgorithms.ES256K),
(SupportedAlgorithms.ED25519, JWTAlgorithms.EDDSA),
(SupportedAlgorithms.P256, JWTAlgorithms.ES256)
]
for key_type, jwt_alg in algorithms:
# In practice, you would generate actual key material
mock_key_bytes = b'\x01' * 32 # Placeholder
multikey = Multikey(jwt_alg=jwt_alg, key_bytes=mock_key_bytes)
did_key = get_did_key(multikey)
print(f"Algorithm: {key_type}")
print(f"JWT Algorithm: {jwt_alg}")
print(f"DID Key: {did_key[:50]}...")
print()class CryptographicError(Exception):
"""Base exception for cryptographic operations."""
class InvalidKeyError(CryptographicError):
"""Raised when key format or content is invalid."""
class UnsupportedAlgorithmError(CryptographicError):
"""Raised when algorithm is not supported."""
class SignatureVerificationError(CryptographicError):
"""Raised when signature verification fails."""
class MultibaseError(CryptographicError):
"""Raised for multibase encoding/decoding errors."""Error handling patterns:
from atproto import (
verify_signature, multibase_to_bytes,
InvalidKeyError, UnsupportedAlgorithmError, MultibaseError
)
# Handle key errors
try:
invalid_did_key = "did:key:invalid"
verify_signature(invalid_did_key, b"data", b"signature")
except InvalidKeyError as e:
print(f"Invalid key format: {e}")
# Handle algorithm errors
try:
unsupported_multikey = "unsupported_format_key"
multikey = Multikey.from_str(unsupported_multikey)
except UnsupportedAlgorithmError as e:
print(f"Unsupported algorithm: {e}")
# Handle multibase errors
try:
invalid_multibase = "invalid_multibase_string"
decoded = multibase_to_bytes(invalid_multibase)
except MultibaseError as e:
print(f"Multibase decoding failed: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-atproto