87 lines
1.9 KiB
Rust
87 lines
1.9 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use sha2::{Digest, Sha256};
|
|
use std::convert::{TryFrom, TryInto};
|
|
|
|
pub type PasswordHash = [u8; 32];
|
|
|
|
#[derive(Clone, Debug, Hash, Eq, PartialEq, Serialize)]
|
|
pub struct AdId([u8; 16]);
|
|
|
|
impl AdId {
|
|
pub fn random() -> Self {
|
|
Self(rand::random())
|
|
}
|
|
}
|
|
|
|
impl AsRef<[u8]> for AdId {
|
|
fn as_ref(&self) -> &[u8] {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl TryFrom<&[u8]> for AdId {
|
|
type Error = std::array::TryFromSliceError;
|
|
|
|
fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
|
|
Ok(Self(v.try_into()?))
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
pub struct Ad {
|
|
pub author: String,
|
|
pub password: PasswordHash,
|
|
pub price: String,
|
|
pub pubkey: Option<String>,
|
|
pub quantity: String,
|
|
pub time: u64,
|
|
pub title: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize)]
|
|
pub struct AdWithId {
|
|
pub id: String,
|
|
pub ad: Ad,
|
|
pub selected: bool,
|
|
}
|
|
|
|
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 raw_pubkey = iter.next().ok_or(PubkeyDecodeError::BadFormat)?;
|
|
if raw_pubkey.len() < 43 || raw_pubkey.len() > 44 {
|
|
return Err(PubkeyDecodeError::BadFormat);
|
|
}
|
|
let mut pubkey = [0u8; 32];
|
|
bs58::decode(raw_pubkey)
|
|
.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]
|
|
))
|
|
}
|