defuse_crypto/
parse.rs

1use thiserror::Error as ThisError;
2
3use crate::Curve;
4pub trait TypedCurve: Curve {
5    const CURVE_TYPE: CurveType;
6
7    #[inline]
8    fn to_base58(bytes: impl AsRef<[u8]>) -> String {
9        format!(
10            "{}:{}",
11            Self::CURVE_TYPE,
12            bs58::encode(bytes.as_ref()).into_string()
13        )
14    }
15
16    fn parse_base58<const N: usize>(s: impl AsRef<str>) -> Result<[u8; N], crate::ParseCurveError> {
17        let s = s.as_ref();
18        let data = if let Some((curve, data)) = s.split_once(':') {
19            if !curve.eq_ignore_ascii_case(Self::CURVE_TYPE.into()) {
20                return Err(crate::ParseCurveError::WrongCurveType);
21            }
22            data
23        } else {
24            s
25        };
26        checked_base58_decode_array(data)
27    }
28}
29
30#[derive(strum::Display, strum::IntoStaticStr, strum::EnumString)]
31#[strum(serialize_all = "snake_case", ascii_case_insensitive)]
32#[repr(u8)]
33pub enum CurveType {
34    #[cfg(feature = "ed25519")]
35    Ed25519 = 0,
36    #[cfg(feature = "secp256k1")]
37    Secp256k1 = 1,
38    #[cfg(feature = "p256")]
39    P256 = 2,
40}
41
42#[derive(Debug, ThisError, PartialEq, Eq)]
43pub enum ParseCurveError {
44    #[error("wrong curve type")]
45    WrongCurveType,
46    #[error("base58: {0}")]
47    Base58(#[from] bs58::decode::Error),
48    #[error("invalid length")]
49    InvalidLength,
50}
51
52fn checked_base58_decode_array<const N: usize>(
53    input: impl AsRef<[u8]>,
54) -> Result<[u8; N], crate::ParseCurveError> {
55    let mut output = [0u8; N];
56    let n = bs58::decode(input.as_ref())
57        // NOTE: `.into_array_const()` doesn't return an error on insufficient
58        // input length and pads the array with zeros
59        .onto(&mut output)?;
60    (n == N)
61        .then_some(output)
62        .ok_or(crate::ParseCurveError::InvalidLength)
63}