Skip to content

Commit e25fd5c

Browse files
committed
docs: keep v1 documentation free of chain flavor
1 parent b3c5d9b commit e25fd5c

9 files changed

Lines changed: 84 additions & 66 deletions

File tree

docs/guest-api-v1.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,8 @@ Generated with an app root key of
283283
|---|---|---|---|
284284
| `""` | secp256k1 | `59f60584ce6fd2a3a31997256db9d77322463fc8a6b1520110401bcb1ee92387` | `0377c7fb050db181d392266a3cee9adb2901c6d665f11bac68be5457f577ba4908` |
285285
| `""` | ed25519 | `b023493030669cf22e9cafa6a464d4cf3ae4edfe5474ec796710f21ea011946d` | `a3dc149fd5b765eab2eb7d3174fa939e39386898f10b15b7b146f6f1358ecf2a` |
286-
| `wallet` | secp256k1 | `2580611f0f936abe59399a8ac4ed9964d0259bd34c88ea012ca42b32acbf9386` | `0369cecd3c8da88730f7d45875824c3e75f63a2d3da4be42f45671954daa2abb28` |
287-
| `wallet` | ed25519 | `d76a703b08ebb074b809b9d6acf3d7c6663131273807717ce9d23bbadc2c644e` | `dade622d0fa1641e79b16e0b04e296be671f85f0aa6387b7d37e9d89f87494f5` |
286+
| `storage-encryption` | secp256k1 | `5510330f86902ddae38c6d89c93a8408019332c17a429e1abd01c4a28d1544a6` | `03d962450a41748021c8b02787ac36ce642ff0ae25f4c55019eb527e1112cfd764` |
287+
| `storage-encryption` | ed25519 | `3c4c3ece12fa99ccb93fc0090877f80e70545fdd971e2ac93d3398c4684538d3` | `2380c4a33a60b60613fa43866421e5b96eb8dcde211317200fd0d41e7e491288` |
288288
| `a/b/c` | secp256k1 | `7f0973449298085d2d36a3b4c4d3243c100ba1981ffa885fe9e9dee883e69538` | `02e9b1a61b6d70aa9b241753828c316bf90e33e77b2e113f9ba75a8b6dc3cde5c1` |
289289
| `k\0:ey` | ed25519 | `42da8bf0b479ed125c370e3b91f982735bf08ff592abbd586985affa43ee96a1` | `c833107822b003ff5675b33b90b151d4315c3ab9162b17d876e8dffde41abf9b` |
290290

@@ -324,21 +324,21 @@ key. `r` and `s` are 32-byte big-endian integers, low-S normalised, and `v` is t
324324
one-byte recovery id in `0..=3`. `public_key` is the raw derived public key from
325325
the table above, not a hex string.
326326

327-
A worked claim, for `domain = "wallet"` and `algorithm = "secp256k1"`:
327+
A worked claim, for `domain = "storage-encryption"` and `algorithm = "secp256k1"`:
328328

329329
```text
330330
00 00 00 19 "dstack-guest-v1-key-claim" 25 bytes
331331
00 00 00 09 "secp256k1" 9 bytes
332-
00 00 00 06 "wallet" 6 bytes
333-
00 00 00 21 03 69 ce cd ... bb 28 33 bytes
332+
00 00 00 12 "storage-encryption" 18 bytes
333+
00 00 00 21 03 d9 62 45 ... d7 64 33 bytes
334334
```
335335

336336
With the app root key from the test vector table, `link0` is
337337

338338
```text
339-
af26d2f258d34580e7288bd83fc97bddc83769476d77823c4f76a3ad77a75149
340-
1a39ffc4ef3aa66cb0d008b8f6f199e6d57c1da9a92ba4cf10f23bf752b8cad0
341-
00
339+
5b6193729ce7976ec67863f21692d4b98c69832698aae8e001a7d33a6f818b6e
340+
46ca950725b6e90e8ca9bcf394abd03ce264bf9b7eec1e91693247f9dd53c269
341+
01
342342
```
343343

