dpp/identity/identity_public_key/v0/
random.rs

1use crate::identity::contract_bounds::ContractBounds;
2use crate::identity::identity_public_key::v0::IdentityPublicKeyV0;
3use crate::identity::KeyType::{ECDSA_HASH160, ECDSA_SECP256K1};
4use crate::identity::Purpose::{AUTHENTICATION, OWNER, TRANSFER, VOTING};
5use crate::identity::SecurityLevel::{CRITICAL, HIGH, MASTER, MEDIUM};
6use crate::identity::{KeyCount, KeyID, KeyType, Purpose, SecurityLevel};
7use crate::version::PlatformVersion;
8use crate::ProtocolError;
9use platform_value::BinaryData;
10use rand::rngs::StdRng;
11use rand::Rng;
12use std::convert::TryFrom;
13use std::ops::{Div, Rem};
14
15pub type UsedKeyMatrix = Vec<bool>;
16
17impl IdentityPublicKeyV0 {
18    pub fn random_authentication_key_with_rng(
19        id: KeyID,
20        rng: &mut StdRng,
21        used_key_matrix: Option<(KeyCount, &mut UsedKeyMatrix)>,
22        platform_version: &PlatformVersion,
23    ) -> Result<Self, ProtocolError> {
24        // we have 16 different permutations possible
25        let mut binding = [false; 16].to_vec();
26        let (key_count, key_matrix) = used_key_matrix.unwrap_or((0, &mut binding));
27        if key_count > 16 {
28            return Err(ProtocolError::PublicKeyGenerationError(
29                "too many keys already created".to_string(),
30            ));
31        }
32        let key_number = rng.gen_range(0..(16 - key_count as u8));
33        // now we need to find the first bool that isn't set to true
34        let mut needed_pos = None;
35        let mut counter = 0;
36        key_matrix.iter_mut().enumerate().for_each(|(pos, is_set)| {
37            if !*is_set {
38                if counter == key_number {
39                    needed_pos = Some(pos as u8);
40                    *is_set = true;
41                }
42                counter += 1;
43            }
44        });
45        let needed_pos = needed_pos.ok_or(ProtocolError::PublicKeyGenerationError(
46            "too many keys already created".to_string(),
47        ))?;
48        let key_type = needed_pos.div(&4);
49        let security_level = needed_pos.rem(&4);
50        let security_level = SecurityLevel::try_from(security_level).unwrap();
51        let key_type = KeyType::try_from(key_type).unwrap();
52        let read_only = false;
53        let data = BinaryData::new(key_type.random_public_key_data(rng, platform_version)?);
54        Ok(IdentityPublicKeyV0 {
55            id,
56            key_type,
57            purpose: AUTHENTICATION,
58            security_level,
59            read_only,
60            disabled_at: None,
61            data,
62            contract_bounds: None,
63        })
64    }
65
66    pub fn random_authentication_key_with_private_key_with_rng(
67        id: KeyID,
68        rng: &mut StdRng,
69        used_key_matrix: Option<(KeyCount, &mut UsedKeyMatrix)>,
70        platform_version: &PlatformVersion,
71    ) -> Result<(Self, [u8; 32]), ProtocolError> {
72        // we have 16 different permutations possible
73        let mut binding = [false; 16].to_vec();
74        let (key_count, key_matrix) = used_key_matrix.unwrap_or((0, &mut binding));
75        if key_count > 16 {
76            return Err(ProtocolError::PublicKeyGenerationError(
77                "too many keys already created".to_string(),
78            ));
79        }
80        let key_number = rng.gen_range(0..(12 - key_count as u8));
81        // now we need to find the first bool that isn't set to true
82        let mut needed_pos = None;
83        let mut counter = 0;
84        key_matrix.iter_mut().enumerate().for_each(|(pos, is_set)| {
85            if !*is_set {
86                if counter == key_number {
87                    needed_pos = Some(pos as u8);
88                    *is_set = true;
89                }
90                counter += 1;
91            }
92        });
93        let needed_pos = needed_pos.ok_or(ProtocolError::PublicKeyGenerationError(
94            "too many keys already created".to_string(),
95        ))?;
96        let key_type = needed_pos.div(&4);
97        let security_level = needed_pos.rem(&4);
98        let security_level = SecurityLevel::try_from(security_level).unwrap();
99        let key_type = KeyType::try_from(key_type).unwrap();
100        let read_only = false;
101        let (public_data, private_data) =
102            key_type.random_public_and_private_key_data(rng, platform_version)?;
103        let data = BinaryData::new(public_data);
104        Ok((
105            IdentityPublicKeyV0 {
106                id,
107                key_type,
108                purpose: AUTHENTICATION,
109                security_level,
110                read_only,
111                disabled_at: None,
112                data,
113                contract_bounds: None,
114            },
115            private_data,
116        ))
117    }
118
119    pub fn random_key_with_known_attributes(
120        id: KeyID,
121        rng: &mut StdRng,
122        purpose: Purpose,
123        security_level: SecurityLevel,
124        key_type: KeyType,
125        contract_bounds: Option<ContractBounds>,
126        platform_version: &PlatformVersion,
127    ) -> Result<(Self, [u8; 32]), ProtocolError> {
128        let read_only = false;
129        let (public_data, private_data) =
130            key_type.random_public_and_private_key_data(rng, platform_version)?;
131        let data = BinaryData::new(public_data);
132        let identity_public_key = IdentityPublicKeyV0 {
133            id,
134            key_type,
135            purpose,
136            security_level,
137            read_only,
138            disabled_at: None,
139            data,
140            contract_bounds,
141        };
142        Ok((identity_public_key, private_data))
143    }
144
145    pub fn random_key_with_rng(
146        id: KeyID,
147        rng: &mut StdRng,
148        used_key_matrix: Option<(KeyCount, &mut UsedKeyMatrix)>,
149        platform_version: &PlatformVersion,
150    ) -> Result<Self, ProtocolError> {
151        // we have 64 different permutations possible
152        let mut binding = [false; 64].to_vec();
153        let (key_count, key_matrix) = used_key_matrix.unwrap_or((0, &mut binding));
154        if key_count > 64 {
155            return Err(ProtocolError::PublicKeyGenerationError(
156                "too many keys already created".to_string(),
157            ));
158        }
159        let key_number = rng.gen_range(0..(64 - key_count as u8));
160        // now we need to find the first bool that isn't set to true
161        let mut needed_pos = None;
162        let mut counter = 0;
163        key_matrix.iter_mut().enumerate().for_each(|(pos, is_set)| {
164            if !*is_set {
165                if counter == key_number {
166                    needed_pos = Some(pos as u8);
167                    *is_set = true;
168                }
169                counter += 1;
170            }
171        });
172        let needed_pos = needed_pos.ok_or(ProtocolError::PublicKeyGenerationError(
173            "too many keys already created".to_string(),
174        ))?;
175        let security_level = needed_pos.div(&16);
176        let left = needed_pos.rem(&16);
177        let security_level = SecurityLevel::try_from(security_level).unwrap();
178        let key_type = left.div(&4);
179        let purpose = left.rem(&4);
180        let purpose = Purpose::try_from(purpose).unwrap();
181        let key_type = KeyType::try_from(key_type).unwrap();
182        let read_only = false;
183        let data = BinaryData::new(key_type.random_public_key_data(rng, platform_version)?);
184        Ok(IdentityPublicKeyV0 {
185            id,
186            key_type,
187            purpose,
188            security_level,
189            read_only,
190            disabled_at: None,
191            data,
192            contract_bounds: None,
193        })
194    }
195
196    pub fn random_ecdsa_master_authentication_key_with_rng(
197        id: KeyID,
198        rng: &mut StdRng,
199        platform_version: &PlatformVersion,
200    ) -> Result<(Self, [u8; 32]), ProtocolError> {
201        let key_type = ECDSA_SECP256K1;
202        let purpose = AUTHENTICATION;
203        let security_level = MASTER;
204        let read_only = false;
205        let (data, private_data) =
206            key_type.random_public_and_private_key_data(rng, platform_version)?;
207        Ok((
208            IdentityPublicKeyV0 {
209                id,
210                key_type,
211                purpose,
212                security_level,
213                read_only,
214                disabled_at: None,
215                data: data.into(),
216                contract_bounds: None,
217            },
218            private_data,
219        ))
220    }
221
222    pub fn random_voting_key_with_rng(
223        id: KeyID,
224        rng: &mut StdRng,
225        platform_version: &PlatformVersion,
226    ) -> Result<(Self, [u8; 32]), ProtocolError> {
227        let key_type = ECDSA_HASH160;
228        let purpose = VOTING;
229        let security_level = MEDIUM;
230        let read_only = false;
231        let (data, private_data) =
232            key_type.random_public_and_private_key_data(rng, platform_version)?;
233        Ok((
234            IdentityPublicKeyV0 {
235                id,
236                key_type,
237                purpose,
238                security_level,
239                read_only,
240                disabled_at: None,
241                data: data.into(),
242                contract_bounds: None,
243            },
244            private_data,
245        ))
246    }
247
248    pub fn random_owner_key_with_rng(
249        id: KeyID,
250        rng: &mut StdRng,
251        platform_version: &PlatformVersion,
252    ) -> Result<(Self, [u8; 32]), ProtocolError> {
253        let key_type = ECDSA_HASH160;
254        let purpose = OWNER;
255        let security_level = CRITICAL;
256        let read_only = true;
257        let (data, private_data) =
258            key_type.random_public_and_private_key_data(rng, platform_version)?;
259        Ok((
260            IdentityPublicKeyV0 {
261                id,
262                key_type,
263                purpose,
264                security_level,
265                read_only,
266                disabled_at: None,
267                data: data.into(),
268                contract_bounds: None,
269            },
270            private_data,
271        ))
272    }
273
274    pub fn random_masternode_transfer_key_with_rng(
275        id: KeyID,
276        rng: &mut StdRng,
277        platform_version: &PlatformVersion,
278    ) -> Result<(Self, [u8; 32]), ProtocolError> {
279        let key_type = ECDSA_HASH160;
280        let purpose = TRANSFER;
281        let security_level = CRITICAL;
282        let read_only = true;
283        let (data, private_data) =
284            key_type.random_public_and_private_key_data(rng, platform_version)?;
285        Ok((
286            IdentityPublicKeyV0 {
287                id,
288                key_type,
289                purpose,
290                security_level,
291                read_only,
292                disabled_at: None,
293                data: data.into(),
294                contract_bounds: None,
295            },
296            private_data,
297        ))
298    }
299
300    pub fn random_ecdsa_critical_level_authentication_key_with_rng(
301        id: KeyID,
302        rng: &mut StdRng,
303        platform_version: &PlatformVersion,
304    ) -> Result<(Self, [u8; 32]), ProtocolError> {
305        let key_type = ECDSA_SECP256K1;
306        let purpose = AUTHENTICATION;
307        let security_level = CRITICAL;
308        let read_only = false;
309        let (data, private_data) =
310            key_type.random_public_and_private_key_data(rng, platform_version)?;
311        Ok((
312            IdentityPublicKeyV0 {
313                id,
314                key_type,
315                purpose,
316                security_level,
317                read_only,
318                disabled_at: None,
319                data: data.into(),
320                contract_bounds: None,
321            },
322            private_data,
323        ))
324    }
325
326    pub fn random_ecdsa_high_level_authentication_key_with_rng(
327        id: KeyID,
328        rng: &mut StdRng,
329        platform_version: &PlatformVersion,
330    ) -> Result<(Self, [u8; 32]), ProtocolError> {
331        let key_type = ECDSA_SECP256K1;
332        let purpose = AUTHENTICATION;
333        let security_level = HIGH;
334        let read_only = false;
335        let (data, private_data) =
336            key_type.random_public_and_private_key_data(rng, platform_version)?;
337        Ok((
338            IdentityPublicKeyV0 {
339                id,
340                key_type,
341                purpose,
342                security_level,
343                read_only,
344                disabled_at: None,
345                data: data.into(),
346                contract_bounds: None,
347            },
348            private_data,
349        ))
350    }
351}