1use crate::{CurveType, Error};
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3use std::fmt::{self, Display, Formatter};
4use std::str::FromStr;
5
6#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
7pub enum SigningAlgorithm {
8 Pairing,
9 Ecdsa,
10 Schnorr,
11}
12
13#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, Serialize, Deserialize)]
14pub enum KeyFormatPreference {
15 Uncompressed,
16 Compressed,
17}
18
19#[derive(Clone, Copy, Debug, Default, Hash, Eq, PartialEq)]
20pub enum SigningScheme {
21 #[default]
22 Bls12381,
23 EcdsaK256Sha256,
24 EcdsaP256Sha256,
25 EcdsaP384Sha384,
26 SchnorrEd25519Sha512,
27 SchnorrK256Sha256,
28 SchnorrP256Sha256,
29 SchnorrP384Sha384,
30 SchnorrRistretto25519Sha512,
31 SchnorrEd448Shake256,
32 SchnorrRedJubjubBlake2b512,
33 SchnorrK256Taproot,
34 SchnorrRedDecaf377Blake2b512,
35 SchnorrRedPallasBlake2b512,
36 SchnorrkelSubstrate,
37 Bls12381G1ProofOfPossession,
38}
39
40impl Display for SigningScheme {
41 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
42 match self {
43 Self::Bls12381 => write!(f, "Bls12381"),
44 Self::EcdsaK256Sha256 => write!(f, "EcdsaK256Sha256"),
45 Self::EcdsaP256Sha256 => write!(f, "EcdsaP256Sha256"),
46 Self::EcdsaP384Sha384 => write!(f, "EcdsaP384Sha384"),
47 Self::SchnorrEd25519Sha512 => write!(f, "SchnorrEd25519Sha512"),
48 Self::SchnorrK256Sha256 => write!(f, "SchnorrK256Sha256"),
49 Self::SchnorrP256Sha256 => write!(f, "SchnorrP256Sha256"),
50 Self::SchnorrP384Sha384 => write!(f, "SchnorrP384Sha384"),
51 Self::SchnorrRistretto25519Sha512 => write!(f, "SchnorrRistretto25519Sha512"),
52 Self::SchnorrEd448Shake256 => write!(f, "SchnorrEd448Shake256"),
53 Self::SchnorrRedJubjubBlake2b512 => write!(f, "SchnorrRedJubjubBlake2b512"),
54 Self::SchnorrRedPallasBlake2b512 => write!(f, "SchnorrRedPallasBlake2b512"),
55 Self::SchnorrK256Taproot => write!(f, "SchnorrK256Taproot"),
56 Self::SchnorrRedDecaf377Blake2b512 => write!(f, "SchnorrRedDecaf377Blake2b512"),
57 Self::SchnorrkelSubstrate => write!(f, "SchnorrkelSubstrate"),
58 Self::Bls12381G1ProofOfPossession => write!(f, "Bls12381G1ProofOfPossession"),
59 }
60 }
61}
62
63impl FromStr for SigningScheme {
64 type Err = Error;
65
66 fn from_str(s: &str) -> Result<Self, Self::Err> {
67 match s {
68 "Bls12381" => Ok(SigningScheme::Bls12381),
69 "EcdsaK256Sha256" => Ok(SigningScheme::EcdsaK256Sha256),
70 "EcdsaP256Sha256" => Ok(SigningScheme::EcdsaP256Sha256),
71 "EcdsaP384Sha384" => Ok(SigningScheme::EcdsaP384Sha384),
72 "SchnorrEd25519Sha512" => Ok(SigningScheme::SchnorrEd25519Sha512),
73 "SchnorrK256Sha256" => Ok(SigningScheme::SchnorrK256Sha256),
74 "SchnorrP256Sha256" => Ok(SigningScheme::SchnorrP256Sha256),
75 "SchnorrP384Sha384" => Ok(SigningScheme::SchnorrP384Sha384),
76 "SchnorrRistretto25519Sha512" => Ok(SigningScheme::SchnorrRistretto25519Sha512),
77 "SchnorrEd448Shake256" => Ok(SigningScheme::SchnorrEd448Shake256),
78 "SchnorrRedJubjubBlake2b512" => Ok(SigningScheme::SchnorrRedJubjubBlake2b512),
79 "SchnorrRedPallasBlake2b512" => Ok(SigningScheme::SchnorrRedPallasBlake2b512),
80 "SchnorrK256Taproot" => Ok(SigningScheme::SchnorrK256Taproot),
81 "SchnorrRedDecaf377Blake2b512" => Ok(SigningScheme::SchnorrRedDecaf377Blake2b512),
82 "SchnorrkelSubstrate" => Ok(SigningScheme::SchnorrkelSubstrate),
83 "Bls12381G1ProofOfPossession" => Ok(SigningScheme::Bls12381G1ProofOfPossession),
84 _ => Err(Error::Parse(format!("Invalid signing scheme: {}", s))),
85 }
86 }
87}
88
89impl From<SigningScheme> for u8 {
90 fn from(value: SigningScheme) -> Self {
91 match value {
92 SigningScheme::Bls12381 => 1,
93 SigningScheme::EcdsaK256Sha256 => 2,
94 SigningScheme::EcdsaP256Sha256 => 3,
95 SigningScheme::EcdsaP384Sha384 => 4,
96 SigningScheme::SchnorrEd25519Sha512 => 5,
97 SigningScheme::SchnorrK256Sha256 => 6,
98 SigningScheme::SchnorrP256Sha256 => 7,
99 SigningScheme::SchnorrP384Sha384 => 8,
100 SigningScheme::SchnorrRistretto25519Sha512 => 9,
101 SigningScheme::SchnorrEd448Shake256 => 10,
102 SigningScheme::SchnorrRedJubjubBlake2b512 => 11,
103 SigningScheme::SchnorrK256Taproot => 12,
104 SigningScheme::SchnorrRedDecaf377Blake2b512 => 13,
105 SigningScheme::SchnorrkelSubstrate => 14,
106 SigningScheme::Bls12381G1ProofOfPossession => 15,
107 SigningScheme::SchnorrRedPallasBlake2b512 => 16,
108 }
109 }
110}
111
112impl TryFrom<u8> for SigningScheme {
113 type Error = Error;
114
115 fn try_from(value: u8) -> Result<Self, Self::Error> {
116 match value {
117 1 => Ok(SigningScheme::Bls12381),
118 2 => Ok(SigningScheme::EcdsaK256Sha256),
119 3 => Ok(SigningScheme::EcdsaP256Sha256),
120 4 => Ok(SigningScheme::EcdsaP384Sha384),
121 5 => Ok(SigningScheme::SchnorrEd25519Sha512),
122 6 => Ok(SigningScheme::SchnorrK256Sha256),
123 7 => Ok(SigningScheme::SchnorrP256Sha256),
124 8 => Ok(SigningScheme::SchnorrP384Sha384),
125 9 => Ok(SigningScheme::SchnorrRistretto25519Sha512),
126 10 => Ok(SigningScheme::SchnorrEd448Shake256),
127 11 => Ok(SigningScheme::SchnorrRedJubjubBlake2b512),
128 12 => Ok(SigningScheme::SchnorrK256Taproot),
129 13 => Ok(SigningScheme::SchnorrRedDecaf377Blake2b512),
130 14 => Ok(SigningScheme::SchnorrkelSubstrate),
131 15 => Ok(SigningScheme::Bls12381G1ProofOfPossession),
132 16 => Ok(SigningScheme::SchnorrRedPallasBlake2b512),
133 _ => Err(Error::Parse(format!("Invalid signing scheme: {}", value))),
134 }
135 }
136}
137
138impl Serialize for SigningScheme {
139 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
140 where
141 S: Serializer,
142 {
143 if serializer.is_human_readable() {
144 serializer.serialize_str(&self.to_string())
145 } else {
146 serializer.serialize_u8((*self).into())
147 }
148 }
149}
150
151impl<'de> Deserialize<'de> for SigningScheme {
152 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
153 where
154 D: Deserializer<'de>,
155 {
156 if deserializer.is_human_readable() {
157 let s = String::deserialize(deserializer)?;
158 SigningScheme::from_str(&s).map_err(serde::de::Error::custom)
159 } else {
160 SigningScheme::try_from(u8::deserialize(deserializer)?)
161 .map_err(serde::de::Error::custom)
162 }
163 }
164}
165
166impl SigningScheme {
167 pub fn supports_algorithm(&self, algorithm: SigningAlgorithm) -> bool {
168 matches!(
170 (algorithm, self),
171 (SigningAlgorithm::Pairing, SigningScheme::Bls12381)
172 | (
173 SigningAlgorithm::Pairing,
174 SigningScheme::Bls12381G1ProofOfPossession
175 )
176 | (SigningAlgorithm::Ecdsa, SigningScheme::EcdsaK256Sha256)
177 | (
178 SigningAlgorithm::Schnorr,
179 SigningScheme::SchnorrEd25519Sha512
180 )
181 | (SigningAlgorithm::Schnorr, SigningScheme::SchnorrK256Sha256)
182 | (SigningAlgorithm::Schnorr, SigningScheme::SchnorrP256Sha256)
183 | (SigningAlgorithm::Schnorr, SigningScheme::SchnorrP384Sha384)
184 | (
185 SigningAlgorithm::Schnorr,
186 SigningScheme::SchnorrRistretto25519Sha512
187 )
188 | (
189 SigningAlgorithm::Schnorr,
190 SigningScheme::SchnorrEd448Shake256
191 )
192 | (
193 SigningAlgorithm::Schnorr,
194 SigningScheme::SchnorrRedJubjubBlake2b512
195 )
196 | (SigningAlgorithm::Schnorr, SigningScheme::SchnorrK256Taproot)
197 | (
198 SigningAlgorithm::Schnorr,
199 SigningScheme::SchnorrRedDecaf377Blake2b512
200 )
201 | (
202 SigningAlgorithm::Schnorr,
203 SigningScheme::SchnorrkelSubstrate
204 )
205 | (
206 SigningAlgorithm::Schnorr,
207 SigningScheme::SchnorrRedPallasBlake2b512
208 )
209 )
210 }
211
212 pub fn supports_curve(&self, curve_type: CurveType) -> bool {
213 self.curve_type() == curve_type
214 }
215
216 pub fn preferred_format(&self) -> KeyFormatPreference {
217 match self {
218 Self::Bls12381
219 | Self::Bls12381G1ProofOfPossession
220 | Self::SchnorrK256Sha256
221 | Self::SchnorrP256Sha256
222 | Self::SchnorrP384Sha384
223 | Self::SchnorrK256Taproot
224 | Self::SchnorrEd25519Sha512
225 | Self::SchnorrRistretto25519Sha512
226 | Self::SchnorrEd448Shake256
227 | Self::SchnorrRedJubjubBlake2b512
228 | Self::SchnorrRedPallasBlake2b512
229 | Self::SchnorrRedDecaf377Blake2b512
230 | Self::SchnorrkelSubstrate => KeyFormatPreference::Compressed,
231 Self::EcdsaK256Sha256 | Self::EcdsaP256Sha256 | Self::EcdsaP384Sha384 => {
232 KeyFormatPreference::Uncompressed
233 }
234 }
235 }
236
237 pub const fn ecdsa_message_len(&self) -> usize {
238 match self {
239 Self::EcdsaK256Sha256 => 32,
240 Self::EcdsaP256Sha256 => 32,
241 Self::EcdsaP384Sha384 => 48,
242 _ => 0,
243 }
244 }
245
246 pub const fn curve_type(&self) -> CurveType {
247 match self {
248 Self::Bls12381 => CurveType::BLS,
249 Self::EcdsaK256Sha256 => CurveType::K256,
250 Self::EcdsaP256Sha256 => CurveType::P256,
251 Self::EcdsaP384Sha384 => CurveType::P384,
252 Self::SchnorrEd25519Sha512 => CurveType::Ed25519,
253 Self::SchnorrK256Sha256 => CurveType::K256,
254 Self::SchnorrP256Sha256 => CurveType::P256,
255 Self::SchnorrP384Sha384 => CurveType::P384,
256 Self::SchnorrRistretto25519Sha512 | Self::SchnorrkelSubstrate => {
257 CurveType::Ristretto25519
258 }
259 Self::SchnorrEd448Shake256 => CurveType::Ed448,
260 Self::SchnorrRedJubjubBlake2b512 => CurveType::RedJubjub,
261 Self::SchnorrRedPallasBlake2b512 => CurveType::RedPallas,
262 Self::SchnorrK256Taproot => CurveType::K256,
263 Self::SchnorrRedDecaf377Blake2b512 => CurveType::RedDecaf377,
264 Self::Bls12381G1ProofOfPossession => CurveType::BLS12381G1,
265 }
266 }
267
268 pub const fn id_sign_ctx(&self) -> &'static [u8] {
269 match self {
270 SigningScheme::Bls12381 => b"LIT_HD_KEY_ID_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_",
271 SigningScheme::EcdsaP256Sha256 | SigningScheme::SchnorrP256Sha256 => {
272 b"LIT_HD_KEY_ID_P256_XMD:SHA-256_SSWU_RO_NUL_"
273 }
274 SigningScheme::SchnorrK256Taproot
275 | SigningScheme::EcdsaK256Sha256
276 | SigningScheme::SchnorrK256Sha256 => b"LIT_HD_KEY_ID_K256_XMD:SHA-256_SSWU_RO_NUL_",
277 SigningScheme::EcdsaP384Sha384 | SigningScheme::SchnorrP384Sha384 => {
278 b"LIT_HD_KEY_ID_P384_XMD:SHA-384_SSWU_RO_NUL_"
279 }
280 SigningScheme::SchnorrRistretto25519Sha512 | SigningScheme::SchnorrkelSubstrate => {
281 b"LIT_HD_KEY_ID_RISTRETTO255_XMD:SHA-512_ELL2_RO_NUL_"
282 }
283 SigningScheme::SchnorrEd25519Sha512 => {
284 b"LIT_HD_KEY_ID_ED25519_XMD:SHA-512_ELL2_RO_NUL_"
285 }
286 SigningScheme::SchnorrEd448Shake256 => {
287 b"LIT_HD_KEY_ID_ED448_XOF:SHAKE-256_ELL2_RO_NUL_"
288 }
289 SigningScheme::SchnorrRedJubjubBlake2b512 => {
290 b"LIT_HD_KEY_ID_REDJUBJUB_XMD:BLAKE2B-512_ELL2_RO_NUL_"
291 }
292 SigningScheme::SchnorrRedPallasBlake2b512 => {
293 b"LIT_HD_KEY_ID_REDPALLAS_XMD:BLAKE2B-512_SSWU_RO_NUL_"
294 }
295 SigningScheme::SchnorrRedDecaf377Blake2b512 => {
296 b"LIT_HD_KEY_ID_DECAF377_XMD:BLAKE2B-512_ELL2_RO_NUL_"
297 }
298 SigningScheme::Bls12381G1ProofOfPossession => {
299 b"LIT_HD_KEY_ID_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_"
300 }
301 }
302 }
303
304 pub const fn hash_prior_to_sending(&self) -> bool {
305 match self {
306 Self::SchnorrK256Sha256
307 | Self::SchnorrP256Sha256
308 | Self::SchnorrP384Sha384
309 | Self::SchnorrEd25519Sha512
310 | Self::SchnorrRistretto25519Sha512
311 | Self::SchnorrEd448Shake256
312 | Self::SchnorrRedJubjubBlake2b512
313 | Self::SchnorrRedPallasBlake2b512
314 | Self::SchnorrRedDecaf377Blake2b512
315 | Self::SchnorrkelSubstrate
316 | Self::Bls12381
317 | Self::Bls12381G1ProofOfPossession => false,
318 Self::EcdsaK256Sha256
319 | Self::EcdsaP256Sha256
320 | Self::EcdsaP384Sha384
321 | Self::SchnorrK256Taproot => true,
322 }
323 }
324
325 pub const fn as_str(&self) -> &'static str {
326 match self {
327 Self::Bls12381 => "Bls12381",
328 Self::EcdsaK256Sha256 => "EcdsaK256Sha256",
329 Self::EcdsaP256Sha256 => "EcdsaP256Sha256",
330 Self::EcdsaP384Sha384 => "EcdsaP384Sha384",
331 Self::SchnorrEd25519Sha512 => "SchnorrEd25519Sha512",
332 Self::SchnorrK256Sha256 => "SchnorrK256Sha256",
333 Self::SchnorrP256Sha256 => "SchnorrP256Sha256",
334 Self::SchnorrP384Sha384 => "SchnorrP384Sha384",
335 Self::SchnorrRistretto25519Sha512 => "SchnorrRistretto25519Sha512",
336 Self::SchnorrEd448Shake256 => "SchnorrEd448Shake256",
337 Self::SchnorrRedJubjubBlake2b512 => "SchnorrRedJubjubBlake2b512",
338 Self::SchnorrRedPallasBlake2b512 => "SchnorrRedPallasBlake2b512",
339 Self::SchnorrK256Taproot => "SchnorrK256Taproot",
340 Self::SchnorrRedDecaf377Blake2b512 => "SchnorrRedDecaf377Blake2b512",
341 Self::SchnorrkelSubstrate => "SchnorrkelSubstrate",
342 Self::Bls12381G1ProofOfPossession => "Bls12381G1ProofOfPossession",
343 }
344 }
345}