identity_storage/key_storage/
bls.rs1use anyhow::Context;
5use identity_verification::jose::jwk::Jwk;
6use identity_verification::jose::jwu;
7use identity_verification::jwk::BlsCurve;
8use identity_verification::jwk::JwkParamsEc;
9use jsonprooftoken::jpa::algs::ProofAlgorithm;
10use zkryptium::bbsplus::ciphersuites::BbsCiphersuite;
11use zkryptium::bbsplus::ciphersuites::Bls12381Sha256;
12use zkryptium::bbsplus::ciphersuites::Bls12381Shake256;
13use zkryptium::bbsplus::keys::BBSplusPublicKey;
14use zkryptium::bbsplus::keys::BBSplusSecretKey;
15use zkryptium::keys::pair::KeyPair;
16use zkryptium::schemes::algorithms::BBSplus;
17use zkryptium::schemes::generics::Signature;
18
19use crate::key_storage::KeyStorageError;
20use crate::key_storage::KeyStorageErrorKind;
21use crate::key_storage::KeyStorageResult;
22use crate::ProofUpdateCtx;
23
24fn random_bbs_keypair<S>() -> Result<(BBSplusSecretKey, BBSplusPublicKey), zkryptium::errors::Error>
25where
26 S: BbsCiphersuite,
27{
28 KeyPair::<BBSplus<S>>::random().map(KeyPair::into_parts)
29}
30
31pub fn generate_bbs_keypair(alg: ProofAlgorithm) -> KeyStorageResult<(BBSplusSecretKey, BBSplusPublicKey)> {
33 match alg {
34 ProofAlgorithm::BLS12381_SHA256 => random_bbs_keypair::<Bls12381Sha256>(),
35 ProofAlgorithm::BLS12381_SHAKE256 => random_bbs_keypair::<Bls12381Shake256>(),
36 _ => return Err(KeyStorageErrorKind::UnsupportedProofAlgorithm.into()),
37 }
38 .map_err(|err| KeyStorageError::new(KeyStorageErrorKind::Unspecified).with_source(err))
39}
40
41pub fn encode_bls_jwk(
43 private_key: &BBSplusSecretKey,
44 public_key: &BBSplusPublicKey,
45 alg: ProofAlgorithm,
46) -> (Jwk, Jwk) {
47 let (x, y) = public_key.to_coordinates();
48 let x = jwu::encode_b64(x);
49 let y = jwu::encode_b64(y);
50
51 let d = jwu::encode_b64(private_key.to_bytes());
52 let params = JwkParamsEc {
53 x,
54 y,
55 d: Some(d),
56 crv: BlsCurve::BLS12381G2.name().to_owned(),
57 };
58
59 let mut jwk = Jwk::from_params(params);
60
61 jwk.set_alg(alg.to_string());
62 jwk.set_kid(jwk.thumbprint_sha256_b64());
63 let public_jwk = jwk.to_public().expect("kty != oct");
64
65 (jwk, public_jwk)
66}
67
68pub fn expand_bls_jwk(jwk: &Jwk) -> KeyStorageResult<(Option<BBSplusSecretKey>, BBSplusPublicKey)> {
70 let params = jwk
72 .try_ec_params()
73 .ok()
74 .filter(|params| {
75 params
76 .try_bls_curve()
77 .map(|curve| curve == BlsCurve::BLS12381G2)
78 .unwrap_or(false)
79 })
80 .context(format!("not a {} curve key", BlsCurve::BLS12381G2))
81 .map_err(|e| KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType).with_source(e))?;
82
83 let sk = params
84 .d
85 .as_deref()
86 .map(|d| {
87 jwu::decode_b64(d)
88 .context("`d` parameter is not base64 encoded")
89 .and_then(|bytes| BBSplusSecretKey::from_bytes(&bytes).context("invalid key size"))
90 })
91 .transpose()
92 .map_err(|e| KeyStorageError::new(KeyStorageErrorKind::Unspecified).with_source(e))?;
93
94 let x = jwu::decode_b64(¶ms.x)
95 .context("`x` parameter is not base64 encoded")
96 .and_then(|bytes| bytes.try_into().ok().context("invalid coordinate size"))
97 .map_err(|e| KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType).with_source(e))?;
98 let y = jwu::decode_b64(¶ms.y)
99 .context("`y` parameter is not base64 encoded")
100 .and_then(|bytes| bytes.try_into().ok().context("invalid coordinate size"))
101 .map_err(|e| KeyStorageError::new(KeyStorageErrorKind::UnsupportedKeyType).with_source(e))?;
102
103 let pk = BBSplusPublicKey::from_coordinates(&x, &y).map_err(|e| {
104 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
105 .with_source(e)
106 .with_custom_message("invalid BBS+ public key".to_owned())
107 })?;
108
109 Ok((sk, pk))
110}
111
112fn _sign_bbs<S>(
113 data: &[Vec<u8>],
114 sk: &BBSplusSecretKey,
115 pk: &BBSplusPublicKey,
116 header: &[u8],
117) -> Result<Vec<u8>, zkryptium::errors::Error>
118where
119 S: BbsCiphersuite,
120{
121 Signature::<BBSplus<S>>::sign(Some(data), sk, pk, Some(header)).map(|s| s.to_bytes().to_vec())
122}
123
124pub fn sign_bbs(
126 alg: ProofAlgorithm,
127 data: &[Vec<u8>],
128 sk: &BBSplusSecretKey,
129 pk: &BBSplusPublicKey,
130 header: &[u8],
131) -> KeyStorageResult<Vec<u8>> {
132 match alg {
133 ProofAlgorithm::BLS12381_SHA256 => _sign_bbs::<Bls12381Sha256>(data, sk, pk, header),
134 ProofAlgorithm::BLS12381_SHAKE256 => _sign_bbs::<Bls12381Shake256>(data, sk, pk, header),
135 _ => return Err(KeyStorageErrorKind::UnsupportedProofAlgorithm.into()),
136 }
137 .map_err(|e| {
138 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
139 .with_source(e)
140 .with_custom_message("signature failed".to_owned())
141 })
142}
143
144fn _update_bbs_signature<S>(
145 sig: &[u8; 80],
146 sk: &BBSplusSecretKey,
147 update_ctx: &ProofUpdateCtx,
148) -> Result<[u8; 80], zkryptium::errors::Error>
149where
150 S: BbsCiphersuite,
151{
152 let sig = Signature::<BBSplus<S>>::from_bytes(sig)?;
153 let ProofUpdateCtx {
154 old_start_validity_timeframe,
155 new_start_validity_timeframe,
156 old_end_validity_timeframe,
157 new_end_validity_timeframe,
158 index_start_validity_timeframe,
159 index_end_validity_timeframe,
160 number_of_signed_messages,
161 } = update_ctx;
162 let half_updated = sig.update_signature(
163 sk,
164 old_start_validity_timeframe,
165 new_start_validity_timeframe,
166 *index_start_validity_timeframe,
167 *number_of_signed_messages,
168 )?;
169 half_updated
170 .update_signature(
171 sk,
172 old_end_validity_timeframe,
173 new_end_validity_timeframe,
174 *index_end_validity_timeframe,
175 *number_of_signed_messages,
176 )
177 .map(|sig| sig.to_bytes())
178}
179
180pub fn update_bbs_signature(
182 alg: ProofAlgorithm,
183 sig: &[u8],
184 sk: &BBSplusSecretKey,
185 update_ctx: &ProofUpdateCtx,
186) -> KeyStorageResult<Vec<u8>> {
187 let exact_size_signature = sig.try_into().map_err(|_| {
188 KeyStorageError::new(KeyStorageErrorKind::Unspecified).with_custom_message("invalid signature size".to_owned())
189 })?;
190 match alg {
191 ProofAlgorithm::BLS12381_SHA256 => _update_bbs_signature::<Bls12381Sha256>(exact_size_signature, sk, update_ctx),
192 ProofAlgorithm::BLS12381_SHAKE256 => {
193 _update_bbs_signature::<Bls12381Shake256>(exact_size_signature, sk, update_ctx)
194 }
195 _ => return Err(KeyStorageErrorKind::UnsupportedProofAlgorithm.into()),
196 }
197 .map(Vec::from)
198 .map_err(|e| {
199 KeyStorageError::new(KeyStorageErrorKind::Unspecified)
200 .with_custom_message("signature failed")
201 .with_source(e)
202 })
203}