1use core::fmt::Debug;
5use std::collections::HashMap;
6use std::fmt::Display;
7use std::str::FromStr;
8
9use async_trait::async_trait;
10use fastcrypto::ed25519::Ed25519KeyPair;
11use fastcrypto::ed25519::Ed25519Signature;
12use fastcrypto::traits::KeyPair as _;
13use fastcrypto::traits::Signer;
14use identity_verification::jose::jwk::EdCurve;
15use identity_verification::jose::jwk::Jwk;
16use identity_verification::jose::jwk::JwkType;
17use identity_verification::jose::jws::JwsAlgorithm;
18use identity_verification::jwk::BlsCurve;
19use identity_verification::jwk::FromJwk as _;
20use identity_verification::jwk::ToJwk as _;
21use rand::distributions::DistString;
22use shared::Shared;
23use tokio::sync::RwLockReadGuard;
24use tokio::sync::RwLockWriteGuard;
25
26use super::jwk_gen_output::JwkGenOutput;
27use super::KeyId;
28use super::KeyStorageError;
29use super::KeyStorageErrorKind;
30use super::KeyStorageResult;
31use super::KeyType;
32use crate::key_storage::JwkStorage;
33
34type JwkKeyStore = HashMap<KeyId, Jwk>;
36
37#[derive(Debug)]
39pub struct JwkMemStore {
40 jwk_store: Shared<JwkKeyStore>,
41}
42
43impl JwkMemStore {
44 pub fn new() -> Self {
46 Self {
47 jwk_store: Shared::new(HashMap::new()),
48 }
49 }
50
51 pub async fn count(&self) -> usize {
53 self.jwk_store.read().await.keys().count()
54 }
55
56 pub async fn get_public_key(&self, key_id: &KeyId) -> KeyStorageResult<Jwk> {
58 self
59 .jwk_store
60 .read()
61 .await
62 .get(key_id)
63 .cloned()
64 .map(|jwk| jwk.to_public().unwrap_or(jwk))
65 .ok_or_else(|| KeyStorageError::new(KeyStorageErrorKind::KeyNotFound))
66 }
67}
68
69#[cfg_attr(not(feature = "send-sync-storage"), async_trait(?Send))]
71#[cfg_attr(feature = "send-sync-storage", async_trait)]
72impl JwkStorage for JwkMemStore {
73 async fn generate(&self, key_type: KeyType, alg: JwsAlgorithm) -> KeyStorageResult<JwkGenOutput> {
74 let key_type: MemStoreKeyType = MemStoreKeyType::try_from(&key_type)?;
75
76 check_key_alg_compatibility(key_type, &alg)?;
77
78 let keypair = match key_type {
79 MemStoreKeyType::Ed25519 => Ed25519KeyPair::generate(&mut rand::thread_rng()),
80 other => {
81 return Err(
82 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)
83 .with_custom_message(format!("{other} is not supported")),
84 );
85 }
86 };
87
88 let kid: KeyId = random_key_id();
89
90 let mut jwk: Jwk = keypair.to_jwk().map_err(|err| {
91 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
92 .with_custom_message("could not convert `Ed25519KeyPair` to `Jwk`")
93 .with_source(err)
94 })?;
95 jwk.set_alg(alg.name());
96 jwk.set_kid(jwk.thumbprint_sha256_b64());
97 let public_jwk: Jwk = jwk.to_public().expect("should only panic if kty == oct");
98
99 let mut jwk_store: RwLockWriteGuard<'_, JwkKeyStore> = self.jwk_store.write().await;
100 jwk_store.insert(kid.clone(), jwk);
101
102 Ok(JwkGenOutput::new(kid, public_jwk))
103 }
104
105 async fn insert(&self, jwk: Jwk) -> KeyStorageResult<KeyId> {
106 let key_type = MemStoreKeyType::try_from(&jwk)?;
107
108 if !jwk.is_private() {
109 return Err(
110 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
111 .with_custom_message("expected a Jwk with all private key components set"),
112 );
113 }
114
115 match jwk.alg() {
116 Some(alg) => {
117 let alg: JwsAlgorithm = JwsAlgorithm::from_str(alg)
118 .map_err(|err| KeyStorageError::new(KeyStorageErrorKind::UnsupportedSignatureAlgorithm).with_source(err))?;
119 check_key_alg_compatibility(key_type, &alg)?;
120 }
121 None => {
122 return Err(
123 KeyStorageError::new(KeyStorageErrorKind::UnsupportedSignatureAlgorithm)
124 .with_custom_message("expected a Jwk with an `alg` parameter"),
125 );
126 }
127 }
128
129 if jwk.alg().is_none() {
130 return Err(
131 KeyStorageError::new(KeyStorageErrorKind::UnsupportedSignatureAlgorithm)
132 .with_custom_message("expected a Jwk with an `alg` parameter"),
133 );
134 }
135
136 let key_id: KeyId = random_key_id();
137
138 let mut jwk_store: RwLockWriteGuard<'_, JwkKeyStore> = self.jwk_store.write().await;
139
140 jwk_store.insert(key_id.clone(), jwk);
141
142 Ok(key_id)
143 }
144
145 async fn sign(&self, key_id: &KeyId, data: &[u8], public_key: &Jwk) -> KeyStorageResult<Vec<u8>> {
146 let jwk_store: RwLockReadGuard<'_, JwkKeyStore> = self.jwk_store.read().await;
147
148 let alg = public_key
150 .alg()
151 .ok_or(KeyStorageErrorKind::UnsupportedSignatureAlgorithm)
152 .and_then(|alg_str| {
153 JwsAlgorithm::from_str(alg_str).map_err(|_| KeyStorageErrorKind::UnsupportedSignatureAlgorithm)
154 })?;
155
156 match alg {
158 JwsAlgorithm::EdDSA => {
159 let okp_params = public_key.try_okp_params().map_err(|err| {
160 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
161 .with_custom_message(format!("expected a Jwk with Okp params in order to sign with {alg}"))
162 .with_source(err)
163 })?;
164 if okp_params.crv != EdCurve::Ed25519.name() {
165 return Err(
166 KeyStorageError::new(KeyStorageErrorKind::Unspecified).with_custom_message(format!(
167 "expected Jwk with Okp {} crv in order to sign with {alg}",
168 EdCurve::Ed25519
169 )),
170 );
171 }
172 }
173 other => {
174 return Err(
175 KeyStorageError::new(KeyStorageErrorKind::UnsupportedSignatureAlgorithm)
176 .with_custom_message(format!("{other} is not supported")),
177 );
178 }
179 };
180
181 let jwk: &Jwk = jwk_store
183 .get(key_id)
184 .ok_or_else(|| KeyStorageError::new(KeyStorageErrorKind::KeyNotFound))?;
185 let secret_key = Ed25519KeyPair::from_jwk(jwk).map_err(|err| {
186 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
187 .with_custom_message("could not convert `Jwk` to `Ed25519KeyPair`")
188 .with_source(err)
189 })?;
190 Ok(Signer::<Ed25519Signature>::sign(&secret_key, data).as_ref().to_vec())
191 }
192
193 async fn delete(&self, key_id: &KeyId) -> KeyStorageResult<()> {
194 let mut jwk_store: RwLockWriteGuard<'_, JwkKeyStore> = self.jwk_store.write().await;
195
196 jwk_store
197 .remove(key_id)
198 .map(|_| ())
199 .ok_or_else(|| KeyStorageError::new(KeyStorageErrorKind::KeyNotFound))
200 }
201
202 async fn exists(&self, key_id: &KeyId) -> KeyStorageResult<bool> {
203 let jwk_store: RwLockReadGuard<'_, JwkKeyStore> = self.jwk_store.read().await;
204 Ok(jwk_store.contains_key(key_id))
205 }
206}
207
208#[derive(Debug, Copy, Clone)]
209enum MemStoreKeyType {
210 Ed25519,
211 BLS12381G2,
212}
213
214impl JwkMemStore {
215 const ED25519_KEY_TYPE_STR: &'static str = "Ed25519";
216 pub const ED25519_KEY_TYPE: KeyType = KeyType::from_static_str(Self::ED25519_KEY_TYPE_STR);
218
219 const BLS12381G2_KEY_TYPE_STR: &'static str = "BLS12381G2";
220 pub const BLS12381G2_KEY_TYPE: KeyType = KeyType::from_static_str(Self::BLS12381G2_KEY_TYPE_STR);
222
223 const PQ_KEY_TYPE_STR: &'static str = "AKP";
224 pub const PQ_KEY_TYPE: KeyType = KeyType::from_static_str(Self::PQ_KEY_TYPE_STR);
226}
227
228impl MemStoreKeyType {
229 const fn name(&self) -> &'static str {
230 match self {
231 MemStoreKeyType::Ed25519 => JwkMemStore::ED25519_KEY_TYPE_STR,
232 MemStoreKeyType::BLS12381G2 => JwkMemStore::BLS12381G2_KEY_TYPE_STR,
233 }
234 }
235}
236
237impl Display for MemStoreKeyType {
238 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
239 f.write_str(self.name())
240 }
241}
242
243impl TryFrom<&KeyType> for MemStoreKeyType {
244 type Error = KeyStorageError;
245
246 fn try_from(value: &KeyType) -> Result<Self, Self::Error> {
247 match value.as_str() {
248 JwkMemStore::ED25519_KEY_TYPE_STR => Ok(MemStoreKeyType::Ed25519),
249 JwkMemStore::BLS12381G2_KEY_TYPE_STR => Ok(MemStoreKeyType::BLS12381G2),
250 _ => Err(KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)),
251 }
252 }
253}
254
255impl TryFrom<&Jwk> for MemStoreKeyType {
256 type Error = KeyStorageError;
257
258 fn try_from(jwk: &Jwk) -> Result<Self, Self::Error> {
259 match jwk.kty() {
260 JwkType::Okp => {
261 let okp_params = jwk.try_okp_params().map_err(|err| {
262 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)
263 .with_custom_message("expected Okp parameters for a JWK with `kty` Okp")
264 .with_source(err)
265 })?;
266 match okp_params.try_ed_curve().map_err(|err| {
267 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)
268 .with_custom_message("only Ed curves are supported for signing")
269 .with_source(err)
270 })? {
271 EdCurve::Ed25519 => Ok(MemStoreKeyType::Ed25519),
272 curve => Err(
273 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)
274 .with_custom_message(format!("{curve} not supported")),
275 ),
276 }
277 }
278 JwkType::Ec => {
279 let ec_params = jwk.try_ec_params().map_err(|err| {
280 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)
281 .with_custom_message("expected EC parameters for a JWK with `kty` Ec")
282 .with_source(err)
283 })?;
284 match ec_params.try_bls_curve().map_err(|err| {
285 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)
286 .with_custom_message("only Ed curves are supported for signing")
287 .with_source(err)
288 })? {
289 BlsCurve::BLS12381G2 => Ok(MemStoreKeyType::BLS12381G2),
290 curve => Err(
291 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)
292 .with_custom_message(format!("{curve} not supported")),
293 ),
294 }
295 }
296 other => Err(
297 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)
298 .with_custom_message(format!("Jwk `kty` {other} not supported")),
299 ),
300 }
301 }
302}
303
304impl Default for JwkMemStore {
305 fn default() -> Self {
306 Self::new()
307 }
308}
309
310fn random_key_id() -> KeyId {
312 KeyId::new(rand::distributions::Alphanumeric.sample_string(&mut rand::thread_rng(), 32))
313}
314
315fn check_key_alg_compatibility(key_type: MemStoreKeyType, alg: &JwsAlgorithm) -> KeyStorageResult<()> {
317 match (key_type, alg) {
318 (MemStoreKeyType::Ed25519, JwsAlgorithm::EdDSA) => Ok(()),
319 (key_type, alg) => Err(
320 KeyStorageError::new(crate::key_storage::KeyStorageErrorKind::KeyAlgorithmMismatch)
321 .with_custom_message(format!("`cannot use key type `{key_type}` with algorithm `{alg}`")),
322 ),
323 }
324}
325
326#[cfg(feature = "pqc-liboqs")]
327mod pqc_liboqs {
328 use async_trait::async_trait;
329 use identity_verification::jose::jwk::Jwk;
330 use identity_verification::jose::jwk::JwkType;
331 use identity_verification::jose::jws::JwsAlgorithm;
332 use identity_verification::jwk::JwkParams;
333 use identity_verification::jwk::PostQuantumJwk;
334 use identity_verification::jwu;
335 use oqs::sig::Algorithm;
336 use oqs::sig::Sig;
337 use std::str::FromStr;
338 use tokio::sync::RwLockReadGuard;
339 use tokio::sync::RwLockWriteGuard;
340
341 use super::random_key_id;
342 use super::JwkKeyStore;
343 use super::JwkMemStore;
344 use super::KeyId;
345 use super::KeyStorageError;
346 use super::KeyStorageErrorKind;
347 use super::KeyStorageResult;
348 use super::KeyType;
349 use crate::key_storage::jwk_storage_pqc::JwkStoragePQ;
350 use crate::JwkGenOutput;
351
352 fn check_pq_alg_compatibility(alg: &JwsAlgorithm) -> KeyStorageResult<Algorithm> {
353 match alg {
354 JwsAlgorithm::ML_DSA_44 => Ok(Algorithm::MlDsa44),
355 JwsAlgorithm::ML_DSA_65 => Ok(Algorithm::MlDsa65),
356 JwsAlgorithm::ML_DSA_87 => Ok(Algorithm::MlDsa87),
357 JwsAlgorithm::SLH_DSA_SHA2_128s => Ok(Algorithm::SphincsSha2128sSimple),
358 JwsAlgorithm::SLH_DSA_SHAKE_128s => Ok(Algorithm::SphincsShake128sSimple),
359 JwsAlgorithm::SLH_DSA_SHA2_128f => Ok(Algorithm::SphincsSha2128fSimple),
360
361 JwsAlgorithm::SLH_DSA_SHAKE_128f => Ok(Algorithm::SphincsShake128fSimple),
362 JwsAlgorithm::SLH_DSA_SHA2_192s => Ok(Algorithm::SphincsSha2192sSimple),
363 JwsAlgorithm::SLH_DSA_SHAKE_192s => Ok(Algorithm::SphincsShake192sSimple),
364 JwsAlgorithm::SLH_DSA_SHA2_192f => Ok(Algorithm::SphincsSha2192fSimple),
365 JwsAlgorithm::SLH_DSA_SHAKE_192f => Ok(Algorithm::SphincsShake192fSimple),
366 JwsAlgorithm::SLH_DSA_SHA2_256s => Ok(Algorithm::SphincsSha2256sSimple),
367 JwsAlgorithm::SLH_DSA_SHAKE_256s => Ok(Algorithm::SphincsShake256sSimple),
368 JwsAlgorithm::SLH_DSA_SHA2_256f => Ok(Algorithm::SphincsSha2256fSimple),
369 JwsAlgorithm::SLH_DSA_SHAKE_256f => Ok(Algorithm::SphincsShake256fSimple),
370
371 JwsAlgorithm::FALCON512 => Ok(Algorithm::Falcon512),
372 JwsAlgorithm::FALCON1024 => Ok(Algorithm::Falcon1024),
373 other => Err(
374 KeyStorageError::new(KeyStorageErrorKind::UnsupportedSignatureAlgorithm)
375 .with_custom_message(format!("{other} is not supported")),
376 ),
377 }
378 }
379
380 #[cfg_attr(not(feature = "send-sync-storage"), async_trait(?Send))]
382 #[cfg_attr(feature = "send-sync-storage", async_trait)]
383 impl JwkStoragePQ for JwkMemStore {
384 async fn generate_pq_key(&self, key_type: KeyType, alg: JwsAlgorithm) -> KeyStorageResult<JwkGenOutput> {
385 if key_type != JwkMemStore::PQ_KEY_TYPE {
386 return Err(
387 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)
388 .with_custom_message(format!("unsupported key type {key_type}")),
389 );
390 }
391
392 let oqs_alg = check_pq_alg_compatibility(&alg)?;
393 oqs::init();
394
395 let scheme = Sig::new(oqs_alg).map_err(|err| {
396 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
397 .with_custom_message("signature scheme init failed".to_string())
398 .with_source(err)
399 })?;
400 let (pk, sk) = scheme.keypair().map_err(|err| {
401 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
402 .with_custom_message("keypair generation failed!".to_string())
403 .with_source(err)
404 })?;
405
406 let kid: KeyId = random_key_id();
407
408 let public = jwu::encode_b64(pk.into_vec());
409 let private = jwu::encode_b64(sk.into_vec());
410
411 let mut jwk_params = match alg {
412 JwsAlgorithm::ML_DSA_44 => JwkParams::new(JwkType::Akp),
413 JwsAlgorithm::ML_DSA_65 => JwkParams::new(JwkType::Akp),
414 JwsAlgorithm::ML_DSA_87 => JwkParams::new(JwkType::Akp),
415 JwsAlgorithm::SLH_DSA_SHA2_128s => JwkParams::new(JwkType::Akp),
416 JwsAlgorithm::SLH_DSA_SHAKE_128s => JwkParams::new(JwkType::Akp),
417 JwsAlgorithm::SLH_DSA_SHA2_128f => JwkParams::new(JwkType::Akp),
418 JwsAlgorithm::SLH_DSA_SHAKE_128f => JwkParams::new(JwkType::Akp),
419 JwsAlgorithm::SLH_DSA_SHA2_192s => JwkParams::new(JwkType::Akp),
420 JwsAlgorithm::SLH_DSA_SHAKE_192s => JwkParams::new(JwkType::Akp),
421 JwsAlgorithm::SLH_DSA_SHA2_192f => JwkParams::new(JwkType::Akp),
422 JwsAlgorithm::SLH_DSA_SHAKE_192f => JwkParams::new(JwkType::Akp),
423 JwsAlgorithm::SLH_DSA_SHA2_256s => JwkParams::new(JwkType::Akp),
424 JwsAlgorithm::SLH_DSA_SHAKE_256s => JwkParams::new(JwkType::Akp),
425 JwsAlgorithm::SLH_DSA_SHA2_256f => JwkParams::new(JwkType::Akp),
426 JwsAlgorithm::SLH_DSA_SHAKE_256f => JwkParams::new(JwkType::Akp),
427 JwsAlgorithm::FALCON512 => JwkParams::new(JwkType::Akp),
428 JwsAlgorithm::FALCON1024 => JwkParams::new(JwkType::Akp),
429 other => {
430 return Err(
431 KeyStorageError::new(KeyStorageErrorKind::UnsupportedSignatureAlgorithm)
432 .with_custom_message(format!("{other} is not supported")),
433 );
434 }
435 };
436
437 match jwk_params {
438 JwkParams::Akp(ref mut params) => {
439 params.public = public;
440 params.private = Some(private);
441 }
442 _ => {
443 return Err(
444 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType).with_custom_message("Should NOT happen!"),
445 )
446 }
447 }
448
449 let mut jwk = Jwk::from_params(jwk_params);
450
451 jwk.set_alg(alg.name());
452 jwk.set_kid(jwk.thumbprint_sha256_b64());
453 let public_jwk: Jwk = jwk.to_public().expect("should only panic if kty == oct");
454
455 let mut jwk_store: RwLockWriteGuard<'_, JwkKeyStore> = self.jwk_store.write().await;
456 jwk_store.insert(kid.clone(), jwk);
457
458 Ok(JwkGenOutput::new(kid, public_jwk))
459 }
460
461 async fn pq_sign(
462 &self,
463 key_id: &KeyId,
464 data: &[u8],
465 public_key: &PostQuantumJwk,
466 ctx: Option<&[u8]>,
467 ) -> KeyStorageResult<Vec<u8>> {
468 let jwk_store: RwLockReadGuard<'_, JwkKeyStore> = self.jwk_store.read().await;
469
470 let alg = public_key
472 .alg()
473 .ok_or(KeyStorageErrorKind::UnsupportedSignatureAlgorithm)
474 .and_then(|alg_str| {
475 JwsAlgorithm::from_str(alg_str).map_err(|_| KeyStorageErrorKind::UnsupportedSignatureAlgorithm)
476 })?;
477
478 let oqs_alg = check_pq_alg_compatibility(&alg)?;
479
480 match alg {
482 JwsAlgorithm::ML_DSA_44
483 | JwsAlgorithm::ML_DSA_65
484 | JwsAlgorithm::ML_DSA_87
485 | JwsAlgorithm::SLH_DSA_SHA2_128s
486 | JwsAlgorithm::SLH_DSA_SHAKE_128s
487 | JwsAlgorithm::SLH_DSA_SHA2_128f
488 | JwsAlgorithm::SLH_DSA_SHAKE_128f
489 | JwsAlgorithm::SLH_DSA_SHA2_192s
490 | JwsAlgorithm::SLH_DSA_SHAKE_192s
491 | JwsAlgorithm::SLH_DSA_SHA2_192f
492 | JwsAlgorithm::SLH_DSA_SHAKE_192f
493 | JwsAlgorithm::SLH_DSA_SHA2_256s
494 | JwsAlgorithm::SLH_DSA_SHAKE_256s
495 | JwsAlgorithm::SLH_DSA_SHA2_256f
496 | JwsAlgorithm::SLH_DSA_SHAKE_256f
497 | JwsAlgorithm::FALCON512
498 | JwsAlgorithm::FALCON1024 => public_key.try_akp_params().map_err(|err| {
499 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
500 .with_custom_message(format!("expected a Jwk with AKP params in order to sign with {alg}"))
501 .with_source(err)
502 })?,
503 other => {
504 return Err(
505 KeyStorageError::new(KeyStorageErrorKind::UnsupportedSignatureAlgorithm)
506 .with_custom_message(format!("{other} is not supported")),
507 );
508 }
509 };
510
511 let jwk: &Jwk = jwk_store
513 .get(key_id)
514 .ok_or_else(|| KeyStorageError::new(KeyStorageErrorKind::KeyNotFound))?;
515
516 let params = jwk.try_akp_params().unwrap();
517
518 let sk_bytes = params
519 .private
520 .as_deref()
521 .map(jwu::decode_b64)
522 .ok_or_else(|| {
523 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
524 .with_custom_message("expected Jwk `private` param to be present")
525 })?
526 .map_err(|err| {
527 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
528 .with_custom_message("unable to decode `private` param")
529 .with_source(err)
530 })?;
531 oqs::init();
532
533 let scheme = Sig::new(oqs_alg).map_err(|err| {
534 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
535 .with_custom_message("signature scheme init failed".to_string())
536 .with_source(err)
537 })?;
538
539 let secret_key = scheme.secret_key_from_bytes(&sk_bytes).ok_or(
540 KeyStorageError::new(KeyStorageErrorKind::Unspecified).with_custom_message("invalid private key".to_string()),
541 )?;
542
543 let signature: oqs::sig::Signature;
544
545 if let Some(ctx) = ctx {
546 if !scheme.has_ctx_str_support() {
547 return Err(
548 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
549 .with_custom_message("signature with ctx is not supported with this algorithm".to_string()),
550 );
551 }
552 signature = scheme.sign_with_ctx_str(data, ctx, secret_key).map_err(|err| {
553 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
554 .with_custom_message("signature computation failed".to_string())
555 .with_source(err)
556 })?;
557 } else {
558 signature = scheme.sign(data, secret_key).map_err(|err| {
559 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
560 .with_custom_message("signature computation failed".to_string())
561 .with_source(err)
562 })?;
563 }
564
565 Ok(signature.into_vec())
566 }
567 }
568}
569
570#[cfg(feature = "jpt-bbs-plus")]
571mod bbs_plus_impl {
572 use std::str::FromStr as _;
573
574 use crate::key_storage::bls::encode_bls_jwk;
575 use crate::key_storage::bls::expand_bls_jwk;
576 use crate::key_storage::bls::generate_bbs_keypair;
577 use crate::key_storage::bls::sign_bbs;
578 use crate::key_storage::bls::update_bbs_signature;
579 use crate::JwkGenOutput;
580 use crate::JwkMemStore;
581 use crate::JwkStorageBbsPlusExt;
582 use crate::KeyId;
583 use crate::KeyStorageError;
584 use crate::KeyStorageErrorKind;
585 use crate::KeyStorageResult;
586 use crate::KeyType;
587 use crate::ProofUpdateCtx;
588 use async_trait::async_trait;
589 use identity_verification::jwk::BlsCurve;
590 use identity_verification::jwk::Jwk;
591 use jsonprooftoken::jpa::algs::ProofAlgorithm;
592
593 use super::random_key_id;
594
595 #[cfg_attr(not(feature = "send-sync-storage"), async_trait(?Send))]
597 #[cfg_attr(feature = "send-sync-storage", async_trait)]
598 impl JwkStorageBbsPlusExt for JwkMemStore {
599 async fn generate_bbs(&self, key_type: KeyType, alg: ProofAlgorithm) -> KeyStorageResult<JwkGenOutput> {
600 if key_type != JwkMemStore::BLS12381G2_KEY_TYPE {
601 return Err(
602 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)
603 .with_custom_message(format!("unsupported key type {key_type}")),
604 );
605 }
606
607 let (private_key, public_key) = generate_bbs_keypair(alg)?;
608 let (jwk, public_jwk) = encode_bls_jwk(&private_key, &public_key, alg);
609
610 let kid: KeyId = random_key_id();
611 let mut jwk_store = self.jwk_store.write().await;
612 jwk_store.insert(kid.clone(), jwk);
613
614 Ok(JwkGenOutput::new(kid, public_jwk))
615 }
616
617 async fn sign_bbs(
618 &self,
619 key_id: &KeyId,
620 data: &[Vec<u8>],
621 header: &[u8],
622 public_key: &Jwk,
623 ) -> KeyStorageResult<Vec<u8>> {
624 let jwk_store = self.jwk_store.read().await;
625
626 let alg = public_key
628 .alg()
629 .and_then(|alg_str| ProofAlgorithm::from_str(alg_str).ok())
630 .ok_or(KeyStorageErrorKind::UnsupportedProofAlgorithm)?;
631
632 if !public_key
634 .try_ec_params()
635 .map(|ec| ec.crv == BlsCurve::BLS12381G2.to_string())
636 .unwrap_or(false)
637 {
638 return Err(
639 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)
640 .with_custom_message(format!("expected a key from the {} curve", BlsCurve::BLS12381G2)),
641 );
642 }
643
644 let jwk: &Jwk = jwk_store.get(key_id).ok_or(KeyStorageErrorKind::KeyNotFound)?;
646 let (sk, pk) = expand_bls_jwk(jwk)?;
647
648 sign_bbs(alg, data, &sk.expect("jwk is private"), &pk, header)
649 }
650
651 async fn update_signature(
652 &self,
653 key_id: &KeyId,
654 public_key: &Jwk,
655 signature: &[u8],
656 ctx: ProofUpdateCtx,
657 ) -> KeyStorageResult<Vec<u8>> {
658 let jwk_store = self.jwk_store.read().await;
659
660 let alg = public_key
662 .alg()
663 .ok_or(KeyStorageErrorKind::UnsupportedProofAlgorithm)
664 .and_then(|alg_str| {
665 ProofAlgorithm::from_str(alg_str).map_err(|_| KeyStorageErrorKind::UnsupportedProofAlgorithm)
666 })?;
667
668 if !public_key
670 .try_ec_params()
671 .map(|ec| ec.crv == BlsCurve::BLS12381G2.to_string())
672 .unwrap_or(false)
673 {
674 return Err(
675 KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType)
676 .with_custom_message(format!("expected a key from the {} curve", BlsCurve::BLS12381G2)),
677 );
678 }
679
680 let jwk = jwk_store.get(key_id).ok_or(KeyStorageErrorKind::KeyNotFound)?;
682 let sk = expand_bls_jwk(jwk)?.0.expect("jwk is private");
683
684 update_bbs_signature(alg, signature, &sk, &ctx)
686 }
687 }
688}
689pub(crate) mod shared {
690 use core::fmt::Debug;
691 use core::fmt::Formatter;
692 use tokio::sync::RwLock;
693 use tokio::sync::RwLockReadGuard;
694 use tokio::sync::RwLockWriteGuard;
695
696 #[derive(Default)]
697 pub(crate) struct Shared<T>(RwLock<T>);
698
699 impl<T> Shared<T> {
700 pub(crate) fn new(data: T) -> Self {
701 Self(RwLock::new(data))
702 }
703
704 pub(crate) async fn read(&self) -> RwLockReadGuard<'_, T> {
705 self.0.read().await
706 }
707
708 pub(crate) async fn write(&self) -> RwLockWriteGuard<'_, T> {
709 self.0.write().await
710 }
711 }
712
713 impl<T: Debug> Debug for Shared<T> {
714 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
715 Debug::fmt(&self.0, f)
716 }
717 }
718}
719
720#[cfg(test)]
721mod tests {
722 use crate::key_storage::tests::utils::generate_ed25519;
723 use fastcrypto::ed25519::Ed25519PublicKey;
724 use fastcrypto::traits::ToFromBytes as _;
725 use fastcrypto::traits::VerifyingKey as _;
726 use identity_verification::jose::jwk::EcCurve;
727 use identity_verification::jose::jwk::JwkParamsEc;
728 use identity_verification::jwk::FromJwk as _;
729
730 use super::*;
731
732 #[tokio::test]
733 async fn generate_and_sign() {
734 let test_msg: &[u8] = b"test";
735 let store: JwkMemStore = JwkMemStore::new();
736
737 let JwkGenOutput { key_id, jwk } = store
738 .generate(JwkMemStore::ED25519_KEY_TYPE, JwsAlgorithm::EdDSA)
739 .await
740 .unwrap();
741
742 let signature = store.sign(&key_id, test_msg, &jwk.to_public().unwrap()).await.unwrap();
743
744 let public_key = Ed25519PublicKey::from_jwk(&jwk).unwrap();
745 let signature = Ed25519Signature::from_bytes(&signature).unwrap();
746
747 assert!(public_key.verify(test_msg, &signature).is_ok());
748 assert!(store.exists(&key_id).await.unwrap());
749 store.delete(&key_id).await.unwrap();
750 }
751
752 #[tokio::test]
753 async fn insert() {
754 let store: JwkMemStore = JwkMemStore::new();
755
756 let key_pair = generate_ed25519();
757 let mut jwk: Jwk = key_pair.to_jwk().unwrap();
758
759 let err = store.insert(jwk.clone()).await.unwrap_err();
761 assert!(matches!(err.kind(), KeyStorageErrorKind::UnsupportedSignatureAlgorithm));
762
763 jwk.set_alg(JwsAlgorithm::EdDSA.name());
765 store.insert(jwk.clone()).await.unwrap();
766
767 let err = store.insert(jwk.to_public().unwrap()).await.unwrap_err();
769 assert!(matches!(err.kind(), KeyStorageErrorKind::Unspecified))
770 }
771
772 #[tokio::test]
773 async fn exists() {
774 let store: JwkMemStore = JwkMemStore::new();
775 assert!(!store.exists(&KeyId::new("non-existent-id")).await.unwrap());
776 }
777
778 #[tokio::test]
779 async fn incompatible_key_type() {
780 let store: JwkMemStore = JwkMemStore::new();
781
782 let mut ec_params = JwkParamsEc::new();
783 ec_params.crv = EcCurve::P256.name().to_string();
784 ec_params.x = String::new();
785 ec_params.y = String::new();
786 ec_params.d = Some(String::new());
787 let jwk_ec = Jwk::from_params(ec_params);
788
789 let err = store.insert(jwk_ec).await.unwrap_err();
790 assert!(matches!(err.kind(), KeyStorageErrorKind::UnsupportedKeyType));
791 }
792
793 #[tokio::test]
794 async fn incompatible_key_alg() {
795 let store: JwkMemStore = JwkMemStore::new();
796
797 let key_pair = generate_ed25519();
798 let mut jwk: Jwk = key_pair.to_jwk().unwrap();
799 jwk.set_alg(JwsAlgorithm::ES256.name());
800
801 let err = store.insert(jwk.clone()).await.unwrap_err();
803 assert!(matches!(err.kind(), KeyStorageErrorKind::KeyAlgorithmMismatch));
804 }
805}