ockam_entity/worker/
create_key.rs

1use crate::change_history::ProfileChangeHistory;
2use crate::profile::Profile;
3use crate::EntityError::InvalidInternalState;
4use crate::{
5    ChangeBlock, EntityError, EventIdentifier, KeyAttributes, MetaKeyAttributes, ProfileChange,
6    ProfileChangeEvent, ProfileChangeType, ProfileEventAttributes, ProfileState, Signature,
7    SignatureType,
8};
9use ockam_core::vault::Signature as OckamVaultSignature;
10use ockam_core::vault::{Hasher, SecretVault, Signer};
11use ockam_core::vault::{PublicKey, Secret};
12use ockam_core::{Encodable, Result};
13use ockam_vault_sync_core::VaultSync;
14use serde::{Deserialize, Serialize};
15
16/// Key change data creation
17#[derive(Serialize, Deserialize, Debug, Clone)]
18pub struct CreateKeyChangeData {
19    key_attributes: KeyAttributes,
20    public_key: PublicKey,
21}
22
23impl CreateKeyChangeData {
24    /// Return key attributes
25    pub fn key_attributes(&self) -> &KeyAttributes {
26        &self.key_attributes
27    }
28    /// Return public key
29    pub fn public_key(&self) -> &PublicKey {
30        &self.public_key
31    }
32}
33
34impl CreateKeyChangeData {
35    /// Create new CreateKeyChangeData
36    pub fn new(key_attributes: KeyAttributes, public_key: PublicKey) -> Self {
37        CreateKeyChangeData {
38            key_attributes,
39            public_key,
40        }
41    }
42}
43
44/// Key change creation
45#[derive(Serialize, Deserialize, Debug, Clone)]
46pub struct CreateKeyChange {
47    data: CreateKeyChangeData,
48    self_signature: OckamVaultSignature,
49}
50
51impl CreateKeyChange {
52    /// Return data
53    pub fn data(&self) -> &CreateKeyChangeData {
54        &self.data
55    }
56    /// Return self signature
57    pub fn self_signature(&self) -> &OckamVaultSignature {
58        &self.self_signature
59    }
60}
61
62impl CreateKeyChange {
63    /// Create new CreateKeyChange
64    pub fn new(data: CreateKeyChangeData, self_signature: OckamVaultSignature) -> Self {
65        CreateKeyChange {
66            data,
67            self_signature,
68        }
69    }
70}
71
72impl ProfileState {
73    async fn generate_key_if_needed(
74        secret: Option<&Secret>,
75        key_attributes: &KeyAttributes,
76        vault: &mut VaultSync,
77    ) -> Result<Secret> {
78        if let Some(s) = secret {
79            Ok(s.clone())
80        } else {
81            let MetaKeyAttributes::SecretAttributes(secret_attributes) = key_attributes.meta();
82
83            vault.secret_generate(*secret_attributes).await
84        }
85    }
86
87    /// Create a new key
88    pub(crate) async fn make_create_key_event_static(
89        secret: Option<&Secret>,
90        prev_id: EventIdentifier,
91        key_attributes: KeyAttributes,
92        attributes: ProfileEventAttributes,
93        root_key: Option<&Secret>,
94        vault: &mut VaultSync,
95    ) -> Result<ProfileChangeEvent> {
96        let secret_key = Self::generate_key_if_needed(secret, &key_attributes, vault).await?;
97
98        let public_key = vault.secret_public_key_get(&secret_key).await?;
99
100        let data = CreateKeyChangeData::new(key_attributes, public_key);
101        let data_binary = data.encode().map_err(|_| EntityError::BareError)?;
102        let data_hash = vault.sha256(data_binary.as_slice()).await?;
103        let self_signature = vault.sign(&secret_key, &data_hash).await?;
104        let change = CreateKeyChange::new(data, self_signature);
105
106        let profile_change = ProfileChange::new(
107            Profile::CURRENT_CHANGE_VERSION,
108            attributes,
109            ProfileChangeType::CreateKey(change),
110        );
111
112        let change_block = ChangeBlock::new(prev_id, profile_change);
113        let change_block_binary = change_block.encode().map_err(|_| EntityError::BareError)?;
114
115        let event_id = vault.sha256(&change_block_binary).await?;
116        let event_id = EventIdentifier::from_hash(event_id);
117
118        let self_signature = vault.sign(&secret_key, event_id.as_ref()).await?;
119        let self_signature = Signature::new(SignatureType::SelfSign, self_signature);
120
121        let mut signatures = vec![self_signature];
122
123        // If we have root_key passed we should sign using it
124        // If there is no root_key - we're creating new profile, so we just generated root_key
125        if let Some(root_key) = root_key {
126            let root_signature = vault.sign(root_key, event_id.as_ref()).await?;
127            let root_signature = Signature::new(SignatureType::RootSign, root_signature);
128
129            signatures.push(root_signature);
130        }
131
132        let signed_change_event = ProfileChangeEvent::new(event_id, change_block, signatures);
133
134        Ok(signed_change_event)
135    }
136
137    /// Create a new key
138    pub(crate) async fn make_create_key_event(
139        &mut self,
140        secret: Option<&Secret>,
141        key_attributes: KeyAttributes,
142        attributes: ProfileEventAttributes,
143    ) -> Result<ProfileChangeEvent> {
144        // Creating key after it was revoked is forbidden
145        if ProfileChangeHistory::find_last_key_event(
146            self.change_history().as_ref(),
147            key_attributes.label(),
148        )
149        .is_ok()
150        {
151            return Err(InvalidInternalState.into());
152        }
153
154        let prev_id = match self.change_history().get_last_event_id() {
155            Ok(prev_id) => prev_id,
156            Err(_) => EventIdentifier::initial(&mut self.vault).await,
157        };
158
159        let root_secret = self.get_root_secret_key().await?;
160        let root_key = Some(&root_secret);
161
162        Self::make_create_key_event_static(
163            secret,
164            prev_id,
165            key_attributes,
166            attributes,
167            root_key,
168            &mut self.vault,
169        )
170        .await
171    }
172}