river_core/
crypto_values.rs1use 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 s.starts_with(Self::VERSION_PREFIX) {
78 Self::from_encoded_string(s)
79 } else {
80 let decoded = bs58::decode(s)
82 .into_vec()
83 .map_err(|e| format!("Base58 decode error: {}", e))?;
84
85 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}