|  | @@ -76,28 +76,13 @@ pub enum Error {
 | 
											
												
													
														|  |      BlockNotEncrypted,
 |  |      BlockNotEncrypted,
 | 
											
												
													
														|  |      InvalidHashFormat,
 |  |      InvalidHashFormat,
 | 
											
												
													
														|  |      InvalidSignature,
 |  |      InvalidSignature,
 | 
											
												
													
														|  | -    IncorrectSize {
 |  | 
 | 
											
												
													
														|  | -        expected: usize,
 |  | 
 | 
											
												
													
														|  | -        actual: usize,
 |  | 
 | 
											
												
													
														|  | -    },
 |  | 
 | 
											
												
													
														|  | -    IndexOutOfBounds {
 |  | 
 | 
											
												
													
														|  | -        index: usize,
 |  | 
 | 
											
												
													
														|  | -        limit: usize,
 |  | 
 | 
											
												
													
														|  | -    },
 |  | 
 | 
											
												
													
														|  | -    IndivisibleSize {
 |  | 
 | 
											
												
													
														|  | -        divisor: usize,
 |  | 
 | 
											
												
													
														|  | -        actual: usize,
 |  | 
 | 
											
												
													
														|  | -    },
 |  | 
 | 
											
												
													
														|  | -    InvalidOffset {
 |  | 
 | 
											
												
													
														|  | -        actual: usize,
 |  | 
 | 
											
												
													
														|  | -        limit: usize,
 |  | 
 | 
											
												
													
														|  | -    },
 |  | 
 | 
											
												
													
														|  | 
 |  | +    IncorrectSize { expected: usize, actual: usize },
 | 
											
												
													
														|  | 
 |  | +    IndexOutOfBounds { index: usize, limit: usize },
 | 
											
												
													
														|  | 
 |  | +    IndivisibleSize { divisor: usize, actual: usize },
 | 
											
												
													
														|  | 
 |  | +    InvalidOffset { actual: usize, limit: usize },
 | 
											
												
													
														|  |      HashCmpFailure,
 |  |      HashCmpFailure,
 | 
											
												
													
														|  |      RootHashNotVerified,
 |  |      RootHashNotVerified,
 | 
											
												
													
														|  | -    SignatureMismatch {
 |  | 
 | 
											
												
													
														|  | -        actual: Principal,
 |  | 
 | 
											
												
													
														|  | -        expected: Principal,
 |  | 
 | 
											
												
													
														|  | -    },
 |  | 
 | 
											
												
													
														|  | 
 |  | +    SignatureMismatch(Box<SignatureMismatch>),
 | 
											
												
													
														|  |      WritecapAuthzErr(WritecapAuthzErr),
 |  |      WritecapAuthzErr(WritecapAuthzErr),
 | 
											
												
													
														|  |      Serde(btserde::Error),
 |  |      Serde(btserde::Error),
 | 
											
												
													
														|  |      Io(std::io::Error),
 |  |      Io(std::io::Error),
 | 
											
										
											
												
													
														|  | @@ -105,9 +90,13 @@ pub enum Error {
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  impl Error {
 |  |  impl Error {
 | 
											
												
													
														|  | -    pub(crate) fn custom<E: std::fmt::Debug + Send + Sync + 'static>(err: E) -> Self {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    pub(crate) fn custom<E: std::fmt::Debug + Send + Sync + 'static>(err: E) -> Error {
 | 
											
												
													
														|  |          Error::Custom(Box::new(err))
 |  |          Error::Custom(Box::new(err))
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  | 
 |  | +    fn signature_mismatch(expected: Principal, actual: Principal) -> Error {
 | 
											
												
													
														|  | 
 |  | +        Error::SignatureMismatch(Box::new(SignatureMismatch { expected, actual }))
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  impl Display for Error {
 |  |  impl Display for Error {
 | 
											
										
											
												
													
														|  | @@ -121,7 +110,7 @@ impl Display for Error {
 | 
											
												
													
														|  |              Error::InvalidHashFormat => write!(f, "invalid format"),
 |  |              Error::InvalidHashFormat => write!(f, "invalid format"),
 | 
											
												
													
														|  |              Error::InvalidSignature => write!(f, "invalid signature"),
 |  |              Error::InvalidSignature => write!(f, "invalid signature"),
 | 
											
												
													
														|  |              Error::IncorrectSize { expected, actual } => {
 |  |              Error::IncorrectSize { expected, actual } => {
 | 
											
												
													
														|  | -                write!(f, "expected size {} but got {}", expected, actual)
 |  | 
 | 
											
												
													
														|  | 
 |  | +                write!(f, "expected size {expected} but got {actual}")
 | 
											
												
													
														|  |              }
 |  |              }
 | 
											
												
													
														|  |              Error::IndexOutOfBounds { index, limit } => write!(
 |  |              Error::IndexOutOfBounds { index, limit } => write!(
 | 
											
												
													
														|  |                  f,
 |  |                  f,
 | 
											
										
											
												
													
														|  | @@ -140,10 +129,14 @@ impl Display for Error {
 | 
											
												
													
														|  |              ),
 |  |              ),
 | 
											
												
													
														|  |              Error::HashCmpFailure => write!(f, "hash data are not equal"),
 |  |              Error::HashCmpFailure => write!(f, "hash data are not equal"),
 | 
											
												
													
														|  |              Error::RootHashNotVerified => write!(f, "root hash is not verified"),
 |  |              Error::RootHashNotVerified => write!(f, "root hash is not verified"),
 | 
											
												
													
														|  | -            Error::SignatureMismatch { actual, expected } => write!(
 |  | 
 | 
											
												
													
														|  | -                f,
 |  | 
 | 
											
												
													
														|  | -                "expected a signature from {expected} but found one from {actual}"
 |  | 
 | 
											
												
													
														|  | -            ),
 |  | 
 | 
											
												
													
														|  | 
 |  | +            Error::SignatureMismatch(mismatch) => {
 | 
											
												
													
														|  | 
 |  | +                let actual = &mismatch.actual;
 | 
											
												
													
														|  | 
 |  | +                let expected = &mismatch.expected;
 | 
											
												
													
														|  | 
 |  | +                write!(
 | 
											
												
													
														|  | 
 |  | +                    f,
 | 
											
												
													
														|  | 
 |  | +                    "expected a signature from {expected} but found one from {actual}"
 | 
											
												
													
														|  | 
 |  | +                )
 | 
											
												
													
														|  | 
 |  | +            }
 | 
											
												
													
														|  |              Error::WritecapAuthzErr(err) => err.fmt(f),
 |  |              Error::WritecapAuthzErr(err) => err.fmt(f),
 | 
											
												
													
														|  |              Error::Serde(err) => err.fmt(f),
 |  |              Error::Serde(err) => err.fmt(f),
 | 
											
												
													
														|  |              Error::Io(err) => err.fmt(f),
 |  |              Error::Io(err) => err.fmt(f),
 | 
											
										
											
												
													
														|  | @@ -198,6 +191,12 @@ impl From<crate::Error> for Error {
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  pub(crate) type Result<T> = std::result::Result<T, Error>;
 |  |  pub(crate) type Result<T> = std::result::Result<T, Error>;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +#[derive(Debug)]
 | 
											
												
													
														|  | 
 |  | +pub struct SignatureMismatch {
 | 
											
												
													
														|  | 
 |  | +    pub actual: Principal,
 | 
											
												
													
														|  | 
 |  | +    pub expected: Principal,
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |  /// Returns an array of the given length filled with cryptographically strong random data.
 |  |  /// Returns an array of the given length filled with cryptographically strong random data.
 | 
											
												
													
														|  |  pub fn rand_array<const LEN: usize>() -> Result<[u8; LEN]> {
 |  |  pub fn rand_array<const LEN: usize>() -> Result<[u8; LEN]> {
 | 
											
												
													
														|  |      let mut array = [0; LEN];
 |  |      let mut array = [0; LEN];
 | 
											
										
											
												
													
														|  | @@ -670,7 +669,7 @@ impl Display for VarHash {
 | 
											
												
													
														|  |      fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 |  |      fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
											
												
													
														|  |          let hash_kind: HashKind = self.into();
 |  |          let hash_kind: HashKind = self.into();
 | 
											
												
													
														|  |          let hash_data = base64_url::encode(self.as_ref());
 |  |          let hash_data = base64_url::encode(self.as_ref());
 | 
											
												
													
														|  | -        write!(f, "{}{}{}", hash_kind as u32, VarHash::HASH_SEP, hash_data)
 |  | 
 | 
											
												
													
														|  | 
 |  | +        write!(f, "{}{}{hash_data}", hash_kind as u32, VarHash::HASH_SEP)
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -1175,7 +1174,7 @@ impl Scheme for RsaEsOaep {
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      fn hash_kind(&self) -> HashKind {
 |  |      fn hash_kind(&self) -> HashKind {
 | 
											
												
													
														|  | -        self.hash_kind.into()
 |  | 
 | 
											
												
													
														|  | 
 |  | +        self.hash_kind
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      fn padding(&self) -> Option<OpensslPadding> {
 |  |      fn padding(&self) -> Option<OpensslPadding> {
 | 
											
										
											
												
													
														|  | @@ -1219,7 +1218,7 @@ impl Scheme for RsaSsaPss {
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      fn hash_kind(&self) -> HashKind {
 |  |      fn hash_kind(&self) -> HashKind {
 | 
											
												
													
														|  | -        self.hash_kind.into()
 |  | 
 | 
											
												
													
														|  | 
 |  | +        self.hash_kind
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      fn padding(&self) -> Option<OpensslPadding> {
 |  |      fn padding(&self) -> Option<OpensslPadding> {
 | 
											
										
											
												
													
														|  | @@ -1422,7 +1421,7 @@ impl Decrypter for AsymKey<Private, Encrypt> {
 | 
											
												
													
														|  |  impl Signer for AsymKey<Private, Sign> {
 |  |  impl Signer for AsymKey<Private, Sign> {
 | 
											
												
													
														|  |      type Op<'s> = OsslSignOp<'s>;
 |  |      type Op<'s> = OsslSignOp<'s>;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    fn init_sign<'s>(&'s self) -> Result<Self::Op<'s>> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    fn init_sign(&self) -> Result<Self::Op<'_>> {
 | 
											
												
													
														|  |          OsslSignOp::init((self.scheme, self.pkey.as_ref()))
 |  |          OsslSignOp::init((self.scheme, self.pkey.as_ref()))
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -1443,7 +1442,7 @@ impl Signer for AsymKey<Private, Sign> {
 | 
											
												
													
														|  |  impl Verifier for AsymKey<Public, Sign> {
 |  |  impl Verifier for AsymKey<Public, Sign> {
 | 
											
												
													
														|  |      type Op<'v> = OsslVerifyOp<'v>;
 |  |      type Op<'v> = OsslVerifyOp<'v>;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    fn init_verify<'v>(&'v self) -> Result<Self::Op<'v>> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    fn init_verify(&self) -> Result<Self::Op<'_>> {
 | 
											
												
													
														|  |          OsslVerifyOp::init((self.scheme, self.pkey.as_ref()))
 |  |          OsslVerifyOp::init((self.scheme, self.pkey.as_ref()))
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -1498,7 +1497,7 @@ impl Decrypter for AsymKeyPair<Encrypt> {
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  impl Signer for AsymKeyPair<Sign> {
 |  |  impl Signer for AsymKeyPair<Sign> {
 | 
											
												
													
														|  |      type Op<'s> = <AsymKey<Private, Sign> as Signer>::Op<'s>;
 |  |      type Op<'s> = <AsymKey<Private, Sign> as Signer>::Op<'s>;
 | 
											
												
													
														|  | -    fn init_sign<'s>(&'s self) -> Result<Self::Op<'s>> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    fn init_sign(&self) -> Result<Self::Op<'_>> {
 | 
											
												
													
														|  |          self.private.init_sign()
 |  |          self.private.init_sign()
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |      fn sign<'a, I: Iterator<Item = &'a [u8]>>(&self, parts: I) -> Result<Signature> {
 |  |      fn sign<'a, I: Iterator<Item = &'a [u8]>>(&self, parts: I) -> Result<Signature> {
 | 
											
										
											
												
													
														|  | @@ -1509,7 +1508,7 @@ impl Signer for AsymKeyPair<Sign> {
 | 
											
												
													
														|  |  impl Verifier for AsymKeyPair<Sign> {
 |  |  impl Verifier for AsymKeyPair<Sign> {
 | 
											
												
													
														|  |      type Op<'v> = OsslVerifyOp<'v>;
 |  |      type Op<'v> = OsslVerifyOp<'v>;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    fn init_verify<'v>(&'v self) -> Result<Self::Op<'v>> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    fn init_verify(&self) -> Result<Self::Op<'_>> {
 | 
											
												
													
														|  |          self.public.init_verify()
 |  |          self.public.init_verify()
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -1539,7 +1538,7 @@ impl Encrypter for PublicCreds {
 | 
											
												
													
														|  |  impl Verifier for PublicCreds {
 |  |  impl Verifier for PublicCreds {
 | 
											
												
													
														|  |      type Op<'v> = OsslVerifyOp<'v>;
 |  |      type Op<'v> = OsslVerifyOp<'v>;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    fn init_verify<'v>(&'v self) -> Result<Self::Op<'v>> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    fn init_verify(&self) -> Result<Self::Op<'_>> {
 | 
											
												
													
														|  |          self.sign.init_verify()
 |  |          self.sign.init_verify()
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -1591,7 +1590,7 @@ impl ConcreteCreds {
 | 
											
												
													
														|  |  impl Verifier for ConcreteCreds {
 |  |  impl Verifier for ConcreteCreds {
 | 
											
												
													
														|  |      type Op<'v> = OsslVerifyOp<'v>;
 |  |      type Op<'v> = OsslVerifyOp<'v>;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    fn init_verify<'v>(&'v self) -> Result<Self::Op<'v>> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    fn init_verify(&self) -> Result<Self::Op<'_>> {
 | 
											
												
													
														|  |          self.sign.init_verify()
 |  |          self.sign.init_verify()
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -1621,7 +1620,7 @@ impl CredsPub for ConcreteCreds {
 | 
											
												
													
														|  |  impl Signer for ConcreteCreds {
 |  |  impl Signer for ConcreteCreds {
 | 
											
												
													
														|  |      type Op<'s> = <AsymKeyPair<Sign> as Signer>::Op<'s>;
 |  |      type Op<'s> = <AsymKeyPair<Sign> as Signer>::Op<'s>;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    fn init_sign<'s>(&'s self) -> Result<Self::Op<'s>> {
 |  | 
 | 
											
												
													
														|  | 
 |  | +    fn init_sign(&self) -> Result<Self::Op<'_>> {
 | 
											
												
													
														|  |          self.sign.init_sign()
 |  |          self.sign.init_sign()
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -1760,7 +1759,7 @@ pub trait Signer {
 | 
											
												
													
														|  |          Self: 's;
 |  |          Self: 's;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      /// Starts a new signing operation and returns the struct representing it.
 |  |      /// Starts a new signing operation and returns the struct representing it.
 | 
											
												
													
														|  | -    fn init_sign<'s>(&'s self) -> Result<Self::Op<'s>>;
 |  | 
 | 
											
												
													
														|  | 
 |  | +    fn init_sign(&self) -> Result<Self::Op<'_>>;
 | 
											
												
													
														|  |      fn sign<'a, I: Iterator<Item = &'a [u8]>>(&self, parts: I) -> Result<Signature>;
 |  |      fn sign<'a, I: Iterator<Item = &'a [u8]>>(&self, parts: I) -> Result<Signature>;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      fn ser_sign<T: Serialize>(&self, value: &T) -> Result<Signed<T>> {
 |  |      fn ser_sign<T: Serialize>(&self, value: &T) -> Result<Signed<T>> {
 | 
											
										
											
												
													
														|  | @@ -1878,7 +1877,7 @@ pub trait Verifier {
 | 
											
												
													
														|  |      where
 |  |      where
 | 
											
												
													
														|  |          Self: 'v;
 |  |          Self: 'v;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | -    fn init_verify<'v>(&'v self) -> Result<Self::Op<'v>>;
 |  | 
 | 
											
												
													
														|  | 
 |  | +    fn init_verify(&self) -> Result<Self::Op<'_>>;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      fn verify<'a, I: Iterator<Item = &'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<()>;
 |  |      fn verify<'a, I: Iterator<Item = &'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<()>;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -1969,10 +1968,10 @@ impl BlockMeta {
 | 
											
												
													
														|  |          writecap.assert_valid_for(&body.path)?;
 |  |          writecap.assert_valid_for(&body.path)?;
 | 
											
												
													
														|  |          let signed_by = body.signing_key.principal();
 |  |          let signed_by = body.signing_key.principal();
 | 
											
												
													
														|  |          if writecap.body.issued_to != signed_by {
 |  |          if writecap.body.issued_to != signed_by {
 | 
											
												
													
														|  | -            return Err(Error::SignatureMismatch {
 |  | 
 | 
											
												
													
														|  | -                actual: signed_by,
 |  | 
 | 
											
												
													
														|  | -                expected: writecap.body.issued_to.clone(),
 |  | 
 | 
											
												
													
														|  | -            });
 |  | 
 | 
											
												
													
														|  | 
 |  | +            return Err(Error::signature_mismatch(
 | 
											
												
													
														|  | 
 |  | +                writecap.body.issued_to.clone(),
 | 
											
												
													
														|  | 
 |  | +                signed_by,
 | 
											
												
													
														|  | 
 |  | +            ));
 | 
											
												
													
														|  |          }
 |  |          }
 | 
											
												
													
														|  |          body.signing_key.ser_verify(&body, self.sig.as_slice())
 |  |          body.signing_key.ser_verify(&body, self.sig.as_slice())
 | 
											
												
													
														|  |      }
 |  |      }
 |