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}