valence_crypto_utils/
types.rs1use core::{fmt, str::FromStr};
2
3use alloc::{
4 string::{String, ToString},
5 vec::Vec,
6};
7use k256::ecdsa::SigningKey;
8use serde::{Deserialize, Serialize};
9
10use crate::Signer;
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
14pub enum SignerEnv {
15 SecretEccNistP256(String),
17}
18
19impl Signer {
20 pub const ENV: &str = "VALENCE_SIGNER";
22
23 pub fn from_secret(secret: &[u8]) -> anyhow::Result<Self> {
25 let secret = SigningKey::from_slice(secret)
26 .map_err(|e| anyhow::anyhow!("error parsing the secret: {e}"))?;
27
28 Ok(secret.into())
29 }
30
31 pub fn to_public(&self) -> Vec<u8> {
33 match self {
34 Signer::SecretEccNistP256(secret) => secret.verifying_key().to_sec1_bytes().to_vec(),
35 }
36 }
37
38 pub fn to_env(&self) -> String {
40 SignerEnv::from(self).to_string()
41 }
42}
43
44impl From<&Signer> for SignerEnv {
45 fn from(signer: &Signer) -> Self {
46 match signer {
47 Signer::SecretEccNistP256(secret) => {
48 let secret = secret.to_bytes();
49 let secret = const_hex::encode(secret);
50
51 Self::SecretEccNistP256(secret)
52 }
53 }
54 }
55}
56
57impl fmt::Display for Signer {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 use Signer::*;
60
61 match self {
62 SecretEccNistP256(secret) => {
63 let public = secret.verifying_key().to_sec1_bytes();
64 let public = const_hex::encode(public);
65
66 write!(f, "EccNistP256({public})")
67 }
68 }
69 }
70}
71
72impl fmt::Display for SignerEnv {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 let env = serde_json::to_string(&self).expect("serialization is infallible");
75
76 write!(f, "{env}")
77 }
78}
79
80impl TryFrom<SignerEnv> for Signer {
81 type Error = anyhow::Error;
82
83 fn try_from(signer: SignerEnv) -> anyhow::Result<Self> {
84 match signer {
85 SignerEnv::SecretEccNistP256(secret) => {
86 let secret = const_hex::decode(secret)?;
87
88 Signer::from_secret(&secret)
89 }
90 }
91 }
92}
93
94impl From<SigningKey> for Signer {
95 fn from(secret: SigningKey) -> Self {
96 Self::SecretEccNistP256(secret)
97 }
98}
99
100impl FromStr for Signer {
101 type Err = anyhow::Error;
102
103 fn from_str(s: &str) -> anyhow::Result<Self> {
104 SignerEnv::from_str(s).and_then(Signer::try_from)
105 }
106}
107
108impl FromStr for SignerEnv {
109 type Err = anyhow::Error;
110
111 fn from_str(s: &str) -> anyhow::Result<Self> {
112 Ok(serde_json::from_str(s)?)
113 }
114}
115
116#[cfg(feature = "std")]
117impl Signer {
118 pub fn try_from_env() -> anyhow::Result<Self> {
120 let env = ::std::env::var(Self::ENV)?;
121
122 Self::from_str(&env)
123 }
124}
125
126#[cfg(all(test, feature = "std"))]
127mod tests {
128 use std::env;
129
130 use super::*;
131
132 #[test]
133 fn signer_from_env_works() {
134 let secret = "b0cb16ba60d3b770eb5e001efaa8f5b94270f4e8e858f673f5e896db11d21698";
135 let secret = const_hex::decode(secret).unwrap();
136 let signer = Signer::from_secret(&secret).unwrap();
137 let public = signer.to_public();
138
139 unsafe {
140 env::set_var(Signer::ENV, signer.to_env());
141 }
142
143 let deserialized = Signer::try_from_env().unwrap().to_public();
144
145 assert_eq!(public, deserialized);
146 }
147}