Skip to main content

dstack SDK for Python

Project description

dstack SDK for Python

Access TEE features from your Python application running inside dstack. Derive deterministic keys, generate attestation quotes, create TLS certificates, and sign data—all backed by hardware security.

Installation

pip install dstack-sdk

Blockchain helpers are optional extras:

Extra Pulls in Use when
dstack-sdk[ethereum] eth-account You want to_account / to_account_secure for Ethereum signing
dstack-sdk[solana] solders You want to_keypair / to_keypair_secure for Solana signing
dstack-sdk[all] both You need both

Aliases [eth] and [sol] are accepted for convenience.

Quick Start

from dstack_sdk import DstackClient

client = DstackClient()

# Derive a deterministic key for your wallet
key = client.get_key('wallet/eth')
print(key.key)  # Same path always returns the same key

# Generate an attestation quote
quote = client.get_quote(b'my-app-state')
print(quote.quote)

The client automatically connects to /var/run/dstack.sock. For local development with the simulator:

client = DstackClient('http://localhost:8090')
# or export DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090

Core API

Derive Keys

get_key() derives deterministic keys bound to your application's identity (app_id). The same path always produces the same key for your app, but different apps get different keys even with the same path.

# Derive keys by path
eth_key = client.get_key('wallet/ethereum')
btc_key = client.get_key('wallet/bitcoin')

# Use path to separate keys
mainnet_key = client.get_key('wallet/eth/mainnet')
testnet_key = client.get_key('wallet/eth/testnet')

# Use a different signature algorithm (requires dstack OS >= 0.5.7)
ed_key = client.get_key('signing/key', algorithm='ed25519')

Parameters:

  • path (optional): Key derivation path. Defaults to "" (root).
  • purpose (optional): Included in the signature chain message; does not affect the derived key.
  • algorithm (optional): 'secp256k1' (default) or 'ed25519'.

Returns: GetKeyResponse

  • key: Hex-encoded private key
  • signature_chain: Signatures proving the key was derived in a genuine TEE
  • decode_key() / decode_signature_chain(): Helpers that return bytes

Generate Attestation Quotes

get_quote() creates a TDX quote proving your code runs in a genuine TEE.

quote = client.get_quote(b'user:alice:nonce123')

# Replay RTMRs from the event log
rtmrs = quote.replay_rtmrs()
print(rtmrs)

Parameters:

  • report_data: Up to 64 bytes (bytes or str). Shorter inputs are padded with zeros; longer inputs should be hashed first (e.g., SHA-256).

Returns: GetQuoteResponse

  • quote: Hex-encoded TDX quote
  • event_log: JSON string of measured events
  • replay_rtmrs(): Method to compute RTMR values from the event log
  • decode_quote() / decode_event_log(): Helpers

Versioned Attestation

attest() returns a versioned attestation payload that newer verifier APIs can dispatch on without sniffing the quote format.

result = client.attest(b'user:alice:nonce123')
print(result.attestation)        # hex string
print(result.decode_attestation())  # bytes

Get Instance Info

info = client.info()
print(info.app_id)
print(info.instance_id)
print(info.tcb_info)
print(info.cloud_vendor, info.cloud_product)  # 0.5.7+

Returns: InfoResponse

  • app_id, instance_id, app_name, device_id
  • tcb_info: TCB measurements (MRTD, RTMRs, event log, compose hash, ...)
  • compose_hash: Hash of the app configuration
  • app_cert: Application certificate (PEM)
  • key_provider_info: Key management configuration
  • cloud_vendor / cloud_product: Cloud provider strings (empty on older OS)

Generate TLS Certificates

get_tls_key() creates fresh TLS certificates. Unlike get_key(), each call generates a new random key.

tls = client.get_tls_key(
    subject='api.example.com',
    alt_names=['localhost'],
    usage_ra_tls=True,    # Embed attestation in certificate
    # 0.5.7+ options below:
    not_before=1700000000,   # seconds since UNIX epoch
    not_after=1800000000,
    with_app_info=True,
)
print(tls.key)                  # PEM private key
print(tls.certificate_chain)    # Certificate chain

