Files
nym/common/ip-packet-requests/src/sign.rs
Jon Häggblad 856dbfe1ac IPR request types v8 (#5498)
* IPR v8 request/response types

* Remove signature for when we use sender tags

* Remove unused

* Address some review comments

* Update license to GPL-3.0 for IPR

Since the IPR can run as a binary, make sure it's license is GPL-3.0

* update cargo deny

* Add back support for v6

* Tidy responses

* Clippy

* Fix compilation

* Conversions

* Conversions

* Split response conversion

* request split

* Complete conversion switch

* Remove commented out code

* rustfmt

* Remove unused conversions

* Remove unused TryFrom

* use from
2025-02-27 15:21:55 +01:00

67 lines
1.9 KiB
Rust

use std::time::Duration;
use nym_crypto::asymmetric::ed25519;
use time::OffsetDateTime;
// For reply protection, if a request is older than this, it will be rejected
const MAX_REQUEST_AGE: Duration = Duration::from_secs(10);
#[derive(thiserror::Error, Debug)]
pub enum SignatureError {
#[error("signature is missing")]
MissingSignature,
#[error("failed to serialize request to binary: {message}")]
RequestSerializationError {
message: String,
error: Box<bincode::ErrorKind>,
},
#[error("signature verification failed: request out of date")]
RequestOutOfDate,
#[error("signature verification failed")]
VerificationFailed {
message: String,
error: ed25519::SignatureError,
},
}
pub trait SignedRequest {
fn identity(&self) -> Option<&ed25519::PublicKey>;
fn request_as_bytes(&self) -> Result<Vec<u8>, SignatureError>;
fn signature(&self) -> Option<&ed25519::Signature>;
fn timestamp(&self) -> OffsetDateTime;
fn verify(&self) -> Result<(), SignatureError> {
let identity = match self.identity() {
Some(identity) => identity,
None => {
// If we are not revealing our identity, we don't need to verify anything
return Ok(());
}
};
if let Some(signature) = self.signature() {
// First check that the request is recent enough
if OffsetDateTime::now_utc() - self.timestamp() > MAX_REQUEST_AGE {
return Err(SignatureError::RequestOutOfDate);
}
let request_as_bytes = self.request_as_bytes()?;
identity
.verify(request_as_bytes, signature)
.map_err(|error| SignatureError::VerificationFailed {
message: "signature verification failed".to_string(),
error,
})
} else {
Err(SignatureError::MissingSignature)
}
}
}