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)]
31pub enum CurveType {
32    Ed25519,
33    Secp256k1,
34    P256,
35}
36
37pub trait TypedCurve: Curve {
38    const CURVE_TYPE: CurveType;
39
40    #[inline]
41    fn to_base58(bytes: impl AsRef<[u8]>) -> String {
42        format!(
43            "{}:{}",
44            Self::CURVE_TYPE,
45            bs58::encode(bytes.as_ref()).into_string()
46        )
47    }
48
49    fn parse_base58<const N: usize>(s: impl AsRef<str>) -> Result<[u8; N], ParseCurveError> {
50        let s = s.as_ref();
51        let data = if let Some((curve, data)) = s.split_once(':') {
52            if !curve.eq_ignore_ascii_case(Self::CURVE_TYPE.into()) {
53                return Err(ParseCurveError::WrongCurveType);
54            }
55            data
56        } else {
57            s
58        };
59        checked_base58_decode_array(data)
60    }
61}