Check pubkey

This commit is contained in:
Pascal Engélibert 2020-12-08 19:53:30 +01:00
parent bd632e3ed1
commit 7962df9ae6
6 changed files with 85 additions and 41 deletions

7
Cargo.lock generated
View File

@ -113,6 +113,12 @@ dependencies = [
"byte-tools", "byte-tools",
] ]
[[package]]
name = "bs58"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
[[package]] [[package]]
name = "buf_redux" name = "buf_redux"
version = "0.8.4" version = "0.8.4"
@ -436,6 +442,7 @@ name = "gmarche"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bincode", "bincode",
"bs58",
"dirs", "dirs",
"handlebars", "handlebars",
"hex", "hex",

View File

@ -6,6 +6,7 @@ edition = "2018"
[dependencies] [dependencies]
bincode = "1.3.1" bincode = "1.3.1"
bs58 = "0.4.0"
dirs = "3.0.1" dirs = "3.0.1"
handlebars = "3.5.1" handlebars = "3.5.1"
hex = "0.4.2" hex = "0.4.2"

View File

@ -6,6 +6,7 @@ mod db;
mod server; mod server;
mod static_files; mod static_files;
mod templates; mod templates;
mod utils;
use structopt::StructOpt; use structopt::StructOpt;

View File

@ -1,4 +1,4 @@
use super::{cli, config, db, static_files, templates}; use super::{cli, config, db, static_files, templates, utils::*};
use handlebars::to_json; use handlebars::to_json;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -118,21 +118,28 @@ pub async fn start_server(
.and(warp::get()) .and(warp::get())
.and(warp::fs::dir(opt.dir.0.join(static_files::STATIC_DIR))); .and(warp::fs::dir(opt.dir.0.join(static_files::STATIC_DIR)));
let handle_new_ad = { let handle_new_ad =
let handle_index = handle_index.clone(); {
let dbs = dbs.clone(); let handle_index = handle_index.clone();
let cache_ads = cache_ads.clone(); let dbs = dbs.clone();
move |query: NewAdQuery| { let cache_ads = cache_ads.clone();
let mut hasher = Sha512Trunc256::new(); move |query: NewAdQuery| {
hasher.update(query.psw); let mut hasher = Sha512Trunc256::new();
dbs.ads hasher.update(query.psw);
dbs.ads
.insert( .insert(
AdId::random(), AdId::random(),
bincode::serialize(&Ad { bincode::serialize(&Ad {
author: query.author, author: query.author,
password: hasher.finalize()[..].try_into().unwrap(), password: hasher.finalize()[..].try_into().unwrap(),
price: query.price, price: query.price,
pubkey: (!query.pubkey.is_empty()).then_some(query.pubkey), pubkey: (!query.pubkey.is_empty()).then_some(match format_pubkey(&query.pubkey) {
Ok(pubkey) => pubkey,
Err(e) => return handle_index(&[ErrorTemplate{text: match e {
PubkeyDecodeError::BadChecksum => "La somme de contrôle de la clé publique est incorrecte.",
PubkeyDecodeError::BadFormat => "Le format de la clé publique est incorrect.",
}}])
}),
quantity: query.quantity, quantity: query.quantity,
time: 0, time: 0,
title: query.title, title: query.title,
@ -140,24 +147,24 @@ pub async fn start_server(
.unwrap(), .unwrap(),
) )
.unwrap(); .unwrap();
dbs.ads.flush().unwrap(); dbs.ads.flush().unwrap();
let mut cache_ads = cache_ads.write().unwrap(); let mut cache_ads = cache_ads.write().unwrap();
*cache_ads = to_json( *cache_ads = to_json(
dbs.ads dbs.ads
.iter() .iter()
.filter_map(|x| { .filter_map(|x| {
let (ad_id, ad) = x.ok()?; let (ad_id, ad) = x.ok()?;
Some(AdWithId { Some(AdWithId {
id: hex::encode(ad_id.as_ref()), id: hex::encode(ad_id.as_ref()),
ad: bincode::deserialize::<Ad>(&ad).ok()?, ad: bincode::deserialize::<Ad>(&ad).ok()?,
})
}) })
}) .collect::<Vec<AdWithId>>(),
.collect::<Vec<AdWithId>>(), );
); drop(cache_ads);
drop(cache_ads); handle_index(&[])
handle_index(&[]) }
} };
};
let handle_rm_ad = { let handle_rm_ad = {
let handle_index = handle_index.clone(); let handle_index = handle_index.clone();
@ -259,14 +266,10 @@ pub async fn start_server(
let handle_admin_login = handle_admin_login.clone(); let handle_admin_login = handle_admin_login.clone();
let config = config.clone(); let config = config.clone();
move |psw, query| { move |psw, query| {
dbg!();
if config.admin_passwords.contains(&psw) { if config.admin_passwords.contains(&psw) {
dbg!();
let AdminQuery::RmAdQuery(query) = query; let AdminQuery::RmAdQuery(query) = query;
dbg!();
handle_admin_rm_ad(query) handle_admin_rm_ad(query)
} else { } else {
dbg!();
handle_admin_login(&[ErrorTemplate { handle_admin_login(&[ErrorTemplate {
text: "Mot de passe administrateur invalide", text: "Mot de passe administrateur invalide",
}]) }])
@ -278,12 +281,9 @@ pub async fn start_server(
let handle_admin_login = handle_admin_login.clone(); let handle_admin_login = handle_admin_login.clone();
let config = config.clone(); let config = config.clone();
move |psw| { move |psw| {
dbg!();
if config.admin_passwords.contains(&psw) { if config.admin_passwords.contains(&psw) {
dbg!();
handle_admin(&[]) handle_admin(&[])
} else { } else {
dbg!();
handle_admin_login(&[ErrorTemplate { handle_admin_login(&[ErrorTemplate {
text: "Mot de passe administrateur invalide", text: "Mot de passe administrateur invalide",
}]) }])
@ -292,10 +292,7 @@ pub async fn start_server(
})) }))
.or(warp::path::end().map({ .or(warp::path::end().map({
let handle_admin_login = handle_admin_login.clone(); let handle_admin_login = handle_admin_login.clone();
move || { move || handle_admin_login(&[])
dbg!();
handle_admin_login(&[])
}
})), })),
) )
.or(warp::path("login").and(warp::path::end()).and( .or(warp::path("login").and(warp::path::end()).and(
@ -304,9 +301,7 @@ pub async fn start_server(
.or(warp::body::form::<AdminLoginQuery>().map({ .or(warp::body::form::<AdminLoginQuery>().map({
let config = config.clone(); let config = config.clone();
move |query: AdminLoginQuery| { move |query: AdminLoginQuery| {
dbg!();
if config.admin_passwords.contains(&query.psw) { if config.admin_passwords.contains(&query.psw) {
dbg!();
warp::reply::with_header( warp::reply::with_header(
warp::redirect(warp::http::Uri::from_static("/admin")), warp::redirect(warp::http::Uri::from_static("/admin")),
"Set-Cookie", "Set-Cookie",
@ -317,7 +312,6 @@ pub async fn start_server(
) )
.into_response() .into_response()
} else { } else {
dbg!();
handle_admin_login(&[ErrorTemplate { handle_admin_login(&[ErrorTemplate {
text: "Mot de passe administrateur invalide", text: "Mot de passe administrateur invalide",
}]) }])

37
src/utils.rs Normal file
View File

@ -0,0 +1,37 @@
use sha2::{Digest, Sha256};
pub enum PubkeyDecodeError {
BadChecksum,
BadFormat,
}
/// Decode pubkey from base 58
/// Verify checksum if provided
/// Accepts any checksum length >=3
pub fn format_pubkey(raw: &str) -> Result<String, PubkeyDecodeError> {
let mut iter = raw.splitn(2, ':');
let mut pubkey = [0u8; 32];
bs58::decode(iter.next().ok_or(PubkeyDecodeError::BadFormat)?)
.into(&mut pubkey)
.map_err(|_| PubkeyDecodeError::BadFormat)?;
let mut hasher1 = Sha256::new();
hasher1.update(&pubkey.as_ref()[..32]);
let mut hasher2 = Sha256::new();
hasher2.update(hasher1.finalize());
let checksum = bs58::encode(hasher2.finalize()).into_string();
if let Some(given_checksum) = iter.next() {
if given_checksum.len() < 3 {
return Err(PubkeyDecodeError::BadFormat);
}
if !checksum.starts_with(given_checksum) {
return Err(PubkeyDecodeError::BadChecksum);
}
}
Ok(format!(
"{}:{}",
bs58::encode(pubkey).into_string(),
&checksum[..3]
))
}

View File

@ -48,6 +48,10 @@ h1, h2, h3, h4 {
width: 100%; width: 100%;
} }
fieldset {
border: 1px dashed grey;
}
.center { .center {
padding: 4px; padding: 4px;
} }