Parameters:

  • subject (optional): Certificate Common Name (e.g., domain name)
  • alt_names (optional): Subject Alternative Names
  • usage_ra_tls (optional): Embed TDX quote in a certificate extension (default False)
  • usage_server_auth (optional): Enable for server authentication (default True)
  • usage_client_auth (optional): Enable for client authentication (default False)
  • not_before / not_after (optional, kw-only): Validity window in seconds since UNIX epoch. Requires dstack OS >= 0.5.7.
  • with_app_info (optional, kw-only): Embed app identity into the certificate. Requires dstack OS >= 0.5.7.

When any of the 0.5.7-only options is set, the SDK probes Version first and raises RuntimeError on older guest agents that lack it.

Returns: GetTlsKeyResponse

  • key: PEM-encoded private key
  • certificate_chain: List of PEM certificates
  • as_uint8array(max_length=None): Returns the DER-encoded private key bytes (handy when feeding key material into low-level crypto libraries)

Sign and Verify

Sign data using TEE-derived keys:

result = client.sign('ed25519', b'message to sign')
print(result.signature)
print(result.public_key)

# Verify the signature
valid = client.verify('ed25519', b'message to sign', result.signature, result.public_key)
print(valid.valid)  # True

sign() Parameters:

  • algorithm: 'ed25519', 'secp256k1', or 'secp256k1_prehashed'
  • data: Data to sign (bytes or str). For secp256k1_prehashed, must be a 32-byte digest.

sign() Returns: SignResponse

  • signature: Hex-encoded signature
  • public_key: Hex-encoded public key
  • signature_chain: Signatures proving TEE origin

verify() Returns: VerifyResponse

  • valid: Boolean indicating if the signature is valid

Emit Events

Extend RTMR3 with custom measurements for your application's boot sequence (requires dstack OS 0.5.0+). These measurements are append-only and become part of the attestation record.

client.emit_event('config_loaded', 'production')
client.emit_event('plugin_initialized', 'auth-v2')

Diagnostics

client.version()        # VersionResponse(version, rev) — raises on OS < 0.5.7
client.is_reachable()   # Quick connectivity probe; never raises

Async Client

For async applications, use AsyncDstackClient. The API surface is identical, but every method is a coroutine:

import asyncio
from dstack_sdk import AsyncDstackClient

async def main():
    client = AsyncDstackClient()

    info = await client.info()
    key = await client.get_key('wallet/eth')

    # Run requests concurrently
    keys = await asyncio.gather(
        client.get_key('user/alice'),
        client.get_key('user/bob'),
    )

asyncio.run(main())

AsyncDstackClient accepts the same constructor as DstackClient plus use_sync_http: bool = False for callers that need to issue sync HTTP from within an async context.

Blockchain Integration

Ethereum

from dstack_sdk.ethereum import to_account_secure

key = client.get_key('wallet/ethereum')
account = to_account_secure(key)
print(account.address)

to_account_secure(key) hashes the full key material with SHA-256 before deriving the Ethereum private key. The legacy to_account() is kept for backward compatibility but uses raw key bytes—prefer the secure variant for new code.

Solana

from dstack_sdk.solana import to_keypair_secure

key = client.get_key('wallet/solana')
keypair = to_keypair_secure(key)
print(keypair.pubkey())

Same pattern: to_keypair_secure(key) SHA-256-hashes the key material; to_keypair() is the legacy raw-bytes variant.


Deployment Utilities

These utilities are for deployment scripts, not runtime SDK operations.

Encrypted Environment Variables

The KMS returns a fresh X25519 public key (with a secp256k1 signature) that you encrypt secrets against before submitting them with your deployment. Always verify the signer before trusting the key:

from dstack_sdk import (
    encrypt_env_vars,
    verify_env_encrypt_public_key,
    verify_env_encrypt_public_key_legacy,
    EnvVar,
)

# `public_key`, `signature_v1`, `timestamp` come from KMS /GetAppEnvEncryptPubKey.
signer = verify_env_encrypt_public_key(
    public_key=public_key_bytes,
    signature=signature_v1_bytes,
    app_id=app_id_hex,
    timestamp=timestamp,
)
if signer is None:
    # Fallback for older KMS builds that only emit the unprotected legacy
    # signature. Vulnerable to replay; warn loudly if you must use it.
    signer = verify_env_encrypt_public_key_legacy(
        public_key=public_key_bytes,
        signature=legacy_signature_bytes,
        app_id=app_id_hex,
    )
    if signer is None:
        raise RuntimeError('invalid KMS env-encrypt public key')

