new-idea
Avril 4 years ago
parent cda9470f86
commit d72a52a988
Signed by: flanchan
GPG Key ID: 284488987C31F630

7
Cargo.lock generated

@ -1,5 +1,11 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "ad-hoc-iter"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90a8dd76beceb5313687262230fcbaaf8d4e25c37541350cf0932e9adb8309c8"
[[package]]
name = "addr2line"
version = "0.14.1"
@ -1902,6 +1908,7 @@ dependencies = [
name = "yuurei"
version = "0.1.0"
dependencies = [
"ad-hoc-iter",
"base64 0.13.0",
"cfg-if 1.0.0",
"chrono",

@ -11,6 +11,7 @@ default = ["nightly"]
nightly = ["smallvec/const_generics"]
[dependencies]
ad-hoc-iter = "0.2.3"
base64 = "0.13.0"
cfg-if = "1.0.0"
chrono = {version = "0.4", features=["serde"]}

@ -233,7 +233,7 @@ pub mod formats
{
type Error = std::convert::Infallible;
#[inline] fn validate(_: &str) -> Result<(), Self::Error>
#[inline(always)] fn validate(_: &str) -> Result<(), Self::Error>
{
Ok(())
}
@ -244,6 +244,9 @@ pub mod formats
pub struct BothFormat<T, U = AnyFormat>(PhantomData<(T, U)>)
where T: FormatSpec, U: FormatSpec;
/// A formatting error coming from an instance of `BothFormat<T,U>`.
///
/// This type's `T` and `U` correspond to the `Error` type of the `BothFormat`'s `T` and `U`.
#[derive(Debug)]
pub enum MultiFormatError<T,U>
{
@ -259,7 +262,7 @@ pub mod formats
{
type Error = MultiFormatError<T::Error, U::Error>;
fn validate(s: &str) -> Result<(), Self::Error> {
#[inline] fn validate(s: &str) -> Result<(), Self::Error> {
T::validate(s).map_err(MultiFormatError::First)?;
U::validate(s).map_err(MultiFormatError::Second)?;
Ok(())

@ -9,6 +9,7 @@
#[macro_use] extern crate log;
#[macro_use] extern crate mopa;
#[macro_use] extern crate cfg_if;
#[macro_use] extern crate ad_hoc_iter;
#[allow(unused_imports)]
use std::convert::{TryFrom, TryInto};

@ -1,10 +1,98 @@
use super::*;
use std::collections::HashMap;
use cryptohelpers::{
rsa::{
RsaPublicKey,
Signature,
},
sha256::{self, Sha256Hash},
};
use post::Post;
#[derive(Debug, Hash)]
pub struct User;
id_type!(UserID; "A unique user iD");
/// The salt added to to the user ID hash to be signed by the user's private key.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UserSalt([u8; 16]);
impl UserSalt
{
/// Generate a new random salt.
pub fn generate() -> Self
{
let mut ar = [0u8; 16];
getrandom::getrandom(&mut ar[..]).expect("rng fatal");
Self(ar)
}
}
impl UserID
{
/// SHA256 hash this ID with a salt
pub fn hash_with_salt(&self, salt: &UserSalt) -> Sha256Hash
{
sha256::compute_slice_iter(iter![&self.0.as_bytes()[..], &salt.0[..]])
}
/// Generate a new salt and then return that salt and this ID hashed with that new salt.
///
/// This salt should be
pub fn generate_hash(&self) -> (UserSalt, Sha256Hash)
{
let salt = UserSalt::generate();
let hash = self.hash_with_salt(&salt);
(salt, hash)
}
}
/// A user identifier.
///
/// Contains the user's unique ID, their public key(s), and a valid signature of the sha256 hash of the user's ID + a random salt.
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct User
{
/// The user's unique ID.
id: UserID,
/// A optional set of identifiers given by the user. The user must be trusted to set/edit this value.
ident: post::Ident,
/// The public keys associated with this user.
///
/// # Trust
/// Each public key must have a corresponding signature in its complemental entry in `id_sig` to be considered trusted.
/// A user with no trusted public keys can be anyone or multiple people. This is not *disallowed* usually but should be discouraged.
///
/// Users are only considered trusted if they have at least one trusted public key.
pubkey: Vec<RsaPublicKey>,
/// This vector contains the complemental signature (and salt used with `id` to produce the signed hash) to the public keys in `pubkey`. Each element of `pubkey` must have a complemental element in this vector.
///
/// # Trusted public keys
/// `None` values for this are signatures that have not yet been produces for a given salt, and do not count as complete. Public keys in `pubkey` that do not have a corresponding `Some` signature value in this field should not be trusted.
id_sig: Vec<(UserSalt, Option<Signature>)>,
}
impl User
{
/// Is this user a trusted user?
///
/// I.e. Does this user have at least one trusted public key (they have produced a valid signature specified in `id_sig`).
pub fn is_trusted(&self) -> eyre::Result<bool>
{
for (key, (salt, sig)) in self.pubkey.iter().zip(self.id_sig.iter())
{
if let Some(sig) = sig {
let hash = self.id.hash_with_salt(salt);
if sig.verify_slice(hash.as_ref(), key)
.wrap_err(eyre!("Failed to verify signature"))? {
return Ok(true);
}
}
}
Ok(false)
}
}
#[derive(Debug)]
pub struct State

Loading…
Cancel
Save