near_api_types/crypto/
mod.rs

1use std::{
2    fmt::{Display, Formatter},
3    str::FromStr,
4};
5
6use crate::errors::{DataConversionError, KeyTypeError};
7
8pub mod public_key;
9pub mod secret_key;
10pub mod signature;
11
12pub const ED25519_PUBLIC_KEY_LENGTH: usize = 32;
13pub const SECP256K1_PUBLIC_KEY_LENGTH: usize = 64;
14pub const COMPONENT_SIZE: usize = 32;
15pub const SECP256K1_SIGNATURE_LENGTH: usize = 65;
16
17#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
18#[cfg_attr(test, derive(bolero::TypeGenerator))]
19pub enum KeyType {
20    ED25519 = 0,
21    SECP256K1 = 1,
22}
23
24impl Display for KeyType {
25    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
26        f.write_str(match self {
27            Self::ED25519 => "ed25519",
28            Self::SECP256K1 => "secp256k1",
29        })
30    }
31}
32
33impl FromStr for KeyType {
34    type Err = KeyTypeError;
35
36    fn from_str(value: &str) -> Result<Self, Self::Err> {
37        let lowercase_key_type = value.to_ascii_lowercase();
38        match lowercase_key_type.as_str() {
39            "ed25519" => Ok(Self::ED25519),
40            "secp256k1" => Ok(Self::SECP256K1),
41            _ => Err(KeyTypeError::InvalidKeyFormat(
42                lowercase_key_type.to_string(),
43            )),
44        }
45    }
46}
47
48impl TryFrom<u8> for KeyType {
49    type Error = KeyTypeError;
50
51    fn try_from(value: u8) -> Result<Self, Self::Error> {
52        match value {
53            0 => Ok(Self::ED25519),
54            1 => Ok(Self::SECP256K1),
55            unknown_key_type => Err(KeyTypeError::InvalidKeyTypeByteIndex(unknown_key_type)),
56        }
57    }
58}
59
60fn split_key_type_data(value: &str) -> Result<(KeyType, &str), DataConversionError> {
61    if let Some((prefix, key_data)) = value.split_once(':') {
62        Ok((KeyType::from_str(prefix)?, key_data))
63    } else {
64        // If there is no prefix then we Default to ED25519.
65        Ok((KeyType::ED25519, value))
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::{public_key::PublicKey, secret_key::SecretKey, signature::Signature, KeyType};
72
73    #[test]
74    fn signature_verify_fuzzer() {
75        bolero::check!().with_type().for_each(
76            |(key_type, sign, data, public_key): &(KeyType, [u8; 65], Vec<u8>, PublicKey)| {
77                let signature = match key_type {
78                    KeyType::ED25519 => {
79                        Signature::from_parts(KeyType::ED25519, &sign[..64]).unwrap()
80                    }
81                    KeyType::SECP256K1 => {
82                        Signature::from_parts(KeyType::SECP256K1, &sign[..65]).unwrap()
83                    }
84                };
85                let _ = signature.verify(data, public_key);
86            },
87        );
88    }
89
90    #[test]
91    fn regression_signature_verification_originally_failed() {
92        let signature = Signature::from_parts(KeyType::SECP256K1, &[4; 65]).unwrap();
93        let _ = signature.verify(&[], &PublicKey::empty(KeyType::SECP256K1));
94    }
95
96    #[test]
97    fn test_invalid_data() {
98        // cspell:disable-next-line
99        let invalid = "\"secp256k1:2xVqteU8PWhadHTv99TGh3bSf\"";
100        assert!(serde_json::from_str::<PublicKey>(invalid).is_err());
101        assert!(serde_json::from_str::<SecretKey>(invalid).is_err());
102        assert!(serde_json::from_str::<Signature>(invalid).is_err());
103    }
104}