env_vars = [
    EnvVar(key='DATABASE_URL', value='postgresql://...'),
    EnvVar(key='API_KEY', value='secret'),
]
encrypted = await encrypt_env_vars(env_vars, public_key_hex)
# encrypt_env_vars_sync(...) is also available for non-async callers.

verify_env_encrypt_public_key returns the recovered compressed secp256k1 signer (0x-prefixed hex) on success, or None for any failure (bad length, expired/future timestamp, malformed app_id, invalid signature). The default max_age_seconds is 300; pass a larger value if your deployment workflow legitimately holds the response longer.

Calculate Compose Hash

from dstack_sdk import get_compose_hash

hash_value = get_compose_hash(app_compose_dict)

Compatibility

Feature Required dstack OS
get_key, get_quote, get_tls_key (legacy fields), info (legacy fields) 0.3+
emit_event 0.5.0+
attest, sign / verify, version, is_reachable 0.5.0+ (sign/verify require server build with the feature)
algorithm='ed25519' on get_key, info.cloud_vendor / cloud_product, not_before / not_after / with_app_info on get_tls_key 0.5.7+
verify_env_encrypt_public_key (signature_v1 with timestamp) Requires KMS build that emits signature_v1; legacy variant remains available

Calls that require 0.5.7-only fields probe the Version RPC first and raise a clear RuntimeError on older guest agents.

Development

For local development without TDX hardware, use the simulator:

git clone https://github.com/Dstack-TEE/dstack.git
cd dstack/sdk/simulator
./build.sh
./dstack-simulator

Then set the endpoint:

export DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090

Install dev dependencies and run tests with PDM:

cd sdk/python
make install
make test

Migration from TappdClient

Replace TappdClient with DstackClient:

# Before
from dstack_sdk import TappdClient
client = TappdClient()

# After
from dstack_sdk import DstackClient
client = DstackClient()

Method changes:

  • derive_key()get_tls_key() for TLS certificates
  • tdx_quote()get_quote() (raw data only, no hash algorithms)
  • Socket path: /var/run/tappd.sock/var/run/dstack.sock

License

Apache License 2.0

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

dstack_sdk-0.5.4b1.tar.gz (32.9 kB view details)

Uploaded Source

Built Distribution

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

dstack_sdk-0.5.4b1-py3-none-any.whl (19.8 kB view details)

Uploaded Python 3

File details

Details for the file dstack_sdk-0.5.4b1.tar.gz.

File metadata

  • Download URL: dstack_sdk-0.5.4b1.tar.gz
  • Upload date:
  • Size: 32.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dstack_sdk-0.5.4b1.tar.gz
Algorithm Hash digest
SHA256 06826e2759315352cb5b912b297a9138cf430c2987a561e5b19d17ee5a15ea0b
MD5 713f31b69854b18c10aaf58f06f56e0e
BLAKE2b-256 ac11849994fd7206110126f2941ec602f4f4b1cd15fd7aa8a44a83019c75d8c2

See more details on using hashes here.

Provenance

The following attestation bundles were made for dstack_sdk-0.5.4b1.tar.gz:

Publisher: python-sdk-release.yml on Dstack-TEE/dstack

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

File details

Details for the file dstack_sdk-0.5.4b1-py3-none-any.whl.

File metadata

  • Download URL: dstack_sdk-0.5.4b1-py3-none-any.whl
  • Upload date:
  • Size: 19.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dstack_sdk-0.5.4b1-py3-none-any.whl
Algorithm Hash digest
SHA256 f2c122422cbe526f5e2de86b03caa8546997d26dc4609c834dc96d1030e85bb4
MD5 7259bb01480d29e8a632f6401340430f
BLAKE2b-256 1300bbf206d61a7ff544c8e900eed2e9332c9e5c5f1637e083a23273b68611d2

See more details on using hashes here.

Provenance

The following attestation bundles were made for dstack_sdk-0.5.4b1-py3-none-any.whl:

Publisher: python-sdk-release.yml on Dstack-TEE/dstack

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