Skip to main content

river_core/
crypto_values.rs

1use bs58;
2use ed25519_dalek::{Signature, SigningKey, VerifyingKey};
3use std::str::FromStr;
4
5#[derive(Debug, Clone, PartialEq)]
6pub enum CryptoValue {
7    VerifyingKey(VerifyingKey),
8    SigningKey(SigningKey),
9    Signature(Signature),
10}
11
12impl CryptoValue {
13    const VERSION_PREFIX: &'static str = "river:v1";
14
15    pub fn to_encoded_string(&self) -> String {
16        let type_str = match self {
17            CryptoValue::VerifyingKey(_) => "vk",
18            CryptoValue::SigningKey(_) => "sk",
19            CryptoValue::Signature(_) => "sig",
20        };
21
22        let key_bytes = match self {
23            CryptoValue::VerifyingKey(vk) => vk.to_bytes().to_vec(),
24            CryptoValue::SigningKey(sk) => sk.to_bytes().to_vec(),
25            CryptoValue::Signature(sig) => sig.to_bytes().to_vec(),
26        };
27
28        format!(
29            "{}:{}:{}",
30            Self::VERSION_PREFIX,
31            type_str,
32            bs58::encode(key_bytes).into_string()
33        )
34    }
35
36    pub fn from_encoded_string(s: &str) -> Result<Self, String> {
37        let parts: Vec<&str> = s.split(':').collect();
38        if parts.len() != 4 || format!("{}:{}", parts[0], parts[1]) != Self::VERSION_PREFIX {
39            return Err("Invalid format".to_string());
40        }
41
42        let decoded = bs58::decode(parts[3])
43            .into_vec()
44            .map_err(|e| format!("Base58 decode error: {}", e))?;
45
46        match parts[2] {
47            "vk" => {
48                let bytes: [u8; 32] = decoded
49                    .try_into()
50                    .map_err(|_| "Invalid verifying key length".to_string())?;
51                VerifyingKey::from_bytes(&bytes)
52                    .map(CryptoValue::VerifyingKey)
53                    .map_err(|e| format!("Invalid verifying key: {}", e))
54            }
55            "sk" => {
56                let bytes: [u8; 32] = decoded
57                    .try_into()
58                    .map_err(|_| "Invalid signing key length".to_string())?;
59                Ok(CryptoValue::SigningKey(SigningKey::from_bytes(&bytes)))
60            }
61            "sig" => {
62                let bytes: [u8; 64] = decoded
63                    .try_into()
64                    .map_err(|_| "Invalid signature length".to_string())?;
65                Ok(CryptoValue::Signature(Signature::from_bytes(&bytes)))
66            }
67            _ => Err("Unknown key type".to_string()),
68        }
69    }
70}
71
72impl FromStr for CryptoValue {
73    type Err = String;
74
75    fn from_str(s: &str) -> Result<Self, Self::Err> {
76        // If string already contains prefix, use it directly
77        if s.starts_with(Self::VERSION_PREFIX) {
78            Self::from_encoded_string(s)
79        } else {
80            // Otherwise treat as raw base58 data
81            let decoded = bs58::decode(s)
82                .into_vec()
83                .map_err(|e| format!("Base58 decode error: {}", e))?;
84
85            // Try to interpret as signing key first
86            if decoded.len() == 32 {
87                let bytes: [u8; 32] = decoded
88                    .try_into()
89                    .map_err(|_| "Invalid signing key length".to_string())?;
90                Ok(CryptoValue::SigningKey(SigningKey::from_bytes(&bytes)))
91            } else {
92                Err("Invalid key length".to_string())
93            }
94        }
95    }
96}