summaryrefslogtreecommitdiffstats
path: root/src/bin/client/database.rs
diff options
context:
space:
mode:
authorsalmonik <raisersoft@proton.me>2026-03-01 14:39:56 +0100
committersalmonik <raisersoft@proton.me>2026-03-01 14:39:56 +0100
commit7ca1b5aeacd9633e5a3dca9f7596975dbc686508 (patch)
tree62de1c6d904e4c2dc1cf60539a16ed1dbb07458b /src/bin/client/database.rs
parentRevert "folder restructuring" (diff)
downloadzagan-bet-7ca1b5aeacd9633e5a3dca9f7596975dbc686508.tar.gz
zagan-bet-7ca1b5aeacd9633e5a3dca9f7596975dbc686508.zip
slowly preparing for actual casino
Diffstat (limited to 'src/bin/client/database.rs')
-rw-r--r--src/bin/client/database.rs54
1 files changed, 9 insertions, 45 deletions
diff --git a/src/bin/client/database.rs b/src/bin/client/database.rs
index 03a6c45..da069a7 100644
--- a/src/bin/client/database.rs
+++ b/src/bin/client/database.rs
@@ -1,10 +1,4 @@
1use rusqlite::Connection; 1use rusqlite::Connection;
2use aes_gcm::{Aes256Gcm, Key, Nonce};
3use aes_gcm::aead::{Aead, KeyInit};
4use pbkdf2::pbkdf2;
5use hmac::Hmac;
6use sha2::Sha256;
7use rand::Rng;
8 2
9pub fn init_db() -> Connection { 3pub fn init_db() -> Connection {
10 let conn = Connection::open("client.db").unwrap(); 4 let conn = Connection::open("client.db").unwrap();
@@ -19,7 +13,7 @@ pub fn init_db() -> Connection {
19 "CREATE TABLE IF NOT EXISTS credentials ( 13 "CREATE TABLE IF NOT EXISTS credentials (
20 host TEXT PRIMARY KEY, 14 host TEXT PRIMARY KEY,
21 username TEXT NOT NULL, 15 username TEXT NOT NULL,
22 encrypted_password BLOB NOT NULL 16 password TEXT NOT NULL
23 )", 17 )",
24 [], 18 [],
25 ).unwrap(); 19 ).unwrap();
@@ -43,52 +37,22 @@ pub fn save_host(conn: &Connection, host: &str) {
43 ).unwrap(); 37 ).unwrap();
44} 38}
45 39
46pub fn save_credentials(conn: &Connection, host: &str, username: &str, password: &str) -> Result<(), aes_gcm::Error> { 40pub fn save_credentials(conn: &Connection, host: &str, username: &str, password: &str) -> Result<(), Box<dyn std::error::Error>> {
47 let encrypted = encrypt_password(password)?;
48 conn.execute( 41 conn.execute(
49 "INSERT OR REPLACE INTO credentials (host, username, encrypted_password) VALUES (?1, ?2, ?3)", 42 "INSERT OR REPLACE INTO credentials (host, username, password) VALUES (?1, ?2, ?3)",
50 (host, username, &encrypted), 43 (host, username, password),
51 ).unwrap(); 44 )?;
52 Ok(()) 45 Ok(())
53} 46}
54 47
55pub fn get_credentials(conn: &Connection, host: &str) -> Option<(String, String)> { 48pub fn get_credentials(conn: &Connection, host: &str) -> Option<(String, String)> {
56 let mut stmt = conn.prepare("SELECT username, encrypted_password FROM credentials WHERE host = ?1").unwrap(); 49 let mut stmt = conn.prepare("SELECT username, password FROM credentials WHERE host = ?1").unwrap();
57 let mut rows = stmt.query([host]).unwrap(); 50 let mut rows = stmt.query([host]).unwrap();
58 if let Ok(Some(row)) = rows.next() { 51 if let Ok(Some(row)) = rows.next() {
59 let username: String = row.get(0).unwrap(); 52 let username: String = row.get(0).unwrap();
60 let encrypted: Vec<u8> = row.get(1).unwrap(); 53 let password: String = row.get(1).unwrap();
61 decrypt_password(&encrypted).map(|password| (username, password)) 54 Some((username, password))
62 } else { 55 } else {
63 None 56 None
64 } 57 }
65} 58} \ No newline at end of file
66
67fn derive_key() -> Key<Aes256Gcm> {
68 let mut key = [0u8; 32];
69 let salt = b"client_salt"; // Fixed salt for simplicity
70 pbkdf2::<Hmac<Sha256>>(b"client_key", salt, 10000, &mut key).expect("error deriving key");
71 key.into()
72}
73
74fn encrypt_password(password: &str) -> Result<Vec<u8>, aes_gcm::Error> {
75 let key = derive_key();
76 let cipher = Aes256Gcm::new(&key);
77 let mut nonce_bytes = [0u8; 12];
78 rand::thread_rng().fill(&mut nonce_bytes);
79 let nonce = Nonce::from_slice(&nonce_bytes);
80 let ciphertext = cipher.encrypt(nonce, password.as_bytes())?;
81 let mut result = nonce_bytes.to_vec();
82 result.extend(ciphertext);
83 Ok(result)
84}
85
86fn decrypt_password(encrypted: &[u8]) -> Option<String> {
87 if encrypted.len() < 12 {
88 return None;
89 }
90 let key = derive_key();
91 let cipher = Aes256Gcm::new(&key);
92 let nonce = Nonce::from_slice(&encrypted[..12]);
93 cipher.decrypt(nonce, &encrypted[12..]).ok().and_then(|plaintext| String::from_utf8(plaintext).ok())
94}