344344
The signature is deterministic (RFC 6979), so this vector pins the whole encoding

dstack/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dstack/guest-agent/src/rpc_service_v1.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
//! This handler shares every backend with the unversioned one -- the same
1818
//! `AppState`, the same certificate client, the same platform attestation and
1919
//! GPU attestor. What it does not share is key derivation and the
20-
//! signature-chain claim, which are new in v1 and live in [`keys`].
20+
//! signature-chain claim, which are new in v1 and live in the `keys` submodule.
2121
//!
2222
//! v1 serves only what needs the TEE: deriving from the app root key, and
2323
//! attesting. It has no `Sign` and no `Verify`, because a caller that can
@@ -362,7 +362,7 @@ mod tests {
362362
for algorithm in ["secp256k1", "ed25519"] {
363363
let (state, _guard) = state().await;
364364
let key = V1RpcHandler::new(state)
365-
.get_key(get_key_request("wallet", algorithm))
365+
.get_key(get_key_request("storage-encryption", algorithm))
366366
.await
367367
.unwrap();
368368

@@ -382,13 +382,16 @@ mod tests {
382382

383383
let (state, _guard) = state().await;
384384
let key = V1RpcHandler::new(state.clone())
385-
.get_key(get_key_request("wallet", "secp256k1"))
385+
.get_key(get_key_request("storage-encryption", "secp256k1"))
386386
.await
387387
.unwrap();
388388

389-
let claim =
390-
ra_tls::api_v1::key_claim(keys::Algorithm::Secp256k1, "wallet", &key.public_key)
391-
.unwrap();
389+
let claim = ra_tls::api_v1::key_claim(
390+
keys::Algorithm::Secp256k1,
391+
"storage-encryption",
392+
&key.public_key,
393+
)
394+
.unwrap();
392395
let link = &key.signature_chain[0];
393396
let recovered = VerifyingKey::recover_from_digest(
394397
Keccak256::new_with_prefix(&claim),
@@ -411,7 +414,7 @@ mod tests {
411414
let (state, _guard) = state().await;
412415

413416
let secp = V1RpcHandler::new(state.clone())
414-
.get_key(get_key_request("wallet", "secp256k1"))
417+
.get_key(get_key_request("storage-encryption", "secp256k1"))
415418
.await
416419
.unwrap();
417420
let derived = k256::ecdsa::SigningKey::from_slice(&secp.key).unwrap();
@@ -421,7 +424,7 @@ mod tests {
421424
);
422425

423426
let ed = V1RpcHandler::new(state)
424-
.get_key(get_key_request("wallet", "ed25519"))
427+
.get_key(get_key_request("storage-encryption", "ed25519"))
425428
.await
426429
.unwrap();
427430
let seed: [u8; 32] = ed.key.as_slice().try_into().unwrap();
@@ -434,7 +437,7 @@ mod tests {
434437
let (state, _guard) = state().await;
435438
for algorithm in ["", "k256", "rsa", "secp256k1_prehashed"] {
436439
let result = V1RpcHandler::new(state.clone())
437-
.get_key(get_key_request("wallet", algorithm))
440+
.get_key(get_key_request("storage-encryption", algorithm))
438441
.await;
439442
assert!(result.is_err(), "v1 accepted algorithm {algorithm:?}");
440443
}
@@ -447,12 +450,12 @@ mod tests {
447450
async fn v1_keys_differ_from_the_unversioned_keys_for_the_same_name() {
448451
let (state, _guard) = state().await;
449452
let v1 = V1RpcHandler::new(state.clone())
450-
.get_key(get_key_request("wallet", "secp256k1"))
453+
.get_key(get_key_request("storage-encryption", "secp256k1"))
451454
.await
452455
.unwrap();
453456
let v0 = crate::rpc_service::InternalRpcHandler::new(state)
454457
.get_key(GetKeyArgs {
455-
path: "wallet".to_string(),
458+
path: "storage-encryption".to_string(),
456459
purpose: "signing".to_string(),
457460
algorithm: "secp256k1".to_string(),
458461
})

dstack/guest-agent/src/rpc_service_v1/keys.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,14 @@ mod tests {
109109
"a3dc149fd5b765eab2eb7d3174fa939e39386898f10b15b7b146f6f1358ecf2a",
110110
),
111111
(
112-
"wallet",
112+
"storage-encryption",
113113
Algorithm::Secp256k1,
114-
"0369cecd3c8da88730f7d45875824c3e75f63a2d3da4be42f45671954daa2abb28",
114+
"03d962450a41748021c8b02787ac36ce642ff0ae25f4c55019eb527e1112cfd764",
115115
),
116116
(
117-
"wallet",
117+
"storage-encryption",
118118
Algorithm::Ed25519,
119-
"dade622d0fa1641e79b16e0b04e296be671f85f0aa6387b7d37e9d89f87494f5",
119+
"2380c4a33a60b60613fa43866421e5b96eb8dcde211317200fd0d41e7e491288",
120120
),
121121
(
122122
"a/b/c",
@@ -142,15 +142,22 @@ mod tests {
142142
#[test]
143143
fn the_public_key_lengths_are_the_specified_ones() {
144144
assert_eq!(
145-
derive("wallet", Algorithm::Secp256k1).public_key().len(),
145+
derive("storage-encryption", Algorithm::Secp256k1)
146+
.public_key()
147+
.len(),
146148
33
147149
);
148-
assert_eq!(derive("wallet", Algorithm::Ed25519).public_key().len(), 32);
150+
assert_eq!(
151+
derive("storage-encryption", Algorithm::Ed25519)
152+
.public_key()
153+
.len(),
154+
32
155+
);
149156
}
150157

151158
#[test]
152159
fn the_two_algorithms_never_share_key_material() {
153-
for domain in ["", "wallet", "a/b/c"] {
160+
for domain in ["", "storage-encryption", "a/b/c"] {
154161
assert_ne!(
155162
derive(domain, Algorithm::Secp256k1).secret(),
156163
derive(domain, Algorithm::Ed25519).secret(),
@@ -164,12 +171,17 @@ mod tests {
164171
use k256::ecdsa::{RecoveryId, Signature, VerifyingKey};
165172
use sha3::{Digest as _, Keccak256};
166173

167-
let key = derive("wallet", Algorithm::Secp256k1);
174+
let key = derive("storage-encryption", Algorithm::Secp256k1);
168175
let app_root = SigningKey::from_slice(&TEST_APP_ROOT_KEY).unwrap();
169176
let link = key.claim_signature(&app_root).unwrap();
170177
assert_eq!(link.len(), 65);
171178

172-
let claim = key_claim(Algorithm::Secp256k1, "wallet", &key.public_key()).unwrap();
179+
let claim = key_claim(
180+
Algorithm::Secp256k1,
181+
"storage-encryption",
182+
&key.public_key(),
183+
)
184+
.unwrap();
173185
let recovered = VerifyingKey::recover_from_digest(
174186
Keccak256::new_with_prefix(&claim),
175187
&Signature::from_slice(&link[..64]).unwrap(),

dstack/ra-tls/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,5 @@ simulator = ["dstack-attest/simulator"]
5151
quote = ["dstack-attest/quote"]
5252

5353
[dev-dependencies]
54+
ed25519-dalek.workspace = true
5455
tokio = { workspace = true, features = ["macros", "rt"] }

dstack/ra-tls/src/api_v1.rs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,14 @@ mod tests {
191191

192192
#[test]
193193
fn encodes_derivation_info_with_length_prefixes() {
194-
let info = key_derivation_info("wallet", KeyAlgorithm::Secp256k1).unwrap();
194+
let info = key_derivation_info("storage-encryption", KeyAlgorithm::Secp256k1).unwrap();
195195
let expected = [
196196
&19u32.to_be_bytes()[..],
197197
b"dstack-guest-v1-key",
198198
&9u32.to_be_bytes()[..],
199199
b"secp256k1",
200-
&6u32.to_be_bytes()[..],
201-
b"wallet",
200+
&18u32.to_be_bytes()[..],
201+
b"storage-encryption",
202202
]
203203
.concat();
204204
assert_eq!(info, expected);
@@ -237,14 +237,14 @@ mod tests {
237237
"b023493030669cf22e9cafa6a464d4cf3ae4edfe5474ec796710f21ea011946d",
238238
),
239239
(
240-
"wallet",
240+
"storage-encryption",
241241
KeyAlgorithm::Secp256k1,
242-
"2580611f0f936abe59399a8ac4ed9964d0259bd34c88ea012ca42b32acbf9386",
242+
"5510330f86902ddae38c6d89c93a8408019332c17a429e1abd01c4a28d1544a6",
243243
),
244244
(
245-
"wallet",
245+
"storage-encryption",
246246
KeyAlgorithm::Ed25519,
247-
"d76a703b08ebb074b809b9d6acf3d7c6663131273807717ce9d23bbadc2c644e",
247+
"3c4c3ece12fa99ccb93fc0090877f80e70545fdd971e2ac93d3398c4684538d3",
248248
),
249249
(
250250
"a/b/c",
@@ -272,7 +272,7 @@ mod tests {
272272

273273
#[test]
274274
fn the_two_algorithms_never_share_key_material() {
275-
for domain in ["", "wallet", "a/b/c", "\u{0}"] {
275+
for domain in ["", "storage-encryption", "a/b/c", "\u{0}"] {
276276
assert_ne!(
277277
derive_app_key(&TEST_APP_ROOT_KEY, domain, KeyAlgorithm::Secp256k1).unwrap(),
278278
derive_app_key(&TEST_APP_ROOT_KEY, domain, KeyAlgorithm::Ed25519).unwrap(),
@@ -286,7 +286,7 @@ mod tests {
286286
/// string equals the old path.
287287
#[test]
288288
fn v1_keys_differ_from_v0_keys_for_the_same_name() {
289-
for name in ["", "wallet", "vms"] {
289+
for name in ["", "storage-encryption", "vms"] {
290290
let v0 = crate::kdf::derive_key(&TEST_APP_ROOT_KEY, &[name.as_bytes()], 32).unwrap();
291291
for algorithm in [KeyAlgorithm::Secp256k1, KeyAlgorithm::Ed25519] {
292292
assert_ne!(
@@ -309,8 +309,8 @@ mod tests {
309309
fn a_v0_path_cannot_reproduce_a_v1_key() {
310310
for (domain, algorithm) in [
311311
("", KeyAlgorithm::Secp256k1),
312-
("wallet", KeyAlgorithm::Secp256k1),
313-
("wallet", KeyAlgorithm::Ed25519),
312+
("storage-encryption", KeyAlgorithm::Secp256k1),
313+
("storage-encryption", KeyAlgorithm::Ed25519),
314314
] {
315315
let info = key_derivation_info(domain, algorithm).unwrap();
316316
// The best a v0 caller can do: hand the whole v1 info to `path`.
@@ -335,16 +335,16 @@ mod tests {
335335
#[test]
336336
fn encodes_the_claim_with_the_raw_public_key() {
337337
let public_key =
338-
hex::decode("0369cecd3c8da88730f7d45875824c3e75f63a2d3da4be42f45671954daa2abb28")
338+
hex::decode("03d962450a41748021c8b02787ac36ce642ff0ae25f4c55019eb527e1112cfd764")
339339
.unwrap();
340-
let claim = key_claim(KeyAlgorithm::Secp256k1, "wallet", &public_key).unwrap();
340+
let claim = key_claim(KeyAlgorithm::Secp256k1, "storage-encryption", &public_key).unwrap();
341341
let expected = [
342342
&25u32.to_be_bytes()[..],
343343
b"dstack-guest-v1-key-claim",
344344
&9u32.to_be_bytes()[..],
345345
b"secp256k1",
346-
&6u32.to_be_bytes()[..],
347-
b"wallet",
346+
&18u32.to_be_bytes()[..],
347+
b"storage-encryption",
348348
&33u32.to_be_bytes()[..],
349349
&public_key,
350350
]
@@ -358,9 +358,10 @@ mod tests {
358358
#[test]
359359
fn a_v0_claim_cannot_be_crafted_into_a_v1_claim() {
360360
let public_key =
361-
hex::decode("0369cecd3c8da88730f7d45875824c3e75f63a2d3da4be42f45671954daa2abb28")
361+
hex::decode("03d962450a41748021c8b02787ac36ce642ff0ae25f4c55019eb527e1112cfd764")
362362
.unwrap();
363-
let v1_claim = key_claim(KeyAlgorithm::Secp256k1, "wallet", &public_key).unwrap();
363+
let v1_claim =
364+
key_claim(KeyAlgorithm::Secp256k1, "storage-encryption", &public_key).unwrap();
364365

365366
// Best case for the attacker: the v1 claim minus exactly the suffix v0
366367
// appends on its own, used verbatim as `purpose`.
@@ -406,15 +407,15 @@ mod tests {
406407
#[test]
407408
fn produces_the_committed_claim_signature_vector() {
408409
let public_key =
409-
hex::decode("0369cecd3c8da88730f7d45875824c3e75f63a2d3da4be42f45671954daa2abb28")
410+
hex::decode("03d962450a41748021c8b02787ac36ce642ff0ae25f4c55019eb527e1112cfd764")
410411
.unwrap();
411-
let claim = key_claim(KeyAlgorithm::Secp256k1, "wallet", &public_key).unwrap();
412+
let claim = key_claim(KeyAlgorithm::Secp256k1, "storage-encryption", &public_key).unwrap();
412413
let key = SigningKey::from_slice(&TEST_APP_ROOT_KEY).unwrap();
413414
assert_eq!(
414415
hex::encode(sign_recoverable_keccak256(&key, &claim).unwrap()),
415-
"af26d2f258d34580e7288bd83fc97bddc83769476d77823c4f76a3ad77a75149\
416-
1a39ffc4ef3aa66cb0d008b8f6f199e6d57c1da9a92ba4cf10f23bf752b8cad0\
417-
00"
416+
"5b6193729ce7976ec67863f21692d4b98c69832698aae8e001a7d33a6f818b6e\
417+
46ca950725b6e90e8ca9bcf394abd03ce264bf9b7eec1e91693247f9dd53c269\
418+
01"
418419
);
419420
}
420421

sdk/curl/api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ Generates a deterministic private key from the application key and returns both
110110
| `purpose` | string | Purpose for the key. Can be any string. This is used in the signature chain and does not affect the private key bytes. | `"signing"` |
111111
| `algorithm` | string | `secp256k1` (default), `k256` (alias), or `ed25519`. For compatibility, this selects how the same derived 32-byte material is interpreted; it does not domain-separate the derivation. | `ed25519` |
112112

113-
Use algorithm-specific paths, such as `wallet/ethereum` and `wallet/solana`, when independent keys are required across algorithms.
113+
Use algorithm-specific paths, such as `backup-signing/secp256k1` and `backup-signing/ed25519`, when independent keys are required across algorithms.
114114

115115
**Example:**
116116
```bash

sdk/rust/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ async fn main() -> anyhow::Result<()> {
5252

5353
// Derive an application key. `domain` is a caller-chosen
5454
// domain-separation string; `algorithm` is required.
55-
let key = client.get_key("wallet", "secp256k1").await?;
55+
let key = client.get_key("storage-encryption", "secp256k1").await?;
5656
println!("public key: {}", key.public_key);
5757

5858
let info = client.info().await?;
@@ -77,7 +77,7 @@ let client = DstackClient::new(None);
7777
#### `get_key(domain: &str, algorithm: &str) -> GetKeyResponse`
7878

7979
```rust
80-
let key = client.get_key("wallet", "secp256k1").await?;
80+
let key = client.get_key("storage-encryption", "secp256k1").await?;
8181
let private_key = key.decode_key()?; // 32 bytes
8282
let public_key = key.decode_public_key()?; // SEC1 compressed, or 32 raw for ed25519
8383
```

0 commit comments

Comments
 (0)