~starkingdoms/starkingdoms

ref: eabc84c8e290163d25ea21f153ae811bf09fc23a starkingdoms/crates/common/src/save/authentication.rs -rw-r--r-- 1.3 KiB
eabc84c8 — core feat: add basic save file authentication infrastructure 12 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
use base64::Engine;
use ed25519_dalek::{Signature, Verifier, VerifyingKey};
use serde::{Deserialize, Serialize};
use crate::save::error::SaveError;

#[derive(Serialize, Deserialize)]
pub struct SignedSavefile {
    pub authenticating_server: AuthenticatingServer,
    pub save_data: crate::save::Savefile,
    pub signature: Signature
}

#[derive(Serialize, Deserialize)]
pub struct AuthenticatingServer {
    pub server: String,
    pub server_build_id: String,
    pub server_public_key: VerifyingKey,
}

impl SignedSavefile {
    pub fn encoded_save_data(&self) -> Result<Vec<u8>, SaveError> {
        Ok(postcard::to_allocvec(&self.save_data)?)
    }
    pub fn is_valid(&self) -> Result<bool, SaveError> {
        let encoded_savefile = self.encoded_save_data()?;
        Ok(self.authenticating_server.server_public_key.verify(&encoded_savefile, &self.signature).is_ok())
    }
}

pub fn encode_public_key(public_key: &VerifyingKey) -> String {
    base64::engine::general_purpose::URL_SAFE.encode(public_key)
}
pub fn decode_public_key(public_key: &str) -> Result<VerifyingKey, SaveError> {
    let bytes = base64::engine::general_purpose::URL_SAFE.decode(public_key)?;
    let key: [u8; 32] = bytes.try_into().ok().ok_or(SaveError::InvalidKeyLength(public_key.len()))?;
    VerifyingKey::from_bytes(&key).ok().ok_or(SaveError::Ed25519Error)
}