From 3533d752c5b21f87ef7f10b5a1ecce2fe70247ec Mon Sep 17 00:00:00 2001 From: Avril Date: Thu, 17 Sep 2020 12:55:30 +0100 Subject: [PATCH] kana hash tripcode --- Cargo.lock | 46 ++++++++++++++++++++- Cargo.toml | 2 + src/config.rs | 8 ++++ src/main.rs | 1 + src/tripcode.rs | 108 +++++++++++++++++++++++++++++++++++++++++++++--- src/web/mod.rs | 5 +++ 6 files changed, 163 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 01da0fe..bb70124 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -240,7 +240,7 @@ checksum = "825b8339215ceae0288ed0384ebe63fe717f5b0c77b102ff3c9f59aefeed9106" dependencies = [ "crc", "getrandom", - "hex-literal", + "hex-literal 0.3.1", "hmac", "libc", "openssl", @@ -515,12 +515,31 @@ dependencies = [ "libc", ] +[[package]] +name = "hex-literal" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "961de220ec9a91af2e1e5bd80d02109155695e516771762381ef8581317066e0" +dependencies = [ + "hex-literal-impl", + "proc-macro-hack", +] + [[package]] name = "hex-literal" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5af1f635ef1bc545d78392b136bfe1c9809e029023c84a3638a864a10b8819c8" +[[package]] +name = "hex-literal-impl" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "853f769599eb31de176303197b7ba4973299c38c7a7604a6bc88c3eef05b9b46" +dependencies = [ + "proc-macro-hack", +] + [[package]] name = "hmac" version = "0.9.0" @@ -632,6 +651,20 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "khash" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "592c0325561e878d43491e8ef0fed4ecb2b84ddbb1d668405914c50400ba1b9e" +dependencies = [ + "crc", + "getrandom", + "hex-literal 0.2.1", + "libc", + "malloc-array", + "sha2", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -665,6 +698,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "malloc-array" +version = "1.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f994770c7bb3f8f7db7c4160665fc8814c8c705c10ae59a3d7354f0b8838f5c" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.3.3" @@ -1430,7 +1472,9 @@ dependencies = [ "difference", "futures", "generational-arena", + "hex-literal 0.3.1", "hyper", + "khash", "libc", "log", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index 850bb9e..972c803 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,8 @@ pretty_env_logger = "0.4.0" log = "0.4.11" pcre = "0.2.3" generational-arena = "0.2.8" +khash = {version = "2.0.0", default-features=false} +hex-literal = "0.3.1" [build-dependencies] rustc_version = "0.2" diff --git a/src/config.rs b/src/config.rs index bff43a6..4acb41a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -42,6 +42,9 @@ pub fn get_or_default() -> Cow<'static, Config> } } +/// A salt for secure tripcode +pub type Salt = [u8; khash::salt::SIZE]; + /// Config for this run #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Config @@ -63,6 +66,9 @@ pub struct Config pub req_timeout_local: Option, /// The timeout for *all* routing dispatchs pub req_timeout_global: Option, + + /// The salt for secure tripcode + pub tripcode_salt: Salt, } impl Default for Config @@ -80,6 +86,8 @@ impl Default for Config req_timeout_local: Some(time::Duration::from_millis(500)), req_timeout_global: Some(time::Duration::from_secs(1)), + + tripcode_salt: hex!("770d64c6bf46da1a812d067fd224bbe671b7607d3274265abfcdda45c44ca3c1"), } } } diff --git a/src/main.rs b/src/main.rs index 3f29fbc..fc6c0c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,7 @@ use futures::{ FutureExt as _, prelude::*, }; +use hex_literal::hex; mod ext; use ext::*; diff --git a/src/tripcode.rs b/src/tripcode.rs index 2f9536a..0a25488 100644 --- a/src/tripcode.rs +++ b/src/tripcode.rs @@ -1,13 +1,109 @@ //! Tripcode. TODO: Use kana-hash use super::*; +use khash::{ + ctx::{ + self, + Algorithm, + }, + salt, +}; +use std::{ + fmt, + error, +}; +#[derive(Debug)] +pub struct Error(khash::error::Error); -///TODO: A kana-hash tripcode +impl From for Error +{ + #[inline] fn from(from: khash::error::Error) -> Self + { + Self(from) + } +} + +impl fmt::Display for Error +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + write!(f, "failed to compute tripcode") + } +} + + +impl error::Error for Error +{ + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + Some(&self.0) + } +} + +///A kana-hash or special tripcode #[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] #[derive(Serialize, Deserialize)] -pub struct Tripcode;/* +pub enum Tripcode +{ + /// A secure tripcode computed with the user set configured salt + Secure(String), + /// A normal tripcode computed with the default embedded salt + Normal(String), + /// A special tripcode with a pre-set string + Special(String), +} + +impl Tripcode { - Secure(i32), - Normal(i32), - Special(&'static str), -}*/ + /// Generate a new normal tripcode + pub fn new_normal(from: impl AsRef<[u8]>) -> Result + { + Ok(Self::Normal(khash::generate(&ctx::Context::new(Algorithm::Sha256Truncated, salt::Salt::internal()), from)?)) + } + /// Generate a new `secure' tripcode. + /// + /// # Panics + /// If global config has not been set yet. + pub fn new_secure(from: impl AsRef<[u8]>) -> Result + { + Ok(Self::Secure(khash::generate(&ctx::Context::new(Algorithm::Sha256Truncated, salt::Salt::fixed(config::get().tripcode_salt)), from)?)) + } + + /// Get the internal string representing the tripcode. + /// + /// # Notes + /// This does not include the prefixes. + pub fn as_str(&self) -> &str + { + match self { + Self::Secure(s) | Self::Normal(s) | Self::Special(s) => s.as_str() + } + } + + /// Consume the instance returning the inner string. + /// + /// # Notes + /// This does not include the prefixes. + pub fn into_inner(self) -> String + { + match self { + Self::Secure(s) | Self::Normal(s) | Self::Special(s) => s + } + } +} + +impl fmt::Display for Tripcode +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + match self { + Self::Secure(sec) => write!(f, "!!{}", sec), + Self::Normal(nor) => write!(f, "!{}", nor), + Self::Special(spec) => write!(f, "{}", spec), + } + } +} + + + + + diff --git a/src/web/mod.rs b/src/web/mod.rs index d6c318b..f6b0549 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -77,6 +77,7 @@ impl Handle } } +/// Contains all web-server state #[derive(Debug)] pub struct State { @@ -86,6 +87,10 @@ pub struct State impl State { + /// Create a new state with this specific config instance. + /// + /// # Notes + /// You'll almost always want to use the *global* config instance, in which case use `default()` to create this. pub fn new(config: config::Config) -> Self { Self{