1use base64::engine::general_purpose;
34use base64::Engine;
35use ring::digest;
36
37#[cfg(feature = "2fa")]
39pub mod totp;
40
41#[cfg(feature = "2fa")]
42pub mod secure_totp;
43
44#[cfg(feature = "2fa")]
45pub mod hardware_fingerprint;
46
47#[cfg(feature = "2fa")]
48pub mod security_question;
49
50#[cfg(feature = "cli")]
52pub mod bot_helper;
53
54#[cfg(feature = "solana-ops")]
56pub mod solana_utils;
57
58pub use solana_sdk::signature::{Keypair, Signer};
60pub use solana_sdk::pubkey::Pubkey;
61
62fn xor_encrypt_decrypt(data: &[u8], key: &[u8; 32]) -> Vec<u8> {
68 let mut result = Vec::with_capacity(data.len());
69
70 let mut keystream = Vec::new();
72 let mut i: u32 = 0;
73 while keystream.len() < data.len() {
74 let mut ctx = digest::Context::new(&digest::SHA256);
75 ctx.update(key);
76 ctx.update(&i.to_le_bytes());
77 let hash = ctx.finish();
78 keystream.extend_from_slice(hash.as_ref());
79 i += 1;
80 }
81
82 for (i, &byte) in data.iter().enumerate() {
84 result.push(byte ^ keystream[i % keystream.len()]);
85 }
86
87 result
88}
89
90pub fn encrypt_key(secret_key: &str, encryption_key: &[u8; 32]) -> Result<String, String> {
94 let data = secret_key.as_bytes();
95 let encrypted = xor_encrypt_decrypt(data, encryption_key);
96 Ok(general_purpose::STANDARD.encode(encrypted))
97}
98
99pub fn decrypt_key(encrypted_data: &str, encryption_key: &[u8; 32]) -> Result<String, String> {
103 let ciphertext = general_purpose::STANDARD.decode(encrypted_data)
104 .map_err(|_| "Invalid encrypted data format".to_string())?;
105
106 let decrypted = xor_encrypt_decrypt(&ciphertext, encryption_key);
107
108 String::from_utf8(decrypted)
109 .map_err(|_| "Invalid UTF-8 data in decrypted content".to_string())
110}
111
112pub const MIN_PASSWORD_LENGTH: usize = 10;
114
115pub const MAX_PASSWORD_LENGTH: usize = 20;
117
118const PASSWORD_SALT: &[u8] = b"sol-safekey-v1-salt-2025";
121
122pub fn generate_encryption_key_simple(password: &str) -> [u8; 32] {
133 let mut salted_password = password.as_bytes().to_vec();
135 salted_password.extend_from_slice(PASSWORD_SALT);
136
137 let hash = digest::digest(&digest::SHA256, &salted_password);
139
140 let mut key = [0u8; 32];
142 key[0..16].copy_from_slice(&hash.as_ref()[0..16]);
143
144 key[16..32].copy_from_slice(&hash.as_ref()[0..16]);
147
148 key
149}
150
151pub type EncryptionResult<T> = Result<T, String>;
157
158pub struct KeyManager;
163
164impl KeyManager {
165 pub fn generate_keypair() -> Keypair {
176 Keypair::new()
177 }
178
179 pub fn encrypt_with_password(private_key: &str, password: &str) -> EncryptionResult<String> {
204 let key = generate_encryption_key_simple(password);
205 encrypt_key(private_key, &key)
206 }
207
208 pub fn decrypt_with_password(encrypted_data: &str, password: &str) -> EncryptionResult<String> {
231 let key = generate_encryption_key_simple(password);
232 decrypt_key(encrypted_data, &key)
233 }
234
235 pub fn get_public_key(private_key: &str) -> EncryptionResult<String> {
245 use solana_sdk::signature::Keypair;
246
247 let keypair = Keypair::from_base58_string(private_key);
249
250 Ok(keypair.pubkey().to_string())
251 }
252
253 pub fn keypair_to_encrypted_json(keypair: &Keypair, password: &str) -> EncryptionResult<String> {
266 use serde_json::json;
267 use chrono::Utc;
268
269 let private_key = keypair.to_base58_string();
270 let public_key = keypair.pubkey().to_string();
271
272 let encrypted = Self::encrypt_with_password(&private_key, password)?;
273
274 let keystore = json!({
275 "encrypted_private_key": encrypted,
276 "public_key": public_key,
277 "encryption_type": "password_only",
278 "created_at": Utc::now().to_rfc3339(),
279 });
280
281 Ok(keystore.to_string())
282 }
283
284 pub fn keypair_from_encrypted_json(json_data: &str, password: &str) -> EncryptionResult<Keypair> {
295 use serde_json::Value;
296
297 let data: Value = serde_json::from_str(json_data)
298 .map_err(|_| "Invalid JSON format")?;
299
300 let encrypted = data["encrypted_private_key"]
301 .as_str()
302 .ok_or("Missing encrypted_private_key field")?;
303
304 let private_key_str = Self::decrypt_with_password(encrypted, password)?;
305
306 let keypair = Keypair::from_base58_string(&private_key_str);
308
309 Ok(keypair)
310 }
311}
312
313#[cfg(feature = "2fa")]
322#[allow(dead_code)]
326fn derive_totp_secret_from_password(password: &str, account: &str, issuer: &str) -> Result<String, String> {
327 use ring::pbkdf2;
328 use data_encoding::BASE32_NOPAD;
329 use std::num::NonZeroU32;
330
331 let salt = format!("sol-safekey-totp-{}-{}", issuer, account);
332 let iterations = NonZeroU32::new(100_000)
333 .ok_or("Invalid iteration count")?;
334
335 let mut secret = [0u8; 20]; pbkdf2::derive(
337 pbkdf2::PBKDF2_HMAC_SHA256,
338 iterations,
339 salt.as_bytes(),
340 password.as_bytes(),
341 &mut secret,
342 );
343
344 Ok(BASE32_NOPAD.encode(&secret))
345}
346
347#[cfg(feature = "2fa")]
348pub fn derive_totp_secret_from_hardware_and_password(
352 hardware_fingerprint: &str,
353 master_password: &str,
354 account: &str,
355 issuer: &str,
356) -> Result<String, String> {
357 use ring::pbkdf2;
358 use data_encoding::BASE32_NOPAD;
359 use std::num::NonZeroU32;
360
361 let key_material = format!("{}::{}", hardware_fingerprint, master_password);
362 let salt = format!("sol-safekey-2fa-{}-{}", issuer, account);
363 let iterations = NonZeroU32::new(100_000)
364 .ok_or("Invalid iteration count")?;
365
366 let mut secret = [0u8; 20];
367 pbkdf2::derive(
368 pbkdf2::PBKDF2_HMAC_SHA256,
369 iterations,
370 salt.as_bytes(),
371 key_material.as_bytes(),
372 &mut secret,
373 );
374
375 Ok(BASE32_NOPAD.encode(&secret))
376}
377
378#[cfg(feature = "2fa")]
379fn verify_current_totp_code(totp_secret: &str, current_code: &str) -> Result<(), String> {
381 use crate::totp::{TOTPConfig, TOTPManager};
382
383 let config = TOTPConfig {
384 secret: totp_secret.to_string(),
385 account: "wallet".to_string(),
386 issuer: "Sol-SafeKey".to_string(),
387 algorithm: "SHA1".to_string(),
388 digits: 6,
389 step: 30,
390 };
391
392 let totp_manager = TOTPManager::new(config);
393
394 match totp_manager.verify_code(current_code) {
395 Ok(true) => Ok(()),
396 Ok(false) => Err("验证失败,请检查主密码、安全问题答案或2FA验证码".to_string()),
397 Err(e) => Err(format!("验证失败: {}", e)),
398 }
399}
400
401#[cfg(feature = "2fa")]
406pub fn generate_triple_factor_key(
410 hardware_fingerprint: &str,
411 master_password: &str,
412 security_answer: &str,
413) -> [u8; 32] {
414 use ring::pbkdf2;
415 use std::num::NonZeroU32;
416
417 let key_material = format!(
418 "HW:{}|PASS:{}|QA:{}",
419 hardware_fingerprint,
420 master_password,
421 security_answer.trim().to_lowercase()
422 );
423
424 let salt = b"sol-safekey-triple-factor-v1";
425 let iterations = NonZeroU32::new(200_000).unwrap();
426
427 let mut key = [0u8; 32];
428 pbkdf2::derive(
429 pbkdf2::PBKDF2_HMAC_SHA256,
430 iterations,
431 salt,
432 key_material.as_bytes(),
433 &mut key,
434 );
435
436 key
437}
438
439#[cfg(feature = "2fa")]
440pub fn encrypt_with_triple_factor(
444 private_key: &str,
445 twofa_secret: &str,
446 hardware_fingerprint: &str,
447 master_password: &str,
448 question_index: usize,
449 security_answer: &str,
450) -> Result<String, String> {
451 use serde_json::json;
452
453 let encryption_key = generate_triple_factor_key(
454 hardware_fingerprint,
455 master_password,
456 security_answer,
457 );
458
459 let data_package = json!({
460 "private_key": private_key,
461 "twofa_secret": twofa_secret,
462 "question_index": question_index,
463 "version": "triple_factor_v1",
464 "created_at": std::time::SystemTime::now()
465 .duration_since(std::time::UNIX_EPOCH)
466 .unwrap()
467 .as_secs()
468 });
469
470 let package_str = data_package.to_string();
471 let encrypted = encrypt_key(&package_str, &encryption_key)?;
472
473 Ok(encrypted)
474}
475
476#[cfg(feature = "2fa")]
477pub fn decrypt_with_triple_factor_and_2fa(
481 encrypted_data: &str,
482 hardware_fingerprint: &str,
483 master_password: &str,
484 security_answer: &str,
485 twofa_code: &str,
486) -> Result<(String, String, usize), String> {
487 let decryption_key = generate_triple_factor_key(
488 hardware_fingerprint,
489 master_password,
490 security_answer,
491 );
492
493 let decrypted = decrypt_key(encrypted_data, &decryption_key)
494 .map_err(|_| "解密失败,请检查主密码、安全问题答案是否正确")?;
495
496 let data: serde_json::Value = serde_json::from_str(&decrypted)
497 .map_err(|_| "解密失败,请检查主密码、安全问题答案是否正确")?;
498
499 let private_key = data["private_key"]
500 .as_str()
501 .ok_or("缺少私钥数据")?
502 .to_string();
503
504 let twofa_secret = data["twofa_secret"]
505 .as_str()
506 .ok_or("缺少2FA密钥数据")?
507 .to_string();
508
509 let question_index = data["question_index"]
510 .as_u64()
511 .ok_or("缺少安全问题索引")? as usize;
512
513 verify_current_totp_code(&twofa_secret, twofa_code)?;
515
516 Ok((private_key, twofa_secret, question_index))
517}
518
519#[cfg(test)]
524mod tests {
525 use super::*;
526
527 #[test]
528 fn test_generate_keypair() {
529 let keypair = KeyManager::generate_keypair();
530 assert_eq!(keypair.to_bytes().len(), 64);
531 }
532
533 #[test]
534 fn test_encrypt_decrypt_with_password() {
535 let keypair = KeyManager::generate_keypair();
536 let private_key = keypair.to_base58_string();
537 let password = "test_password_123";
538
539 let encrypted = KeyManager::encrypt_with_password(&private_key, password).unwrap();
540 let decrypted = KeyManager::decrypt_with_password(&encrypted, password).unwrap();
541
542 assert_eq!(private_key, decrypted);
543 }
544
545 #[test]
546 fn test_get_public_key() {
547 let keypair = KeyManager::generate_keypair();
548 let private_key = keypair.to_base58_string();
549 let expected_pubkey = keypair.pubkey().to_string();
550
551 let pubkey = KeyManager::get_public_key(&private_key).unwrap();
552 assert_eq!(pubkey, expected_pubkey);
553 }
554
555 #[test]
556 fn test_keystore_json_round_trip() {
557 let keypair = KeyManager::generate_keypair();
558 let password = "secure_password";
559
560 let json = KeyManager::keypair_to_encrypted_json(&keypair, password).unwrap();
561 let restored_keypair = KeyManager::keypair_from_encrypted_json(&json, password).unwrap();
562
563 assert_eq!(keypair.to_bytes(), restored_keypair.to_bytes());
564 }
565
566 #[test]
567 fn test_wrong_password_fails() {
568 let keypair = KeyManager::generate_keypair();
569 let private_key = keypair.to_base58_string();
570
571 let encrypted = KeyManager::encrypt_with_password(&private_key, "correct").unwrap();
572 let result = KeyManager::decrypt_with_password(&encrypted, "wrong");
573
574 assert!(result.is_err());
575 }
576}