tp_keystore/
testing.rs

1// This file is part of Tetcore.
2
3// Copyright (C) 2019-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//! Types that should only be used for testing!
19
20use tet_core::crypto::KeyTypeId;
21use tet_core::{
22	crypto::{Pair, Public, CryptoTypePublicPair},
23	ed25519, sr25519, ecdsa,
24};
25use crate::{
26	{CryptoStore, SyncCryptoStorePtr, Error, SyncCryptoStore},
27	vrf::{VRFTranscriptData, VRFSignature, make_transcript},
28};
29use std::{collections::{HashMap, HashSet}, sync::Arc};
30use parking_lot::RwLock;
31use async_trait::async_trait;
32
33/// A keystore implementation usable in tests.
34#[derive(Default)]
35pub struct KeyStore {
36	/// `KeyTypeId` maps to public keys and public keys map to private keys.
37	keys: Arc<RwLock<HashMap<KeyTypeId, HashMap<Vec<u8>, String>>>>,
38}
39
40impl KeyStore {
41	/// Creates a new instance of `Self`.
42	pub fn new() -> Self {
43		Self::default()
44	}
45
46	fn sr25519_key_pair(&self, id: KeyTypeId, pub_key: &sr25519::Public) -> Option<sr25519::Pair> {
47		self.keys.read().get(&id)
48			.and_then(|inner|
49				inner.get(pub_key.as_slice())
50					.map(|s| sr25519::Pair::from_string(s, None).expect("`sr25519` seed slice is valid"))
51			)
52	}
53
54	fn ed25519_key_pair(&self, id: KeyTypeId, pub_key: &ed25519::Public) -> Option<ed25519::Pair> {
55		self.keys.read().get(&id)
56			.and_then(|inner|
57				inner.get(pub_key.as_slice())
58					.map(|s| ed25519::Pair::from_string(s, None).expect("`ed25519` seed slice is valid"))
59			)
60	}
61
62	fn ecdsa_key_pair(&self, id: KeyTypeId, pub_key: &ecdsa::Public) -> Option<ecdsa::Pair> {
63		self.keys.read().get(&id)
64			.and_then(|inner|
65				inner.get(pub_key.as_slice())
66					.map(|s| ecdsa::Pair::from_string(s, None).expect("`ecdsa` seed slice is valid"))
67			)
68	}
69
70}
71
72#[async_trait]
73impl CryptoStore for KeyStore {
74	async fn keys(&self, id: KeyTypeId) -> Result<Vec<CryptoTypePublicPair>, Error> {
75		SyncCryptoStore::keys(self, id)
76	}
77
78	async fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec<sr25519::Public> {
79		SyncCryptoStore::sr25519_public_keys(self, id)
80	}
81
82	async fn sr25519_generate_new(
83		&self,
84		id: KeyTypeId,
85		seed: Option<&str>,
86	) -> Result<sr25519::Public, Error> {
87		SyncCryptoStore::sr25519_generate_new(self, id, seed)
88	}
89
90	async fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec<ed25519::Public> {
91		SyncCryptoStore::ed25519_public_keys(self, id)
92	}
93
94	async fn ed25519_generate_new(
95		&self,
96		id: KeyTypeId,
97		seed: Option<&str>,
98	) -> Result<ed25519::Public, Error> {
99		SyncCryptoStore::ed25519_generate_new(self, id, seed)
100	}
101
102	async fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa::Public> {
103		SyncCryptoStore::ecdsa_public_keys(self, id)
104	}
105
106	async fn ecdsa_generate_new(
107		&self,
108		id: KeyTypeId,
109		seed: Option<&str>,
110	) -> Result<ecdsa::Public, Error> {
111		SyncCryptoStore::ecdsa_generate_new(self, id, seed)
112	}
113
114	async fn insert_unknown(&self, id: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()> {
115		SyncCryptoStore::insert_unknown(self, id, suri, public)
116	}
117
118	async fn has_keys(&self, public_keys: &[(Vec<u8>, KeyTypeId)]) -> bool {
119		SyncCryptoStore::has_keys(self, public_keys)
120	}
121
122	async fn supported_keys(
123		&self,
124		id: KeyTypeId,
125		keys: Vec<CryptoTypePublicPair>,
126	) -> std::result::Result<Vec<CryptoTypePublicPair>, Error> {
127		SyncCryptoStore::supported_keys(self, id, keys)
128	}
129
130	async fn sign_with(
131		&self,
132		id: KeyTypeId,
133		key: &CryptoTypePublicPair,
134		msg: &[u8],
135	) -> Result<Vec<u8>, Error> {
136		SyncCryptoStore::sign_with(self, id, key, msg)
137	}
138
139	async fn sr25519_vrf_sign(
140		&self,
141		key_type: KeyTypeId,
142		public: &sr25519::Public,
143		transcript_data: VRFTranscriptData,
144	) -> Result<VRFSignature, Error> {
145		SyncCryptoStore::sr25519_vrf_sign(self, key_type, public, transcript_data)
146	}
147}
148
149impl SyncCryptoStore for KeyStore {
150	fn keys(&self, id: KeyTypeId) -> Result<Vec<CryptoTypePublicPair>, Error> {
151		self.keys.read()
152			.get(&id)
153			.map(|map| {
154				Ok(map.keys()
155					.fold(Vec::new(), |mut v, k| {
156						v.push(CryptoTypePublicPair(sr25519::CRYPTO_ID, k.clone()));
157						v.push(CryptoTypePublicPair(ed25519::CRYPTO_ID, k.clone()));
158						v.push(CryptoTypePublicPair(ecdsa::CRYPTO_ID, k.clone()));
159						v
160					}))
161			})
162			.unwrap_or_else(|| Ok(vec![]))
163	}
164
165	fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec<sr25519::Public> {
166		self.keys.read().get(&id)
167			.map(|keys|
168				keys.values()
169					.map(|s| sr25519::Pair::from_string(s, None).expect("`sr25519` seed slice is valid"))
170					.map(|p| p.public())
171					.collect()
172			)
173			.unwrap_or_default()
174	}
175
176	fn sr25519_generate_new(
177		&self,
178		id: KeyTypeId,
179		seed: Option<&str>,
180	) -> Result<sr25519::Public, Error> {
181		match seed {
182			Some(seed) => {
183				let pair = sr25519::Pair::from_string(seed, None)
184					.map_err(|_| Error::ValidationError("Generates an `sr25519` pair.".to_owned()))?;
185				self.keys.write().entry(id).or_default().insert(pair.public().to_raw_vec(), seed.into());
186				Ok(pair.public())
187			},
188			None => {
189				let (pair, phrase, _) = sr25519::Pair::generate_with_phrase(None);
190				self.keys.write().entry(id).or_default().insert(pair.public().to_raw_vec(), phrase);
191				Ok(pair.public())
192			}
193		}
194	}
195
196	fn ed25519_public_keys(&self, id: KeyTypeId) -> Vec<ed25519::Public> {
197		self.keys.read().get(&id)
198			.map(|keys|
199				keys.values()
200					.map(|s| ed25519::Pair::from_string(s, None).expect("`ed25519` seed slice is valid"))
201					.map(|p| p.public())
202					.collect()
203			)
204			.unwrap_or_default()
205	}
206
207	fn ed25519_generate_new(
208		&self,
209		id: KeyTypeId,
210		seed: Option<&str>,
211	) -> Result<ed25519::Public, Error> {
212		match seed {
213			Some(seed) => {
214				let pair = ed25519::Pair::from_string(seed, None)
215					.map_err(|_| Error::ValidationError("Generates an `ed25519` pair.".to_owned()))?;
216				self.keys.write().entry(id).or_default().insert(pair.public().to_raw_vec(), seed.into());
217				Ok(pair.public())
218			},
219			None => {
220				let (pair, phrase, _) = ed25519::Pair::generate_with_phrase(None);
221				self.keys.write().entry(id).or_default().insert(pair.public().to_raw_vec(), phrase);
222				Ok(pair.public())
223			}
224		}
225	}
226
227	fn ecdsa_public_keys(&self, id: KeyTypeId) -> Vec<ecdsa::Public> {
228		self.keys.read().get(&id)
229			.map(|keys|
230				keys.values()
231					.map(|s| ecdsa::Pair::from_string(s, None).expect("`ecdsa` seed slice is valid"))
232					.map(|p| p.public())
233					.collect()
234			)
235			.unwrap_or_default()
236	}
237
238	fn ecdsa_generate_new(
239		&self,
240		id: KeyTypeId,
241		seed: Option<&str>,
242	) -> Result<ecdsa::Public, Error> {
243		match seed {
244			Some(seed) => {
245				let pair = ecdsa::Pair::from_string(seed, None)
246					.map_err(|_| Error::ValidationError("Generates an `ecdsa` pair.".to_owned()))?;
247				self.keys.write().entry(id).or_default().insert(pair.public().to_raw_vec(), seed.into());
248				Ok(pair.public())
249			},
250			None => {
251				let (pair, phrase, _) = ecdsa::Pair::generate_with_phrase(None);
252				self.keys.write().entry(id).or_default().insert(pair.public().to_raw_vec(), phrase);
253				Ok(pair.public())
254			}
255		}
256	}
257
258	fn insert_unknown(&self, id: KeyTypeId, suri: &str, public: &[u8]) -> Result<(), ()> {
259		self.keys.write().entry(id).or_default().insert(public.to_owned(), suri.to_string());
260		Ok(())
261	}
262
263	fn has_keys(&self, public_keys: &[(Vec<u8>, KeyTypeId)]) -> bool {
264		public_keys.iter().all(|(k, t)| self.keys.read().get(&t).and_then(|s| s.get(k)).is_some())
265	}
266
267	fn supported_keys(
268		&self,
269		id: KeyTypeId,
270		keys: Vec<CryptoTypePublicPair>,
271	) -> std::result::Result<Vec<CryptoTypePublicPair>, Error> {
272		let provided_keys = keys.into_iter().collect::<HashSet<_>>();
273		let all_keys = SyncCryptoStore::keys(self, id)?.into_iter().collect::<HashSet<_>>();
274
275		Ok(provided_keys.intersection(&all_keys).cloned().collect())
276	}
277
278	fn sign_with(
279		&self,
280		id: KeyTypeId,
281		key: &CryptoTypePublicPair,
282		msg: &[u8],
283	) -> Result<Vec<u8>, Error> {
284		use codec::Encode;
285
286		match key.0 {
287			ed25519::CRYPTO_ID => {
288				let key_pair: ed25519::Pair = self
289					.ed25519_key_pair(id, &ed25519::Public::from_slice(key.1.as_slice()))
290					.ok_or_else(|| Error::PairNotFound("ed25519".to_owned()))?;
291				return Ok(key_pair.sign(msg).encode());
292			}
293			sr25519::CRYPTO_ID => {
294				let key_pair: sr25519::Pair = self
295					.sr25519_key_pair(id, &sr25519::Public::from_slice(key.1.as_slice()))
296					.ok_or_else(|| Error::PairNotFound("sr25519".to_owned()))?;
297				return Ok(key_pair.sign(msg).encode());
298			}
299			ecdsa::CRYPTO_ID => {
300				let key_pair: ecdsa::Pair = self
301					.ecdsa_key_pair(id, &ecdsa::Public::from_slice(key.1.as_slice()))
302					.ok_or_else(|| Error::PairNotFound("ecdsa".to_owned()))?;
303				return Ok(key_pair.sign(msg).encode());
304			}
305			_ => Err(Error::KeyNotSupported(id))
306		}
307	}
308
309	fn sr25519_vrf_sign(
310		&self,
311		key_type: KeyTypeId,
312		public: &sr25519::Public,
313		transcript_data: VRFTranscriptData,
314	) -> Result<VRFSignature, Error> {
315		let transcript = make_transcript(transcript_data);
316		let pair = self.sr25519_key_pair(key_type, public)
317			.ok_or_else(|| Error::PairNotFound("Not found".to_owned()))?;
318		let (inout, proof, _) = pair.as_ref().vrf_sign(transcript);
319		Ok(VRFSignature {
320			output: inout.to_output(),
321			proof,
322		})
323	}
324}
325
326impl Into<SyncCryptoStorePtr> for KeyStore {
327	fn into(self) -> SyncCryptoStorePtr {
328		Arc::new(self)
329	}
330}
331
332impl Into<Arc<dyn CryptoStore>> for KeyStore {
333	fn into(self) -> Arc<dyn CryptoStore> {
334		Arc::new(self)
335	}
336}
337
338#[cfg(test)]
339mod tests {
340	use super::*;
341	use tet_core::{sr25519, testing::{ED25519, SR25519}};
342	use crate::{SyncCryptoStore, vrf::VRFTranscriptValue};
343
344	#[test]
345	fn store_key_and_extract() {
346		let store = KeyStore::new();
347
348		let public = SyncCryptoStore::ed25519_generate_new(&store, ED25519, None)
349			.expect("Generates key");
350
351		let public_keys = SyncCryptoStore::keys(&store, ED25519).unwrap();
352
353		assert!(public_keys.contains(&public.into()));
354	}
355
356	#[test]
357	fn store_unknown_and_extract_it() {
358		let store = KeyStore::new();
359
360		let secret_uri = "//Alice";
361		let key_pair = sr25519::Pair::from_string(secret_uri, None).expect("Generates key pair");
362
363		SyncCryptoStore::insert_unknown(
364			&store,
365			SR25519,
366			secret_uri,
367			key_pair.public().as_ref(),
368		).expect("Inserts unknown key");
369
370		let public_keys = SyncCryptoStore::keys(&store, SR25519).unwrap();
371
372		assert!(public_keys.contains(&key_pair.public().into()));
373	}
374
375	#[test]
376	fn vrf_sign() {
377		let store = KeyStore::new();
378
379		let secret_uri = "//Alice";
380		let key_pair = sr25519::Pair::from_string(secret_uri, None).expect("Generates key pair");
381
382		let transcript_data = VRFTranscriptData {
383			label: b"Test",
384			items: vec![
385				("one", VRFTranscriptValue::U64(1)),
386				("two", VRFTranscriptValue::U64(2)),
387				("three", VRFTranscriptValue::Bytes("test".as_bytes().to_vec())),
388			]
389		};
390
391		let result = SyncCryptoStore::sr25519_vrf_sign(
392			&store,
393			SR25519,
394			&key_pair.public(),
395			transcript_data.clone(),
396		);
397		assert!(result.is_err());
398
399		SyncCryptoStore::insert_unknown(
400			&store,
401			SR25519,
402			secret_uri,
403			key_pair.public().as_ref(),
404		).expect("Inserts unknown key");
405
406		let result = SyncCryptoStore::sr25519_vrf_sign(
407			&store,
408			SR25519,
409			&key_pair.public(),
410			transcript_data,
411		);
412
413		assert!(result.is_ok());
414	}
415}