1use crate::tn_public_address;
2use crate::txn_lib::TnPubkey;
3use crate::{tn_public_address::tn_pubkey_to_address_string, tn_signature_encoding};
4use anyhow::Result;
5use ed25519_dalek::SigningKey;
6use hex;
7use rand::TryRngCore;
8use rand::rngs::OsRng;
9use serde::{Deserialize, Serialize};
10use std::fmt;
11
12use thiserror::Error;
13
14pub fn gen_key() -> Result<[u8; 32]> {
15 let mut private_key = [0u8; 32];
16 let mut rng = OsRng;
17 rng.try_fill_bytes(&mut private_key).unwrap();
18 Ok(private_key)
19}
20
21#[derive(Debug, Clone)]
22pub struct KeyPair {
23 pub name: String,
24 pub private_key: [u8; 32],
25 pub public_key: TnPubkey,
26 pub address_string: Pubkey,
27}
28
29impl KeyPair {
30 pub fn generate(name: &str) -> Result<Self> {
31 let mut private_key = [0u8; 32];
33 let mut rng = OsRng;
34 rng.try_fill_bytes(&mut private_key)?;
35 let signing_key = SigningKey::from_bytes(&private_key);
37 let verifying_key = signing_key.verifying_key();
38 let public_key = verifying_key.to_bytes();
39
40 let address_string = Pubkey::from_bytes(&public_key);
42
43 Ok(Self {
44 name: name.to_string(),
45 private_key,
46 public_key,
47 address_string,
48 })
49 }
50
51 pub fn from_hex_private_key<P: AsRef<[u8]>>(name: &str, hex_private_key: P) -> Result<Self> {
52 let private_key_bytes = hex::decode(hex_private_key)
54 .map_err(|e| anyhow::anyhow!("Failed to decode hex private key: {}", e))?;
55
56 if private_key_bytes.len() != 32 {
57 return Err(anyhow::anyhow!(
58 "Private key must be 32 bytes, got {}",
59 private_key_bytes.len()
60 ));
61 }
62
63 let mut private_key = [0u8; 32];
64 private_key.copy_from_slice(&private_key_bytes);
65
66 let signing_key = SigningKey::from_bytes(&private_key);
68 let verifying_key = signing_key.verifying_key();
69 let public_key = verifying_key.to_bytes();
70
71 let address_string = Pubkey::from_bytes(&public_key);
73
74 Ok(Self {
75 name: name.to_string(),
76 private_key,
77 public_key,
78 address_string,
79 })
80 }
81
82 pub fn public_key_hex(&self) -> String {
83 hex::encode(self.public_key)
84 }
85 pub fn public_key_str(&self) -> String {
86 tn_pubkey_to_address_string(&self.public_key)
87 }
88}
89
90#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
95pub struct Pubkey(String);
96
97impl Pubkey {
98 pub fn new(key: String) -> Result<Self> {
102 if key.is_empty() {
104 return Err(ValidationError::InvalidPubkey("empty pubkey".to_string()).into());
105 }
106
107 if key.len() != 46 {
109 return Err(ValidationError::InvalidPubkey(format!(
110 "invalid pubkey length: expected 46, got {}",
111 key.len()
112 ))
113 .into());
114 }
115
116 if !key.starts_with("ta") {
117 return Err(
118 ValidationError::InvalidPubkey("pubkey must start with 'ta'".to_string()).into(),
119 );
120 }
121
122 let mut decoded = [0u8; 32];
124 match tn_public_address::tn_public_address_decode(&mut decoded, key.as_bytes()) {
125 Ok(()) => Ok(Self(key)),
126 Err(code) => Err(ValidationError::InvalidPubkey(format!(
127 "invalid pubkey format: decode error {}",
128 code
129 ))
130 .into()),
131 }
132 }
133
134 pub fn as_str(&self) -> &str {
136 &self.0
137 }
138
139 pub fn to_bytes(&self) -> Result<[u8; 32]> {
141 let mut bytes = [0u8; 32];
142 match tn_public_address::tn_public_address_decode(&mut bytes, self.0.as_bytes()) {
143 Ok(()) => Ok(bytes),
144 Err(code) => Err(ValidationError::InvalidPubkey(format!(
145 "failed to decode pubkey: error {}",
146 code
147 ))
148 .into()),
149 }
150 }
151
152 pub fn from_bytes(bytes: &[u8; 32]) -> Self {
154 let address = tn_public_address::tn_pubkey_to_address_string(bytes);
155 Self(address)
157 }
158}
159
160impl fmt::Display for Pubkey {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 write!(f, "{}", self.0)
163 }
164}
165
166#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
171pub struct Signature(String);
172
173impl Signature {
174 pub fn new(sig: String) -> Result<Self> {
178 if sig.is_empty() {
180 return Err(ValidationError::InvalidSignature("empty signature".to_string()).into());
181 }
182
183 if sig.len() != 90 {
185 return Err(ValidationError::InvalidSignature(format!(
186 "invalid signature length: expected 90, got {}",
187 sig.len()
188 ))
189 .into());
190 }
191
192 if !sig.starts_with("ts") {
193 return Err(ValidationError::InvalidSignature(
194 "signature must start with 'ts'".to_string(),
195 )
196 .into());
197 }
198
199 let mut decoded = [0u8; 64];
201 match tn_signature_encoding::tn_signature_decode(&mut decoded, sig.as_bytes()) {
202 Ok(()) => Ok(Self(sig)),
203 Err(code) => Err(ValidationError::InvalidSignature(format!(
204 "invalid signature format: decode error {}",
205 code
206 ))
207 .into()),
208 }
209 }
210
211 pub fn as_str(&self) -> &str {
213 &self.0
214 }
215
216 pub fn to_bytes(&self) -> Result<[u8; 64]> {
218 let mut bytes = [0u8; 64];
219 match tn_signature_encoding::tn_signature_decode(&mut bytes, self.0.as_bytes()) {
220 Ok(()) => Ok(bytes),
221 Err(code) => Err(ValidationError::InvalidSignature(format!(
222 "failed to decode signature: error {}",
223 code
224 ))
225 .into()),
226 }
227 }
228
229 pub fn from_bytes(bytes: &[u8; 64]) -> Self {
231 let signature = tn_signature_encoding::tn_signature_to_string(bytes);
232 Self(signature)
234 }
235}
236
237impl fmt::Display for Signature {
238 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
239 write!(f, "{}", self.0)
240 }
241}
242
243#[derive(Error, Debug)]
245pub enum ValidationError {
246 #[error("Invalid public key: {0}")]
248 InvalidPubkey(String),
249
250 #[error("Invalid signature: {0}")]
252 InvalidSignature(String),
253}
254
255#[cfg(test)]
256mod tests {
257
258 use super::*;
259
260 #[test]
261 fn test_pubkey_validation() {
262 let bytes = [1u8; 32];
264 let valid_pubkey = tn_public_address::tn_pubkey_to_address_string(&bytes);
265 assert!(Pubkey::new(valid_pubkey.to_string()).is_ok());
266
267 assert!(Pubkey::new("".to_string()).is_err());
269
270 assert!(Pubkey::new("ta111".to_string()).is_err());
272
273 assert!(Pubkey::new("tb1111111111111111111111111111111111111111111".to_string()).is_err());
275
276 assert!(Pubkey::new("ta!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".to_string()).is_err());
278 }
279
280 #[test]
281 fn test_signature_validation() {
282 let bytes = [1u8; 64];
284 let valid_signature = tn_signature_encoding::tn_signature_to_string(&bytes);
285 assert!(Signature::new(valid_signature.to_string()).is_ok());
286
287 assert!(Signature::new("".to_string()).is_err());
289
290 assert!(Signature::new("ts111".to_string()).is_err());
292
293 assert!(Signature::new("ta111111111111111111111111111111111111111111111111111111111111111111111111111111111111".to_string()).is_err());
295
296 assert!(Signature::new("ts!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!".to_string()).is_err());
298 }
299
300 #[test]
301 fn test_pubkey_roundtrip() {
302 let bytes = [1u8; 32];
304 let pubkey = Pubkey::from_bytes(&bytes);
305 let decoded_bytes = pubkey.to_bytes().unwrap();
306 assert_eq!(bytes, decoded_bytes);
307 }
308
309 #[test]
310 fn test_signature_roundtrip() {
311 let bytes = [1u8; 64];
313 let signature = Signature::from_bytes(&bytes);
314 let decoded_bytes = signature.to_bytes().unwrap();
315 assert_eq!(bytes, decoded_bytes);
316 }
317}