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
50pub mod interactive;
52
53pub mod bot_helper;
55
56pub mod operations;
58
59#[cfg(any(feature = "solana-ops", feature = "sol-trade-sdk"))]
61pub mod solana_utils;
62
63pub use solana_sdk::signature::{Keypair, Signer};
65pub use solana_sdk::pubkey::Pubkey;
66
67fn xor_encrypt_decrypt(data: &[u8], key: &[u8; 32]) -> Vec<u8> {
73 let mut result = Vec::with_capacity(data.len());
74
75 let mut keystream = Vec::new();
77 let mut i: u32 = 0;
78 while keystream.len() < data.len() {
79 let mut ctx = digest::Context::new(&digest::SHA256);
80 ctx.update(key);
81 ctx.update(&i.to_le_bytes());
82 let hash = ctx.finish();
83 keystream.extend_from_slice(hash.as_ref());
84 i += 1;
85 }
86
87 for (i, &byte) in data.iter().enumerate() {
89 result.push(byte ^ keystream[i % keystream.len()]);
90 }
91
92 result
93}
94
95pub fn encrypt_key(secret_key: &str, encryption_key: &[u8; 32]) -> Result<String, String> {
99 let data = secret_key.as_bytes();
100 let encrypted = xor_encrypt_decrypt(data, encryption_key);
101 Ok(general_purpose::STANDARD.encode(encrypted))
102}
103
104pub fn decrypt_key(encrypted_data: &str, encryption_key: &[u8; 32]) -> Result<String, String> {
108 let ciphertext = general_purpose::STANDARD.decode(encrypted_data)
109 .map_err(|_| "Invalid encrypted data format".to_string())?;
110
111 let decrypted = xor_encrypt_decrypt(&ciphertext, encryption_key);
112
113 String::from_utf8(decrypted)
114 .map_err(|_| "Invalid UTF-8 data in decrypted content".to_string())
115}
116
117pub const MIN_PASSWORD_LENGTH: usize = 10;
119
120pub const MAX_PASSWORD_LENGTH: usize = 20;
122
123const PASSWORD_SALT: &[u8] = b"sol-safekey-v1-salt-2025";
126
127pub fn generate_encryption_key_simple(password: &str) -> [u8; 32] {
138 let mut salted_password = password.as_bytes().to_vec();
140 salted_password.extend_from_slice(PASSWORD_SALT);
141
142 let hash = digest::digest(&digest::SHA256, &salted_password);
144
145 let mut key = [0u8; 32];
147 key[0..16].copy_from_slice(&hash.as_ref()[0..16]);
148
149 key[16..32].copy_from_slice(&hash.as_ref()[0..16]);
152
153 key
154}
155
156pub type EncryptionResult<T> = Result<T, String>;
162
163pub struct KeyManager;
168
169impl KeyManager {
170 pub fn generate_keypair() -> Keypair {
181 Keypair::new()
182 }
183
184 pub fn encrypt_with_password(private_key: &str, password: &str) -> EncryptionResult<String> {
209 let key = generate_encryption_key_simple(password);
210 encrypt_key(private_key, &key)
211 }
212
213 pub fn decrypt_with_password(encrypted_data: &str, password: &str) -> EncryptionResult<String> {
236 let key = generate_encryption_key_simple(password);
237 decrypt_key(encrypted_data, &key)
238 }
239
240 pub fn get_public_key(private_key: &str) -> EncryptionResult<String> {
250 use solana_sdk::signature::Keypair;
251
252 let keypair = Keypair::from_base58_string(private_key);
254
255 Ok(keypair.pubkey().to_string())
256 }
257
258 pub fn keypair_to_encrypted_json(keypair: &Keypair, password: &str) -> EncryptionResult<String> {
271 use serde_json::json;
272 use chrono::Utc;
273
274 let private_key = keypair.to_base58_string();
275 let public_key = keypair.pubkey().to_string();
276
277 let encrypted = Self::encrypt_with_password(&private_key, password)?;
278
279 let keystore = json!({
280 "encrypted_private_key": encrypted,
281 "public_key": public_key,
282 "encryption_type": "password_only",
283 "created_at": Utc::now().to_rfc3339(),
284 });
285
286 Ok(keystore.to_string())
287 }
288
289 pub fn keypair_from_encrypted_json(json_data: &str, password: &str) -> EncryptionResult<Keypair> {
300 use serde_json::Value;
301
302 let data: Value = serde_json::from_str(json_data)
303 .map_err(|_| "Invalid JSON format")?;
304
305 let encrypted = data["encrypted_private_key"]
306 .as_str()
307 .ok_or("Missing encrypted_private_key field")?;
308
309 let private_key_str = Self::decrypt_with_password(encrypted, password)?;
310
311 let keypair = Keypair::from_base58_string(&private_key_str);
313
314 Ok(keypair)
315 }
316}
317
318#[cfg(feature = "2fa")]
327#[allow(dead_code)]
331fn derive_totp_secret_from_password(password: &str, account: &str, issuer: &str) -> Result<String, String> {
332 use ring::pbkdf2;
333 use data_encoding::BASE32_NOPAD;
334 use std::num::NonZeroU32;
335
336 let salt = format!("sol-safekey-totp-{}-{}", issuer, account);
337 let iterations = NonZeroU32::new(100_000)
338 .ok_or("Invalid iteration count")?;
339
340 let mut secret = [0u8; 20]; pbkdf2::derive(
342 pbkdf2::PBKDF2_HMAC_SHA256,
343 iterations,
344 salt.as_bytes(),
345 password.as_bytes(),
346 &mut secret,
347 );
348
349 Ok(BASE32_NOPAD.encode(&secret))
350}
351
352#[cfg(feature = "2fa")]
353pub fn derive_totp_secret_from_hardware_and_password(
357 hardware_fingerprint: &str,
358 master_password: &str,
359 account: &str,
360 issuer: &str,
361) -> Result<String, String> {
362 use ring::pbkdf2;
363 use data_encoding::BASE32_NOPAD;
364 use std::num::NonZeroU32;
365
366 let key_material = format!("{}::{}", hardware_fingerprint, master_password);
367 let salt = format!("sol-safekey-2fa-{}-{}", issuer, account);
368 let iterations = NonZeroU32::new(100_000)
369 .ok_or("Invalid iteration count")?;
370
371 let mut secret = [0u8; 20];
372 pbkdf2::derive(
373 pbkdf2::PBKDF2_HMAC_SHA256,
374 iterations,
375 salt.as_bytes(),
376 key_material.as_bytes(),
377 &mut secret,
378 );
379
380 Ok(BASE32_NOPAD.encode(&secret))
381}
382
383#[cfg(feature = "2fa")]
384fn verify_current_totp_code(totp_secret: &str, current_code: &str) -> Result<(), String> {
386 use crate::totp::{TOTPConfig, TOTPManager};
387
388 let config = TOTPConfig {
389 secret: totp_secret.to_string(),
390 account: "wallet".to_string(),
391 issuer: "Sol-SafeKey".to_string(),
392 algorithm: "SHA1".to_string(),
393 digits: 6,
394 step: 30,
395 };
396
397 let totp_manager = TOTPManager::new(config);
398
399 match totp_manager.verify_code(current_code) {
400 Ok(true) => Ok(()),
401 Ok(false) => Err("验证失败,请检查主密码、安全问题答案或2FA验证码".to_string()),
402 Err(e) => Err(format!("验证失败: {}", e)),
403 }
404}
405
406#[cfg(feature = "2fa")]
411pub fn generate_triple_factor_key(
415 hardware_fingerprint: &str,
416 master_password: &str,
417 security_answer: &str,
418) -> [u8; 32] {
419 use ring::pbkdf2;
420 use std::num::NonZeroU32;
421
422 let key_material = format!(
423 "HW:{}|PASS:{}|QA:{}",
424 hardware_fingerprint,
425 master_password,
426 security_answer.trim().to_lowercase()
427 );
428
429 let salt = b"sol-safekey-triple-factor-v1";
430 let iterations = NonZeroU32::new(200_000).unwrap();
431
432 let mut key = [0u8; 32];
433 pbkdf2::derive(
434 pbkdf2::PBKDF2_HMAC_SHA256,
435 iterations,
436 salt,
437 key_material.as_bytes(),
438 &mut key,
439 );
440
441 key
442}
443
444#[cfg(feature = "2fa")]
445pub fn encrypt_with_triple_factor(
449 private_key: &str,
450 twofa_secret: &str,
451 hardware_fingerprint: &str,
452 master_password: &str,
453 question_index: usize,
454 security_answer: &str,
455) -> Result<String, String> {
456 use serde_json::json;
457
458 let encryption_key = generate_triple_factor_key(
459 hardware_fingerprint,
460 master_password,
461 security_answer,
462 );
463
464 let data_package = json!({
465 "private_key": private_key,
466 "twofa_secret": twofa_secret,
467 "question_index": question_index,
468 "version": "triple_factor_v1",
469 "created_at": std::time::SystemTime::now()
470 .duration_since(std::time::UNIX_EPOCH)
471 .unwrap()
472 .as_secs()
473 });
474
475 let package_str = data_package.to_string();
476 let encrypted = encrypt_key(&package_str, &encryption_key)?;
477
478 Ok(encrypted)
479}
480
481#[cfg(feature = "2fa")]
482pub fn decrypt_with_triple_factor_and_2fa(
486 encrypted_data: &str,
487 hardware_fingerprint: &str,
488 master_password: &str,
489 security_answer: &str,
490 twofa_code: &str,
491) -> Result<(String, String, usize), String> {
492 let decryption_key = generate_triple_factor_key(
493 hardware_fingerprint,
494 master_password,
495 security_answer,
496 );
497
498 let decrypted = decrypt_key(encrypted_data, &decryption_key)
499 .map_err(|_| "解密失败,请检查主密码、安全问题答案是否正确")?;
500
501 let data: serde_json::Value = serde_json::from_str(&decrypted)
502 .map_err(|_| "解密失败,请检查主密码、安全问题答案是否正确")?;
503
504 let private_key = data["private_key"]
505 .as_str()
506 .ok_or("缺少私钥数据")?
507 .to_string();
508
509 let twofa_secret = data["twofa_secret"]
510 .as_str()
511 .ok_or("缺少2FA密钥数据")?
512 .to_string();
513
514 let question_index = data["question_index"]
515 .as_u64()
516 .ok_or("缺少安全问题索引")? as usize;
517
518 verify_current_totp_code(&twofa_secret, twofa_code)?;
520
521 Ok((private_key, twofa_secret, question_index))
522}
523
524#[cfg(test)]
529mod tests {
530 use super::*;
531
532 #[test]
533 fn test_generate_keypair() {
534 let keypair = KeyManager::generate_keypair();
535 assert_eq!(keypair.to_bytes().len(), 64);
536 }
537
538 #[test]
539 fn test_encrypt_decrypt_with_password() {
540 let keypair = KeyManager::generate_keypair();
541 let private_key = keypair.to_base58_string();
542 let password = "test_password_123";
543
544 let encrypted = KeyManager::encrypt_with_password(&private_key, password).unwrap();
545 let decrypted = KeyManager::decrypt_with_password(&encrypted, password).unwrap();
546
547 assert_eq!(private_key, decrypted);
548 }
549
550 #[test]
551 fn test_get_public_key() {
552 let keypair = KeyManager::generate_keypair();
553 let private_key = keypair.to_base58_string();
554 let expected_pubkey = keypair.pubkey().to_string();
555
556 let pubkey = KeyManager::get_public_key(&private_key).unwrap();
557 assert_eq!(pubkey, expected_pubkey);
558 }
559
560 #[test]
561 fn test_keystore_json_round_trip() {
562 let keypair = KeyManager::generate_keypair();
563 let password = "secure_password";
564
565 let json = KeyManager::keypair_to_encrypted_json(&keypair, password).unwrap();
566 let restored_keypair = KeyManager::keypair_from_encrypted_json(&json, password).unwrap();
567
568 assert_eq!(keypair.to_bytes(), restored_keypair.to_bytes());
569 }
570
571 #[test]
572 fn test_wrong_password_fails() {
573 let keypair = KeyManager::generate_keypair();
574 let private_key = keypair.to_base58_string();
575
576 let encrypted = KeyManager::encrypt_with_password(&private_key, "correct").unwrap();
577 let result = KeyManager::decrypt_with_password(&encrypted, "wrong");
578
579 assert!(result.is_err());
580 }
581}