Sirraya Labs UDNA SDK - W3C Universal DID-Native Addressing Implementation
Project description
Sirraya Labs UDNA SDK
W3C Universal DID-Native Addressing Implementation
Built by Sirraya Labs | Compliant with W3C DID Core
Table of Contents
- Overview
- Installation
- Quick Start
- Python API Reference
- Command Line Interface
- Advanced Features
- Examples
- Architecture
- Security
- Development
- License
Overview
The Sirraya Labs UDNA SDK provides a production-ready implementation of Universal DID-Native Addressing, enabling decentralized identity management and secure communication.
Key Capabilities
| Capability | Description | Status |
|---|---|---|
| DID Generation | Create W3C-compliant DIDs (did:key, did:web) | Complete |
| UDNA Addresses | Generate compact, verifiable network addresses | Complete |
| Cryptographic Verification | Ed25519 signature verification | Complete |
| Key Rotation | Secure key rotation with cryptographic proof | Complete |
| Identity Export/Import | Backup and restore identities | Complete |
| Pairwise DIDs | Relationship-specific privacy DIDs | Complete |
| Secure Messaging | Noise protocol encrypted communication | Complete |
| Storage Directory | Persistent identity storage | Complete |
| CLI Interface | Command-line tools for automation | Complete |
| JSON Output | Script-friendly JSON formatting | Complete |
Installation
pip install sirraya-udna-sdk
Requirements
- Python 3.7 or higher
- cryptography >= 41.0.0
- base58 >= 2.1.0
Quick Start
Python API
from udna_sdk import UdnaSDK
# Initialize SDK
sdk = UdnaSDK()
# Create a DID
did = sdk.create_did()
print(f"DID: {did.did}")
# Create a UDNA address
address = sdk.create_address(
did.did,
flags=["messaging", "routing"]
)
print(f"Address: {address.address}")
# Verify the address
result = sdk.verify_address(address.address)
print(f"Valid: {result.is_valid}")
Command Line Interface
# Create a new identity
udna create --flags messaging routing
# Verify an address
udna verify --address "7XFJXFpgRQ..."
# Get DID information
udna info --did "did:key:z6Mkk..."
Python API Reference
UdnaSDK Class
The main entry point for all UDNA operations.
Constructor
UdnaSDK(cache_enabled: bool = True, storage_dir: Optional[str] = None)
| Parameter | Type | Default | Description |
|---|---|---|---|
cache_enabled |
bool | True | Enable DID document caching |
storage_dir |
str | None | Directory for persistent identity storage |
Core Methods
| Method | Description | Returns |
|---|---|---|
create_did(method="key", domain=None) |
Creates a new DID | DidInfo |
resolve_did(did) |
Resolves a DID to its document | Dict |
create_address(did, facet_id=0x02, flags=None) |
Creates a UDNA address | UdnaAddressInfo |
verify_address(address) |
Cryptographically verifies an address | VerificationResult |
Key Management Methods
| Method | Description | Returns |
|---|---|---|
rotate_keys(did, reason="regular_rotation") |
Rotates keys with proof | KeyRotationResult |
export_identity(did, filepath, format="json") |
Exports identity to file | bool |
import_identity(filepath) |
Imports identity from file | Optional[DidInfo] |
load_identity(did, private_key_pem) |
Loads identity from PEM | bool |
list_identities() |
Lists all stored identities | List[str] |
get_did_info(did) |
Gets DID information | Optional[Dict] |
Privacy and Security Methods
| Method | Description | Returns |
|---|---|---|
create_pairwise_did(my_did, peer_did) |
Creates relationship-specific DID | DidInfo |
initiate_secure_session(my_did, remote_did) |
Starts Noise protocol session | SecureSession |
encrypt_message(session_id, plaintext) |
Encrypts message with session key | bytes |
decrypt_message(session_id, ciphertext) |
Decrypts message with session key | str |
Example with All Features
from udna_sdk import UdnaSDK
# Initialize with storage
sdk = UdnaSDK(storage_dir="./identities")
# Create identity
did = sdk.create_did()
print(f"DID: {did.did}")
# Export for backup
sdk.export_identity(did.did, "backup.json")
# Create address
address = sdk.create_address(did.did, flags=["messaging", "routing"])
# Rotate keys
result = sdk.rotate_keys(did.did, reason="regular_rotation")
print(f"Keys rotated: {result.success}")
# Create pairwise DID for privacy
peer_did = "did:key:z6MknVNjGKcWuUoxFXKmg29XV5RHkmx7gVvoYLGS8Qt4uACp"
pairwise = sdk.create_pairwise_did(did.did, peer_did)
print(f"Pairwise DID: {pairwise.did}")
# List all identities
identities = sdk.list_identities()
print(f"Stored identities: {identities}")
Data Models
DidInfo
| Attribute | Type | Description |
|---|---|---|
did |
str | Full DID string |
method |
str | DID method (e.g., "key") |
identifier |
str | Method-specific identifier |
created_at |
str | ISO timestamp of creation |
private_key_pem |
str | PEM-encoded private key (optional) |
UdnaAddressInfo
| Attribute | Type | Description |
|---|---|---|
address |
str | Base58-encoded UDNA address |
did |
str | Associated DID |
facet_id |
int | Service facet identifier |
flags |
List[str] | Enabled address flags |
nonce |
int | 64-bit random nonce |
created_at |
str | ISO timestamp of creation |
VerificationResult
| Attribute | Type | Description |
|---|---|---|
is_valid |
bool | True if signature verifies |
address |
str | The verified address |
did |
str | DID from the address |
verified_at |
str | ISO timestamp of verification |
error |
str or None | Error message if verification failed |
KeyRotationResult
| Attribute | Type | Description |
|---|---|---|
success |
bool | True if rotation succeeded |
did |
str | DID that was rotated |
old_key_fingerprint |
str | Fingerprint of old key |
new_key_fingerprint |
str | Fingerprint of new key |
rotated_at |
str | ISO timestamp of rotation |
error |
str or None | Error message if failed |
SecureSession
| Attribute | Type | Description |
|---|---|---|
session_id |
str | Unique session identifier |
local_did |
str | Local party DID |
remote_did |
str | Remote party DID |
established_at |
str | ISO timestamp of establishment |
session_key_hash |
str | Hash of session key |
AddressFlags Enum
Flags control address behavior and capabilities.
| Flag | Value | Description |
|---|---|---|
DEFAULT |
0 | No special flags |
MESSAGING_ENABLED |
1 | Enables messaging capabilities |
ROUTING_ENABLED |
2 | Enables routing hints |
EPHEMERAL |
4 | Address is temporary |
PRIORITY_HIGH |
8 | High priority handling |
ENCRYPTED |
16 | Encryption enabled |
Usage:
from udna_sdk import AddressFlags
address = sdk.create_address(
did.did,
flags=["messaging", "routing", "priority"]
)
Facet IDs
Facets represent different service types.
| Facet ID | Service Type | Description |
|---|---|---|
| 0x01 | Control | Management and configuration |
| 0x02 | Messaging | Communication services |
| 0x03 | Telemetry | Monitoring and analytics |
Command Line Interface
The SDK installs a global udna command.
Commands
Create Identity
udna create [options]
Options:
-m, --method {key,web} DID method (default: key)
-d, --domain DOMAIN Domain for did:web method
-f, --facet FACET Facet ID (default: 0x02)
--flags FLAGS... Address flags
-o, --output FILE Save address to file
-e, --export FILE Export identity to file
-s, --storage DIR Storage directory for identities
--format {text,json} Output format (default: text)
Examples:
udna create
udna create --method web --domain example.com
udna create --flags messaging routing priority
udna create --storage ./ids --export alice.json
udna create --format json
Rotate Keys
udna rotate DID [options]
Options:
-r, --reason {regular_rotation,compromised,expired}
Rotation reason (default: regular_rotation)
-i, --identity-file FILE
Identity JSON file to load
-s, --storage DIR Storage directory for identities
Examples:
udna rotate "did:key:z6Mkk..."
udna rotate "did:key:z6Mkk..." --reason compromised
udna rotate "did:key:z6Mkk..." --identity-file alice.json
Export Identity
udna export DID --output FILE [options]
Options:
-o, --output FILE Output file path (required)
--format {json,pem} Export format (default: json)
Examples:
udna export "did:key:z6Mkk..." --output backup.json
udna export "did:key:z6Mkk..." --output key.pem --format pem
List Identities
udna list [options]
Options:
-s, --storage DIR Storage directory
Examples:
udna list
udna list --storage ./identities
Verify Address
udna verify [options]
Options:
-a, --address ADDRESS UDNA address to verify
-f, --file FILE JSON file containing address
--format {text,json} Output format (default: text)
Examples:
udna verify --address "7XFJXFpgRQ..."
udna verify --file identity.json
udna verify --address "7XFJXFpgRQ..." --format json
Get Information
udna info [options]
Options:
-d, --did DID DID to inspect
-a, --address ADDRESS UDNA address to inspect
Examples:
udna info --did "did:key:z6Mkk..."
udna info --address "7XFJXFpgRQ..."
JSON Output
All commands support --format json for script integration:
$ udna create --format json
{
"did": {
"did": "did:key:z6Mkk...",
"method": "key",
"identifier": "z6Mkk...",
"created_at": "2026-04-04T16:42:17.782540"
},
"address": {
"address": "7XFJXFpgRQ...",
"did": "did:key:z6Mkk...",
"facet_id": 2,
"flags": ["messaging", "routing"],
"nonce": 252016976580823665,
"created_at": "2026-04-04T16:42:17.782540"
}
}
Advanced Features
Key Rotation
Rotate keys securely with cryptographic proof of ownership.
from udna_sdk import UdnaSDK
sdk = UdnaSDK()
did = sdk.create_did()
# Create address before rotation
addr1 = sdk.create_address(did.did, flags=["messaging"])
# Rotate keys
result = sdk.rotate_keys(did.did, reason="regular_rotation")
print(f"Rotation successful: {result.success}")
print(f"Old key: {result.old_key_fingerprint}")
print(f"New key: {result.new_key_fingerprint}")
# Create address after rotation (still valid)
addr2 = sdk.create_address(did.did, flags=["messaging"])
# Both addresses remain verifiable
assert sdk.verify_address(addr1.address).is_valid
assert sdk.verify_address(addr2.address).is_valid
Identity Export and Import
Export identities for backup, migration, or secure storage.
# Export to JSON
udna export "did:key:z6Mkk..." --output backup.json
# Export to PEM (raw private key)
udna export "did:key:z6Mkk..." --output key.pem --format pem
# Python API
sdk = UdnaSDK()
# Export
did = sdk.create_did()
sdk.export_identity(did.did, "backup.json")
# Import in new instance
sdk2 = UdnaSDK()
imported = sdk2.import_identity("backup.json")
print(f"Imported: {imported.did}")
Pairwise DIDs
Create relationship-specific DIDs for privacy.
sdk = UdnaSDK()
my_did = sdk.create_did()
peer_did = "did:key:z6MknVNjGKcWuUoxFXKmg29XV5RHkmx7gVvoYLGS8Qt4uACp"
# Create pairwise DID for this relationship only
pairwise = sdk.create_pairwise_did(my_did.did, peer_did)
print(f"Pairwise DID: {pairwise.did}")
# Use pairwise DID for all communications with this peer
address = sdk.create_address(pairwise.did, flags=["messaging"])
Secure Messaging with Noise Protocol
Establish encrypted communication channels using the Noise protocol.
# Alice and Bob create their identities
alice = UdnaSDK()
bob = UdnaSDK()
alice_did = alice.create_did()
bob_did = bob.create_did()
# Alice initiates secure session
session = alice.initiate_secure_session(alice_did.did, bob_did.did)
print(f"Session ID: {session.session_id}")
# Encrypt and send message
encrypted = alice.encrypt_message(session.session_id, "Hello Bob, this is secret!")
# Bob decrypts (session establishment would complete the handshake)
# decrypted = bob.decrypt_message(session.session_id, encrypted)
Persistent Storage Directory
Configure a storage directory for automatic identity persistence.
# CLI usage
udna create --storage ./identities
udna list --storage ./identities
# Python API
sdk = UdnaSDK(storage_dir="./identities")
# Identities are automatically saved
did = sdk.create_did()
# Later, list all stored identities
identities = sdk.list_identities()
print(f"Stored: {identities}")
Examples
Batch Identity Creation
from udna_sdk import UdnaSDK
import json
sdk = UdnaSDK(storage_dir="./identities")
identities = []
for i in range(10):
did = sdk.create_did()
address = sdk.create_address(did.did, flags=["messaging"])
identities.append({
"index": i,
"did": did.did,
"address": address.address
})
with open("batch_identities.json", "w") as f:
json.dump(identities, f, indent=2)
Verification with Error Handling
from udna_sdk import UdnaSDK
sdk = UdnaSDK()
result = sdk.verify_address(address_string)
if result.is_valid:
print(f"Address belongs to DID: {result.did}")
print(f"Verified at: {result.verified_at}")
else:
print(f"Verification failed: {result.error}")
Custom Facet Configuration
from udna_sdk import UdnaSDK
sdk = UdnaSDK()
did = sdk.create_did()
# Control facet (0x01) - Management
control = sdk.create_address(did.did, facet_id=0x01)
print(f"Control: {control.address[:30]}...")
# Messaging facet (0x02) - Communication
messaging = sdk.create_address(
did.did,
facet_id=0x02,
flags=["messaging", "routing"]
)
print(f"Messaging: {messaging.address[:30]}...")
# Telemetry facet (0x03) - Analytics
telemetry = sdk.create_address(did.did, facet_id=0x03)
print(f"Telemetry: {telemetry.address[:30]}...")
Complete Identity Lifecycle
from udna_sdk import UdnaSDK
# 1. Initialize with storage
sdk = UdnaSDK(storage_dir="./identities")
# 2. Create identity
did = sdk.create_did()
print(f"Created: {did.did}")
# 3. Export backup
sdk.export_identity(did.did, "backup.json")
# 4. Create addresses
address1 = sdk.create_address(did.did, flags=["messaging"])
address2 = sdk.create_address(did.did, facet_id=0x03)
# 5. Rotate keys periodically
result = sdk.rotate_keys(did.did, reason="regular_rotation")
print(f"Keys rotated: {result.success}")
# 6. Verify all addresses remain valid
assert sdk.verify_address(address1.address).is_valid
assert sdk.verify_address(address2.address).is_valid
# 7. List stored identities
print(f"Stored: {sdk.list_identities()}")
Architecture
The SDK implements the following specifications:
- W3C DID Core 1.0 - Decentralized Identifier specification
- did:key Method - Cryptographic key-based DIDs
- did:web Method - Web-based DIDs
- Ed25519 - Digital signatures for authentication
- Base58 - Encoding for addresses and keys
- Noise Protocol - Secure channel establishment
Address Structure
A UDNA address is a binary structure containing:
| Field | Size | Description |
|---|---|---|
| Version | 1 byte | Protocol version (1) |
| DID Type | 1 byte | Method identifier (0x01 for did:key) |
| DID Length | 2 bytes | Length of DID string |
| DID | variable | Full DID string |
| Key Hint | 1 byte + variable | Truncated key fingerprint |
| Route Hint | 1 byte + variable | Routing information |
| Flags | 2 bytes | Behavioral flags bitmask |
| Nonce | 8 bytes | 64-bit random value |
| Signature | 2 bytes + variable | Ed25519 signature |
DID Resolution Flow
- Check local cache for DID document
- If not cached, resolve using method-specific resolver
- Cache document with TTL (default 3600 seconds)
- Return DID document for verification
Cryptographic Verification
- Decode base58 address to bytes
- Parse binary structure
- Extract DID and signature
- Resolve DID document to get public key
- Recreate message without signature
- Verify Ed25519 signature
- Return verification result
Key Rotation Flow
- Generate new key pair
- Create rotation proof signed by old key
- Update DID document with new key
- Store rotation proof for audit
- Return new key fingerprint
Security
Key Management
Private keys are stored in memory only during SDK instance lifetime.
# Keys are automatically managed
sdk = UdnaSDK()
did = sdk.create_did() # Key stored internally
address = sdk.create_address(did.did) # Key used for signing
# Key is lost when SDK instance is destroyed
del sdk
For persistent storage, use export functionality:
# Export for secure storage
sdk.export_identity(did.did, "secure_backup.json", format="json")
# Store the file in a secure location, not in code
Signature Verification
All UDNA addresses are cryptographically signed. The SDK automatically:
- Extracts public key from DID document
- Recreates the signed message
- Verifies the Ed25519 signature
- Returns verification result
Best Practices
- Always verify addresses before trusting them
- Store private keys securely, never in code
- Use different facets for different services
- Rotate keys periodically
- Enable logging in production for audit trails
- Use pairwise DIDs for relationship-specific privacy
- Export and backup identities regularly
Rotation Reasons
| Reason | Code | Use Case |
|---|---|---|
regular_rotation |
1 | Scheduled key rotation |
compromised |
2 | Key compromise suspected |
expired |
3 | Key lifetime exceeded |
Development
Local Development Setup
git clone https://github.com/sirrayalabs/udna-sdk
cd udna-sdk
pip install -e .
Running Tests
pip install pytest
pytest tests/
Building Documentation
pip install sphinx
cd docs
make html
Building Package
pip install build twine
python -m build
twine upload dist/*
Version History
| Version | Date | Changes |
|---|---|---|
| 1.0.0 | 2026-04-04 | Initial release |
| 1.0.1 | 2026-04-04 | Fix imports, add AddressFlags |
| 1.0.2 | 2026-04-04 | Production ready release |
| 1.1.0 | 2026-04-04 | Key rotation, export/import, pairwise DIDs, secure messaging |
License
MIT License - Copyright (c) 2026 Sirraya Labs
See LICENSE file for details.
Contributing
Contributions are welcome. Please follow these guidelines:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
Support
- Documentation: https://docs.sirraya.org/udna-sdk
- Issues: GitHub Issues
- Email: amir@sirraya.org
Acknowledgments
- W3C DID Working Group for the DID Core specification
- Decentralized Identity Foundation (DIF) for standards guidance
- Python cryptography team for Ed25519 implementation
- Noise Protocol Framework for secure channel specification
Citation
If you use this SDK in research or production, please cite:
@software{sirraya_udna_sdk_2026,
title = {Sirraya Labs UDNA SDK},
author = {Sirraya Labs},
year = {2026},
version = {1.1.0},
url = {https://github.com/sirraya-labs/udna-sdk},
note = {W3C Universal DID-Native Addressing Implementation}
}
Built by Sirraya Labs | W3C Compliant | MIT Licensed
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sirraya_udna_sdk-1.0.6.tar.gz.
File metadata
- Download URL: sirraya_udna_sdk-1.0.6.tar.gz
- Upload date:
- Size: 31.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
38bc603d97a0a9340bbeb9de3c64a6b14f4ad61a01cfa173ad0d4edc50378235
|
|
| MD5 |
418c21de0b4e5690a638bb40d1c34c8a
|
|
| BLAKE2b-256 |
09977196d2bc40dfa1ec60b1b9f36bbdc083b9876fea4e70a724c269823d392f
|
File details
Details for the file sirraya_udna_sdk-1.0.6-py3-none-any.whl.
File metadata
- Download URL: sirraya_udna_sdk-1.0.6-py3-none-any.whl
- Upload date:
- Size: 27.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f289ba566f2fe0553fa01dcf95d948fda388e73ea62c93c5ea291b75d8724394
|
|
| MD5 |
e67d6b4894159862cdb4b76038f81f97
|
|
| BLAKE2b-256 |
a3d8156404905163c928a5b5f198fef70c3b640c57999a0932f0ea2cfb4b0ff5
|