Access TEE features from your Go application running inside dstack. Derive deterministic keys, generate attestation quotes, create TLS certificates, and sign data—all backed by hardware security.
go get github.com/Dstack-TEE/dstack/sdk/gopackage main
import (
"context"
"fmt"
"github.com/Dstack-TEE/dstack/sdk/go/dstack"
)
func main() {
client := dstack.NewDstackClient()
// Derive a deterministic key for your wallet
key, _ := client.GetKey(context.Background(), "wallet/eth", "", "secp256k1")
fmt.Println(key.Key) // Same path always returns the same key
// Generate an attestation quote
attest, _ := client.Attest(context.Background(), []byte("my-app-state"))
fmt.Println(attest.Attestation)
}The client automatically connects to /var/run/dstack.sock. For local development with the simulator:
client := dstack.NewDstackClient(dstack.WithEndpoint("http://localhost:8090"))GetKey() 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
ethKey, _ := client.GetKey(ctx, "wallet/ethereum", "", "secp256k1")
btcKey, _ := client.GetKey(ctx, "wallet/bitcoin", "", "secp256k1")
// Use path to separate keys
mainnetKey, _ := client.GetKey(ctx, "wallet/eth/mainnet", "", "secp256k1")
testnetKey, _ := client.GetKey(ctx, "wallet/eth/testnet", "", "secp256k1")
// Different algorithm
edKey, _ := client.GetKey(ctx, "signing/key", "", "ed25519")Parameters:
path: Key derivation path (determines the key)purpose: Included in signature chain message, does not affect the derived keyalgorithm:"secp256k1"or"ed25519"
Returns: *GetKeyResponse
Key: Hex-encoded private keySignatureChain: Signatures proving the key was derived in a genuine TEE
GetQuote() creates a TDX quote proving your code runs in a genuine TEE.
quote, _ := client.GetQuote(ctx, []byte("user:alice:nonce123"))
// Replay RTMRs from the event log
rtmrs, _ := quote.ReplayRTMRs()
fmt.Println(rtmrs)Parameters:
reportData: Exactly 64 bytes recommended. If shorter, pad with zeros. If longer, hash it first (e.g., SHA-256).
Returns: *GetQuoteResponse
Quote: TDX quote as bytesEventLog: JSON string of measured eventsReplayRTMRs(): Method to compute RTMR values from event log
Attest() creates a versioned attestation with the given report data.
attest, _ := client.Attest(ctx, []byte("my-app-state"))
fmt.Println(attest.Attestation)Parameters:
reportData: Exactly 64 bytes recommended. If shorter, pad with zeros. If longer, hash it first (e.g., SHA-256).
Returns: *AttestResponse
Attestation: Versioned attestation as bytes
info, _ := client.Info(ctx)
fmt.Println(info.AppID)
fmt.Println(info.InstanceID)
fmt.Println(info.TcbInfo)
// Decode TCB info for detailed measurements
tcb, _ := info.DecodeTcbInfo()
fmt.Println(tcb.Mrtd)Returns: *InfoResponse
AppID: Application identifierInstanceID: Instance identifierAppName: Application nameTcbInfo: TCB measurements (JSON string)ComposeHash: Hash of the app configurationAppCert: Application certificate (PEM)DecodeTcbInfo(): Helper method to parse TcbInfo JSON
GetTlsKey() creates fresh TLS certificates. Unlike GetKey(), each call generates a new random key.
tls, _ := client.GetTlsKey(
ctx,
dstack.WithSubject("api.example.com"),
dstack.WithAltNames([]string{"localhost"}),
dstack.WithUsageRaTls(true), // Embed attestation in certificate
dstack.WithUsageServerAuth(true),
)
fmt.Println(tls.Key) // PEM private key
fmt.Println(tls.CertificateChain) // Certificate chainOptions:
WithSubject(subject): Certificate common name (e.g., domain name)WithAltNames(altNames): List of subject alternative namesWithUsageRaTls(bool): Embed TDX quote in certificate extensionWithUsageServerAuth(bool): Enable for server authenticationWithUsageClientAuth(bool): Enable for client authentication
Returns: *GetTlsKeyResponse
Key: PEM-encoded private keyCertificateChain: List of PEM certificates
Sign data using TEE-derived keys (not yet released):
result, _ := client.Sign(ctx, "ed25519", []byte("message to sign"))
fmt.Println(result.Signature)
fmt.Println(result.PublicKey)
// Verify the signature
valid, _ := client.Verify(ctx, "ed25519", []byte("message to sign"), result.Signature, result.PublicKey)
fmt.Println(valid.Valid) // trueSign() Parameters:
algorithm:"ed25519","secp256k1", or"secp256k1_prehashed"data: Data to sign
Sign() Returns: *SignResponse
Signature: Signature bytesPublicKey: Public key bytesSignatureChain: Signatures proving TEE origin
Verify() Parameters:
algorithm: Algorithm used for signingdata: Original datasignature: Signature to verifypublicKey: Public key to verify against
Verify() Returns: *VerifyResponse
Valid: Boolean indicating if signature is valid
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.EmitEvent(ctx, "config_loaded", []byte("production"))
client.EmitEvent(ctx, "plugin_initialized", []byte("auth-v2"))Parameters:
event: Event name (string identifier)payload: Event value (bytes)
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-simulatorThen set the endpoint:
export DSTACK_SIMULATOR_ENDPOINT=http://localhost:8090Run tests:
go test -v ./dstackReplace tappd package with dstack:
// Before
import "github.com/Dstack-TEE/dstack/sdk/go/tappd"
client := tappd.NewTappdClient()
// After
import "github.com/Dstack-TEE/dstack/sdk/go/dstack"
client := dstack.NewDstackClient()Socket path: /var/run/tappd.sock → /var/run/dstack.sock
Apache License 2.0