forked from alemi/upub
chore(httpsign): moved httpsign into standalone crate
This commit is contained in:
parent
5ea4940f58
commit
e7e9584783
4 changed files with 50 additions and 5 deletions
|
@ -7,7 +7,6 @@ pub mod inbox;
|
|||
pub mod init;
|
||||
pub mod outbox;
|
||||
pub mod auth;
|
||||
pub mod httpsign;
|
||||
pub mod normalizer;
|
||||
pub mod side_effects;
|
||||
|
||||
|
|
26
utils/httpsign/Cargo.toml
Normal file
26
utils/httpsign/Cargo.toml
Normal file
|
@ -0,0 +1,26 @@
|
|||
[package]
|
||||
name = "httpsign"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = [ "alemi <me@alemi.dev>" ]
|
||||
description = "fediverse-friendly implementation of http signaures in rust"
|
||||
license = "MIT"
|
||||
#keywords = ["html", "markdown", "parser"]
|
||||
repository = "https://git.alemi.dev/upub.git"
|
||||
readme = "README.md"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
thiserror = "1"
|
||||
tracing = "0.1"
|
||||
base64 = "0.22"
|
||||
openssl = "0.10" # TODO handle pubkeys with a smaller crate
|
||||
axum = { version = "0.7", optional = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
axum = ["dep:axum"]
|
0
utils/httpsign/README.md
Normal file
0
utils/httpsign/README.md
Normal file
|
@ -1,9 +1,25 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use axum::http::request::Parts;
|
||||
use base64::Engine;
|
||||
use openssl::{hash::MessageDigest, pkey::PKey, sign::Verifier};
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum HttpSignatureError {
|
||||
#[error("openssl error: {0:?}")]
|
||||
OpenSSL(#[from] openssl::error::ErrorStack),
|
||||
|
||||
#[error("invalid UTF8 in key: {0:?}")]
|
||||
UTF8(#[from] std::str::Utf8Error),
|
||||
|
||||
#[error("os I/O error: {0}")]
|
||||
IO(#[from] std::io::Error),
|
||||
|
||||
#[error("invalid base64: {0}")]
|
||||
Base64(#[from] base64::DecodeError),
|
||||
}
|
||||
|
||||
type Result<T> = std::result::Result<T, HttpSignatureError>;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct HttpSignature {
|
||||
pub key_id: String,
|
||||
|
@ -60,7 +76,8 @@ impl HttpSignature {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn build_from_parts(&mut self, parts: &Parts) -> &mut Self {
|
||||
#[cfg(feature = "axum")]
|
||||
pub fn build_from_parts(&mut self, parts: &axum::http::request::Parts) -> &mut Self {
|
||||
let mut out = Vec::new();
|
||||
for header in self.headers.iter() {
|
||||
match header.as_str() {
|
||||
|
@ -82,14 +99,14 @@ impl HttpSignature {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn verify(&self, key: &str) -> crate::Result<bool> {
|
||||
pub fn verify(&self, key: &str) -> Result<bool> {
|
||||
let pubkey = PKey::public_key_from_pem(key.as_bytes())?;
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &pubkey)?;
|
||||
let signature = base64::prelude::BASE64_STANDARD.decode(&self.signature)?;
|
||||
Ok(verifier.verify_oneshot(&signature, self.control.as_bytes())?)
|
||||
}
|
||||
|
||||
pub fn sign(&mut self, key: &str) -> crate::Result<&str> {
|
||||
pub fn sign(&mut self, key: &str) -> Result<&str> {
|
||||
let privkey = PKey::private_key_from_pem(key.as_bytes())?;
|
||||
let mut signer = openssl::sign::Signer::new(MessageDigest::sha256(), &privkey)?;
|
||||
signer.update(self.control.as_bytes())?;
|
||||
|
@ -100,6 +117,9 @@ impl HttpSignature {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
// TODO more tests!!!
|
||||
|
||||
#[test]
|
||||
fn http_signature_signs_and_verifies() {
|
||||
let key = openssl::rsa::Rsa::generate(2048).unwrap();
|
Loading…
Reference in a new issue