M Cargo.lock => Cargo.lock +179 -3
@@ 373,6 373,15 @@ dependencies = [
]
[[package]]
+name = "atomic-polyfill"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
+dependencies = [
+ "critical-section",
+]
+
+[[package]]
name = "atomic-waker"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 466,6 475,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
+name = "base64ct"
+version = "1.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
+
+[[package]]
name = "bevy"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 1210,7 1225,7 @@ dependencies = [
"portable-atomic",
"portable-atomic-util",
"serde",
- "spin",
+ "spin 0.10.0",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-time 1.1.0",
@@ 1539,7 1554,7 @@ dependencies = [
"crossbeam-queue",
"derive_more",
"futures-lite",
- "heapless",
+ "heapless 0.9.2",
"pin-project",
]
@@ 2162,6 2177,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32b13ea120a812beba79e34316b3942a857c86ec1593cb34f27bb28272ce2cca"
[[package]]
+name = "const-oid"
+version = "0.9.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+
+[[package]]
name = "const_format"
version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 2475,6 2496,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f"
[[package]]
+name = "curve25519-dalek"
+version = "4.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
+dependencies = [
+ "cfg-if",
+ "cpufeatures 0.2.17",
+ "curve25519-dalek-derive",
+ "digest",
+ "fiat-crypto",
+ "rustc_version",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "curve25519-dalek-derive"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
+[[package]]
name = "darling"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 2516,6 2564,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8"
[[package]]
+name = "der"
+version = "0.7.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
+dependencies = [
+ "const-oid",
+ "zeroize",
+]
+
+[[package]]
name = "der-parser"
version = "10.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 2783,12 2841,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fdab65db9274e0168143841eb8f864a0a21f8b1b8d2ba6812bbe6024346e99e"
[[package]]
+name = "ed25519"
+version = "2.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
+dependencies = [
+ "pkcs8",
+ "serde",
+ "signature",
+]
+
+[[package]]
+name = "ed25519-dalek"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
+dependencies = [
+ "curve25519-dalek",
+ "ed25519",
+ "serde",
+ "sha2",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
+name = "embedded-io"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
+
+[[package]]
+name = "embedded-io"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
+
+[[package]]
name = "ena"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 2924,6 3019,12 @@ dependencies = [
]
[[package]]
+name = "fiat-crypto"
+version = "0.2.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
+
+[[package]]
name = "file-id"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 3465,6 3566,15 @@ dependencies = [
[[package]]
name = "hash32"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "hash32"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
@@ 3502,11 3612,25 @@ checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
[[package]]
name = "heapless"
+version = "0.7.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
+dependencies = [
+ "atomic-polyfill",
+ "hash32 0.2.1",
+ "rustc_version",
+ "serde",
+ "spin 0.9.8",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "heapless"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af2455f757db2b292a9b1768c4b70186d443bcb3b316252d6b540aec1cd89ed"
dependencies = [
- "hash32",
+ "hash32 0.3.1",
"portable-atomic",
"stable_deref_trait",
]
@@ 4931,6 5055,16 @@ dependencies = [
]
[[package]]
+name = "pkcs8"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
+dependencies = [
+ "der",
+ "spki",
+]
+
+[[package]]
name = "pkg-config"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 5030,6 5164,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
dependencies = [
"cobs",
+ "embedded-io 0.4.0",
+ "embedded-io 0.6.1",
+ "heapless 0.7.17",
"postcard-derive",
"serde",
]
@@ 5916,6 6053,15 @@ dependencies = [
]
[[package]]
+name = "signature"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
+dependencies = [
+ "rand_core 0.6.4",
+]
+
+[[package]]
name = "simba"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 6071,6 6217,15 @@ dependencies = [
[[package]]
name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
+name = "spin"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591"
@@ 6088,6 6243,16 @@ dependencies = [
]
[[package]]
+name = "spki"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
+dependencies = [
+ "base64ct",
+ "der",
+]
+
+[[package]]
name = "stable_deref_trait"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ 6132,6 6297,17 @@ dependencies = [
]
[[package]]
+name = "starkingdoms-common"
+version = "0.1.0"
+dependencies = [
+ "base64",
+ "ed25519-dalek",
+ "postcard",
+ "serde",
+ "thiserror 2.0.18",
+]
+
+[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
A crates/common/Cargo.toml => crates/common/Cargo.toml +11 -0
@@ 0,0 1,11 @@
+[package]
+name = "starkingdoms-common"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+serde = { version = "1", features = ["derive"] }
+postcard = { version = "1", features = ["alloc"] }
+ed25519-dalek = { version = "2", features = ["serde"] }
+base64 = { version = "0.22" }
+thiserror = "2"<
\ No newline at end of file
A crates/common/src/lib.rs => crates/common/src/lib.rs +16 -0
@@ 0,0 1,16 @@
+pub mod save;
+
+pub fn add(left: u64, right: u64) -> u64 {
+ left + right
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn it_works() {
+ let result = add(2, 2);
+ assert_eq!(result, 4);
+ }
+}
A crates/common/src/save/authentication.rs => crates/common/src/save/authentication.rs +37 -0
@@ 0,0 1,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)
+}<
\ No newline at end of file
A crates/common/src/save/error.rs => crates/common/src/save/error.rs +13 -0
@@ 0,0 1,13 @@
+use thiserror::Error;
+
+#[derive(Clone, Debug, Error)]
+pub enum SaveError {
+ #[error("postcard ser/de error: {0}")]
+ PostcardError(#[from] postcard::Error),
+ #[error("invalid base64: {0}")]
+ Base64(#[from] base64::DecodeError),
+ #[error("incorrect key length: should be 32, got {0}")]
+ InvalidKeyLength(usize),
+ #[error("ed25519 error")]
+ Ed25519Error
+}<
\ No newline at end of file
A crates/common/src/save/mod.rs => crates/common/src/save/mod.rs +26 -0
@@ 0,0 1,26 @@
+use serde::{Deserialize, Serialize};
+
+pub mod authentication;
+pub mod v1;
+pub mod error;
+
+#[derive(Serialize, Deserialize)]
+pub enum Savefile {
+ V1(v1::Savefile),
+}
+
+pub trait SaveContainer {
+ type LatestFormat;
+
+ fn as_latest(&self) -> &Self::LatestFormat;
+}
+
+impl SaveContainer for Savefile {
+ type LatestFormat = v1::Savefile;
+
+ fn as_latest(&self) -> &Self::LatestFormat {
+ match self {
+ Savefile::V1(s) => s,
+ }
+ }
+}<
\ No newline at end of file
A crates/common/src/save/v1.rs => crates/common/src/save/v1.rs +6 -0
@@ 0,0 1,6 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize)]
+pub struct Savefile {
+
+}<
\ No newline at end of file