tp_keystore/lib.rs
1// This file is part of Tetcore.
2
3// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Keystore traits
19pub mod testing;
20pub mod vrf;
21
22use std::sync::Arc;
23use async_trait::async_trait;
24use futures::{executor::block_on, future::join_all};
25use tet_core::{
26 crypto::{KeyTypeId, CryptoTypePublicPair},
27 ed25519, sr25519, ecdsa,
28};
29use crate::vrf::{VRFTranscriptData, VRFSignature};
30
31/// CryptoStore error
32#[derive(Debug, derive_more::Display)]
33pub enum Error {
34 /// Public key type is not supported
35 #[display(fmt="Key not supported: {:?}", _0)]
36 KeyNotSupported(KeyTypeId),
37 /// Pair not found for public key and KeyTypeId
38 #[display(fmt="Pair was not found: {}", _0)]
39 PairNotFound(String),
40 /// Validation error
41 #[display(fmt="Validation error: {}", _0)]
42 ValidationError(String),
43 /// Keystore unavailable
44 #[display(fmt="Keystore unavailable")]
45 Unavailable,
46 /// Programming errors
47 #[display(fmt="An unknown keystore error occurred: {}", _0)]
48 Other(String)
49}
50
51/// Something that generates, stores and provides access to keys.
52#[async_trait]
53pub trait CryptoStore: Send + Sync {
54 /// Returns all sr25519 public keys for the given key type.
55 async fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec<sr25519::Public>;
56 /// Generate a new sr25519 key pair for the given key type and an optional seed.
57 ///
58 /// If the given seed is `Some(_)`, the key pair will only be stored in memory.
59 ///
60 /// Returns the public key of the generated key pair.
61 async fn sr25519_generate_new(
62 &self,
63 id: KeyTypeId,
64 seed: Option<&str>,
65 ) -> Result<sr25519::Public, Error>;
66 /// Returns all ed25519 public keys for the given key type.
67 async fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec<ed25519::Public>;
68 /// Generate a new ed25519 key pair for the given key type and an optional seed.
69 ///
70 /// If the given seed is `Some(_)`, the key pair will only be stored in memory.
71 ///
72 /// Returns the public key of the generated key pair.
73 async fn ed25519_generate_new(
74 &self,
75 id: KeyTypeId,
76 seed: Option<&str>,
77 ) -> Result<ed25519::Public, Error>;
78 /// Returns all ecdsa public keys for the given key type.
79 async fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa::Public>;
80 /// Generate a new ecdsa key pair for the given key type and an optional seed.
81 ///
82 /// If the given seed is `Some(_)`, the key pair will only be stored in memory.
83 ///
84 /// Returns the public key of the generated key pair.
85 async fn ecdsa_generate_new(
86 &self,
87 id: KeyTypeId,
88 seed: Option<&str>,
89 ) -> Result<ecdsa::Public, Error>;
90
91 /// Insert a new key. This doesn't require any known of the crypto; but a public key must be
92 /// manually provided.
93 ///
94 /// Places it into the file system store.
95 ///
96 /// `Err` if there's some sort of weird filesystem error, but should generally be `Ok`.
97 async fn insert_unknown(
98 &self,
99 id: KeyTypeId,
100 suri: &str,
101 public: &[u8]
102 ) -> Result<(), ()>;
103
104 /// Find intersection between provided keys and supported keys
105 ///
106 /// Provided a list of (CryptoTypeId,[u8]) pairs, this would return
107 /// a filtered set of public keys which are supported by the keystore.
108 async fn supported_keys(
109 &self,
110 id: KeyTypeId,
111 keys: Vec<CryptoTypePublicPair>
112 ) -> Result<Vec<CryptoTypePublicPair>, Error>;
113 /// List all supported keys
114 ///
115 /// Returns a set of public keys the signer supports.
116 async fn keys(&self, id: KeyTypeId) -> Result<Vec<CryptoTypePublicPair>, Error>;
117
118 /// Checks if the private keys for the given public key and key type combinations exist.
119 ///
120 /// Returns `true` iff all private keys could be found.
121 async fn has_keys(&self, public_keys: &[(Vec<u8>, KeyTypeId)]) -> bool;
122
123 /// Sign with key
124 ///
125 /// Signs a message with the private key that matches
126 /// the public key passed.
127 ///
128 /// Returns the SCALE encoded signature if key is found & supported,
129 /// an error otherwise.
130 async fn sign_with(
131 &self,
132 id: KeyTypeId,
133 key: &CryptoTypePublicPair,
134 msg: &[u8],
135 ) -> Result<Vec<u8>, Error>;
136
137 /// Sign with any key
138 ///
139 /// Given a list of public keys, find the first supported key and
140 /// sign the provided message with that key.
141 ///
142 /// Returns a tuple of the used key and the SCALE encoded signature.
143 async fn sign_with_any(
144 &self,
145 id: KeyTypeId,
146 keys: Vec<CryptoTypePublicPair>,
147 msg: &[u8]
148 ) -> Result<(CryptoTypePublicPair, Vec<u8>), Error> {
149 if keys.len() == 1 {
150 return self.sign_with(id, &keys[0], msg).await.map(|s| (keys[0].clone(), s));
151 } else {
152 for k in self.supported_keys(id, keys).await? {
153 if let Ok(sign) = self.sign_with(id, &k, msg).await {
154 return Ok((k, sign));
155 }
156 }
157 }
158 Err(Error::KeyNotSupported(id))
159 }
160
161 /// Sign with all keys
162 ///
163 /// Provided a list of public keys, sign a message with
164 /// each key given that the key is supported.
165 ///
166 /// Returns a list of `Result`s each representing the SCALE encoded
167 /// signature of each key or a Error for non-supported keys.
168 async fn sign_with_all(
169 &self,
170 id: KeyTypeId,
171 keys: Vec<CryptoTypePublicPair>,
172 msg: &[u8],
173 ) -> Result<Vec<Result<Vec<u8>, Error>>, ()> {
174 let futs = keys.iter()
175 .map(|k| self.sign_with(id, k, msg));
176
177 Ok(join_all(futs).await)
178 }
179
180 /// Generate VRF signature for given transcript data.
181 ///
182 /// Receives KeyTypeId and Public key to be able to map
183 /// them to a private key that exists in the keystore which
184 /// is, in turn, used for signing the provided transcript.
185 ///
186 /// Returns a result containing the signature data.
187 /// Namely, VRFOutput and VRFProof which are returned
188 /// inside the `VRFSignature` container struct.
189 ///
190 /// This function will return an error in the cases where
191 /// the public key and key type provided do not match a private
192 /// key in the keystore. Or, in the context of remote signing
193 /// an error could be a network one.
194 async fn sr25519_vrf_sign(
195 &self,
196 key_type: KeyTypeId,
197 public: &sr25519::Public,
198 transcript_data: VRFTranscriptData,
199 ) -> Result<VRFSignature, Error>;
200}
201
202/// Sync version of the CryptoStore
203///
204/// Some parts of Tetcore still rely on a sync version of the `CryptoStore`.
205/// To make the transition easier this auto trait wraps any async `CryptoStore` and
206/// exposes a `sync` interface using `block_on`. Usage of this is deprecated and it
207/// will be removed as soon as the internal usage has transitioned successfully.
208/// If you are starting out building something new **do not use this**,
209/// instead, use [`CryptoStore`].
210pub trait SyncCryptoStore: CryptoStore + Send + Sync {
211 /// Returns all sr25519 public keys for the given key type.
212 fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec<sr25519::Public>;
213
214 /// Generate a new sr25519 key pair for the given key type and an optional seed.
215 ///
216 /// If the given seed is `Some(_)`, the key pair will only be stored in memory.
217 ///
218 /// Returns the public key of the generated key pair.
219 fn sr25519_generate_new(
220 &self,
221 id: KeyTypeId,
222 seed: Option<&str>,
223 ) -> Result<sr25519::Public, Error>;
224
225 /// Returns all ed25519 public keys for the given key type.
226 fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec<ed25519::Public>;
227
228 /// Generate a new ed25519 key pair for the given key type and an optional seed.
229 ///
230 /// If the given seed is `Some(_)`, the key pair will only be stored in memory.
231 ///
232 /// Returns the public key of the generated key pair.
233 fn ed25519_generate_new(
234 &self,
235 id: KeyTypeId,
236 seed: Option<&str>,
237 ) -> Result<ed25519::Public, Error>;
238
239 /// Returns all ecdsa public keys for the given key type.
240 fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa::Public>;
241
242 /// Generate a new ecdsa key pair for the given key type and an optional seed.
243 ///
244 /// If the given seed is `Some(_)`, the key pair will only be stored in memory.
245 ///
246 /// Returns the public key of the generated key pair.
247 fn ecdsa_generate_new(
248 &self,
249 id: KeyTypeId,
250 seed: Option<&str>,
251 ) -> Result<ecdsa::Public, Error>;
252
253 /// Insert a new key. This doesn't require any known of the crypto; but a public key must be
254 /// manually provided.
255 ///
256 /// Places it into the file system store.
257 ///
258 /// `Err` if there's some sort of weird filesystem error, but should generally be `Ok`.
259 fn insert_unknown(&self, key_type: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()>;
260
261 /// Find intersection between provided keys and supported keys
262 ///
263 /// Provided a list of (CryptoTypeId,[u8]) pairs, this would return
264 /// a filtered set of public keys which are supported by the keystore.
265 fn supported_keys(
266 &self,
267 id: KeyTypeId,
268 keys: Vec<CryptoTypePublicPair>
269 ) -> Result<Vec<CryptoTypePublicPair>, Error>;
270
271 /// List all supported keys
272 ///
273 /// Returns a set of public keys the signer supports.
274 fn keys(&self, id: KeyTypeId) -> Result<Vec<CryptoTypePublicPair>, Error> {
275 block_on(CryptoStore::keys(self, id))
276 }
277
278 /// Checks if the private keys for the given public key and key type combinations exist.
279 ///
280 /// Returns `true` iff all private keys could be found.
281 fn has_keys(&self, public_keys: &[(Vec<u8>, KeyTypeId)]) -> bool;
282
283 /// Sign with key
284 ///
285 /// Signs a message with the private key that matches
286 /// the public key passed.
287 ///
288 /// Returns the SCALE encoded signature if key is found & supported,
289 /// an error otherwise.
290 fn sign_with(
291 &self,
292 id: KeyTypeId,
293 key: &CryptoTypePublicPair,
294 msg: &[u8],
295 ) -> Result<Vec<u8>, Error>;
296
297 /// Sign with any key
298 ///
299 /// Given a list of public keys, find the first supported key and
300 /// sign the provided message with that key.
301 ///
302 /// Returns a tuple of the used key and the SCALE encoded signature.
303 fn sign_with_any(
304 &self,
305 id: KeyTypeId,
306 keys: Vec<CryptoTypePublicPair>,
307 msg: &[u8]
308 ) -> Result<(CryptoTypePublicPair, Vec<u8>), Error> {
309 if keys.len() == 1 {
310 return SyncCryptoStore::sign_with(self, id, &keys[0], msg).map(|s| (keys[0].clone(), s));
311 } else {
312 for k in SyncCryptoStore::supported_keys(self, id, keys)? {
313 if let Ok(sign) = SyncCryptoStore::sign_with(self, id, &k, msg) {
314 return Ok((k, sign));
315 }
316 }
317 }
318 Err(Error::KeyNotSupported(id))
319 }
320
321 /// Sign with all keys
322 ///
323 /// Provided a list of public keys, sign a message with
324 /// each key given that the key is supported.
325 ///
326 /// Returns a list of `Result`s each representing the SCALE encoded
327 /// signature of each key or a Error for non-supported keys.
328 fn sign_with_all(
329 &self,
330 id: KeyTypeId,
331 keys: Vec<CryptoTypePublicPair>,
332 msg: &[u8],
333 ) -> Result<Vec<Result<Vec<u8>, Error>>, ()>{
334 Ok(keys.iter().map(|k| SyncCryptoStore::sign_with(self, id, k, msg)).collect())
335 }
336
337 /// Generate VRF signature for given transcript data.
338 ///
339 /// Receives KeyTypeId and Public key to be able to map
340 /// them to a private key that exists in the keystore which
341 /// is, in turn, used for signing the provided transcript.
342 ///
343 /// Returns a result containing the signature data.
344 /// Namely, VRFOutput and VRFProof which are returned
345 /// inside the `VRFSignature` container struct.
346 ///
347 /// This function will return an error in the cases where
348 /// the public key and key type provided do not match a private
349 /// key in the keystore. Or, in the context of remote signing
350 /// an error could be a network one.
351 fn sr25519_vrf_sign(
352 &self,
353 key_type: KeyTypeId,
354 public: &sr25519::Public,
355 transcript_data: VRFTranscriptData,
356 ) -> Result<VRFSignature, Error>;
357}
358
359/// A pointer to a keystore.
360pub type SyncCryptoStorePtr = Arc<dyn SyncCryptoStore>;
361
362externalities::decl_extension! {
363 /// The keystore extension to register/retrieve from the externalities.
364 pub struct KeystoreExt(SyncCryptoStorePtr);
365}