defuse_crypto/curve/
mod.rs

1mod ed25519;
2mod p256;
3mod secp256k1;
4
5use crate::{ParseCurveError, parse::checked_base58_decode_array};
6
7pub use self::{ed25519::*, p256::*, secp256k1::*};
8
9use near_sdk::bs58;
10use strum::{Display, EnumString, IntoStaticStr};
11
12pub trait Curve {
13    type PublicKey;
14    type Signature;
15
16    /// Message that can be signed by this curve
17    type Message: AsRef<[u8]> + ?Sized;
18
19    /// Public key that should be known prior to verification
20    type VerifyingKey;
21
22    fn verify(
23        signature: &Self::Signature,
24        message: &Self::Message,
25        verifying_key: &Self::VerifyingKey,
26    ) -> Option<Self::PublicKey>;
27}
28
29#[derive(Display, IntoStaticStr, EnumString)]
30#[strum(serialize_all = "snake_case", ascii_case_insensitive)]
31#[repr(u8)]
32pub enum CurveType {
33    Ed25519 = 0,
34    Secp256k1 = 1,
35    P256 = 2,
36}
37
38pub trait TypedCurve: Curve {
39    const CURVE_TYPE: CurveType;
40
41    #[inline]
42    fn to_base58(bytes: impl AsRef<[u8]>) -> String {
43        format!(
44            "{}:{}",
45            Self::CURVE_TYPE,
46            bs58::encode(bytes.as_ref()).into_string()
47        )
48    }
49
50    fn parse_base58<const N: usize>(s: impl AsRef<str>) -> Result<[u8; N], ParseCurveError> {
51        let s = s.as_ref();
52        let data = if let Some((curve, data)) = s.split_once(':') {
53            if !curve.eq_ignore_ascii_case(Self::CURVE_TYPE.into()) {
54                return Err(ParseCurveError::WrongCurveType);
55            }
56            data
57        } else {
58            s
59        };
60        checked_base58_decode_array(data)
61    }
62}