Skip to main content

appcore_dnt/
migration.rs

1// =============================================================================
2//        #######
3//     ###       ###     F: migration.rs
4//    ##   ## ##   ##    P: AppCore-Runtime
5//         ## ##
6//                       C: 2026/08/02 12:07:11 by dnettoRaw
7//    ##   ## ##   ##    U: 2026/08/02 12:07:11 by dnettoRaw
8//      ###########      S: 1.0.1-rc.8
9// =============================================================================
10
11//! DNT key rotation and envelope migration operations.
12
13use crate::{
14    open, seal, DntCodec, DntKeyProvider, DntOpenOptions, DntResult, DntSealOptions, KeyId,
15    OpenedDnt,
16};
17/// Opens and seals the same semantic payload under a new key identifier.
18pub fn rekey<P, C>(
19    input: &[u8],
20    key_provider: &P,
21    codec: &C,
22    options: &DntOpenOptions,
23    new_key_id: KeyId,
24) -> DntResult<Vec<u8>>
25where
26    P: DntKeyProvider,
27    C: DntCodec,
28{
29    reseal(input, key_provider, codec, options, Some(new_key_id))
30}
31
32/// Migrates an envelope by opening and resealing it with the current writer.
33pub fn migrate_envelope<P, C>(
34    input: &[u8],
35    key_provider: &P,
36    codec: &C,
37    options: &DntOpenOptions,
38) -> DntResult<Vec<u8>>
39where
40    P: DntKeyProvider,
41    C: DntCodec,
42{
43    reseal(input, key_provider, codec, options, None)
44}
45
46fn reseal<P, C>(
47    input: &[u8],
48    key_provider: &P,
49    codec: &C,
50    options: &DntOpenOptions,
51    new_key_id: Option<KeyId>,
52) -> DntResult<Vec<u8>>
53where
54    P: DntKeyProvider,
55    C: DntCodec,
56{
57    let mut opened = open(input, key_provider, codec, options)?;
58    let key_id = new_key_id.unwrap_or_else(|| opened.header.key_id.clone());
59    let seal_options = options_from_opened(&opened, key_id, options.max_payload_bytes);
60    let result = seal(&opened.payload, key_provider, codec, seal_options);
61    opened.zeroize_plaintext();
62    result
63}
64
65fn options_from_opened(
66    opened: &OpenedDnt,
67    key_id: KeyId,
68    max_payload_bytes: Option<u64>,
69) -> DntSealOptions {
70    DntSealOptions {
71        application_id: opened.header.application_id.clone(),
72        tenant_id: opened.header.tenant_id.clone(),
73        content_type: opened.header.content_type.clone(),
74        schema_version: opened.header.schema_version,
75        key_id,
76        created_at_ms: opened.header.created_at_ms,
77        public_metadata: opened.header.public_metadata.clone(),
78        encrypted_metadata: opened.encrypted_metadata.clone(),
79        flags: opened.header.flags,
80        max_payload_bytes,
81    }
82}