wtx 0.52.0

A collection of different transport implementations and related tools focused primarily on web technologies.
Documentation
use crate::{
  collections::ArrayVectorCopy,
  crypto::{
    EcdsaP256SigningKeyRuco, EcdsaP384SigningKeyRuco, Ed25519SigningKeyRuco, HashTy,
    RsaPkcs1SigningKeyRuco, RsaPssSigningKeyRuco, SigningOutput, signing_key::SigningKey,
  },
  rng::CryptoRng,
};
use alloc::boxed::Box;
use pkcs8::DecodePrivateKey as _;
use rsa::{RsaPublicKey, pkcs1::DecodeRsaPublicKey as _, pkcs1v15, pss};
use signature::{RandomizedSigner as _, Signer as _, Verifier as _};
use spki::DecodePublicKey as _;

impl SigningKey for EcdsaP256SigningKeyRuco {
  type Signature = ArrayVectorCopy<u8, 72>;

  #[inline]
  fn from_pkcs8(bytes: &[u8], _: HashTy) -> crate::Result<Self> {
    Ok(Self(p256::ecdsa::SigningKey::from_pkcs8_der(bytes)?))
  }

  #[inline]
  fn sign<RNG>(&self, msg: &[u8], rng: &mut RNG) -> crate::Result<SigningOutput<Self::Signature>>
  where
    RNG: CryptoRng,
  {
    let local_signature: p256::ecdsa::Signature = self.0.try_sign_with_rng(rng, msg)?;
    let mut signature = ArrayVectorCopy::new();
    signature.extend_from_copyable_slice(local_signature.to_der().as_bytes())?;
    Ok(SigningOutput::new(HashTy::Sha256, signature))
  }

  #[inline]
  fn validate(msg: &[u8], pk: &[u8], so: &SigningOutput<&[u8]>) -> crate::Result<()> {
    let sig = if so.signature().len() == 64 {
      p256::ecdsa::Signature::from_slice(so.signature())?
    } else {
      p256::ecdsa::Signature::from_der(so.signature())?
    };
    p256::ecdsa::VerifyingKey::from_sec1_bytes(pk)?.verify(msg, &sig)?;
    Ok(())
  }
}

impl SigningKey for EcdsaP384SigningKeyRuco {
  type Signature = ArrayVectorCopy<u8, 104>;

  #[inline]
  fn from_pkcs8(bytes: &[u8], _: HashTy) -> crate::Result<Self> {
    Ok(Self(p384::ecdsa::SigningKey::from_pkcs8_der(bytes)?))
  }

  #[inline]
  fn sign<RNG>(&self, msg: &[u8], rng: &mut RNG) -> crate::Result<SigningOutput<Self::Signature>>
  where
    RNG: CryptoRng,
  {
    let local_signature: p384::ecdsa::Signature = self.0.try_sign_with_rng(rng, msg)?;
    let mut signature = ArrayVectorCopy::new();
    signature.extend_from_copyable_slice(local_signature.to_der().as_bytes())?;
    Ok(SigningOutput::new(HashTy::Sha384, signature))
  }

  #[inline]
  fn validate(msg: &[u8], pk: &[u8], so: &SigningOutput<&[u8]>) -> crate::Result<()> {
    let sig = if so.signature().len() == 96 {
      p384::ecdsa::Signature::from_slice(so.signature())?
    } else {
      p384::ecdsa::Signature::from_der(so.signature())?
    };
    p384::ecdsa::VerifyingKey::from_sec1_bytes(pk)?.verify(msg, &sig)?;
    Ok(())
  }
}

impl SigningKey for Ed25519SigningKeyRuco {
  type Signature = [u8; 64];

  #[inline]
  fn from_pkcs8(bytes: &[u8], _: HashTy) -> crate::Result<Self> {
    Ok(Self(ed25519_dalek::SigningKey::from_pkcs8_der(bytes)?))
  }

  #[inline]
  fn sign<RNG>(&self, msg: &[u8], _: &mut RNG) -> crate::Result<SigningOutput<Self::Signature>>
  where
    RNG: CryptoRng,
  {
    Ok(SigningOutput::new(HashTy::Sha512, self.0.try_sign(msg)?.to_bytes()))
  }

  #[inline]
  fn validate(msg: &[u8], pk: &[u8], so: &SigningOutput<&[u8]>) -> crate::Result<()> {
    ed25519_dalek::VerifyingKey::from_bytes(pk.try_into()?)?
      .verify(msg, &ed25519_dalek::Signature::from_slice(so.signature())?)?;
    Ok(())
  }
}

impl SigningKey for RsaPkcs1SigningKeyRuco {
  type Signature = Box<[u8]>;

  #[inline]
  fn from_pkcs8(bytes: &[u8], hash_ty: HashTy) -> crate::Result<Self> {
    Ok(match hash_ty {
      HashTy::Sha256 => RsaPkcs1SigningKeyRuco::Sha256(pkcs1v15::SigningKey::new(
        rsa::RsaPrivateKey::from_pkcs8_der(bytes)?,
      )),
      HashTy::Sha384 => RsaPkcs1SigningKeyRuco::Sha384(pkcs1v15::SigningKey::new(
        rsa::RsaPrivateKey::from_pkcs8_der(bytes)?,
      )),
      HashTy::Sha512 => RsaPkcs1SigningKeyRuco::Sha512(pkcs1v15::SigningKey::new(
        rsa::RsaPrivateKey::from_pkcs8_der(bytes)?,
      )),
    })
  }

  #[inline]
  fn sign<RNG>(&self, msg: &[u8], rng: &mut RNG) -> crate::Result<SigningOutput<Self::Signature>>
  where
    RNG: CryptoRng,
  {
    let (hash_ty, signature) = match self {
      RsaPkcs1SigningKeyRuco::Sha256(el) => (HashTy::Sha256, el.try_sign_with_rng(rng, msg)?),
      RsaPkcs1SigningKeyRuco::Sha384(el) => (HashTy::Sha384, el.try_sign_with_rng(rng, msg)?),
      RsaPkcs1SigningKeyRuco::Sha512(el) => (HashTy::Sha512, el.try_sign_with_rng(rng, msg)?),
    };
    Ok(SigningOutput::new(hash_ty, signature.into()))
  }

  #[inline]
  fn validate(msg: &[u8], pk: &[u8], so: &SigningOutput<&[u8]>) -> crate::Result<()> {
    let rpk =
      RsaPublicKey::from_public_key_der(pk).or_else(|_| RsaPublicKey::from_pkcs1_der(pk))?;
    let sig = pkcs1v15::Signature::try_from(&**so.signature())?;
    match so.hash_ty() {
      HashTy::Sha256 => pkcs1v15::VerifyingKey::<sha2::Sha256>::new(rpk).verify(msg, &sig)?,
      HashTy::Sha384 => pkcs1v15::VerifyingKey::<sha2::Sha384>::new(rpk).verify(msg, &sig)?,
      HashTy::Sha512 => pkcs1v15::VerifyingKey::<sha2::Sha512>::new(rpk).verify(msg, &sig)?,
    }
    Ok(())
  }
}

impl SigningKey for RsaPssSigningKeyRuco {
  type Signature = Box<[u8]>;

  #[inline]
  fn from_pkcs8(bytes: &[u8], hash_ty: HashTy) -> crate::Result<Self> {
    Ok(match hash_ty {
      HashTy::Sha256 => RsaPssSigningKeyRuco::Sha256(pss::SigningKey::new(
        rsa::RsaPrivateKey::from_pkcs8_der(bytes)?,
      )),
      HashTy::Sha384 => RsaPssSigningKeyRuco::Sha384(pss::SigningKey::new(
        rsa::RsaPrivateKey::from_pkcs8_der(bytes)?,
      )),
      HashTy::Sha512 => RsaPssSigningKeyRuco::Sha512(pss::SigningKey::new(
        rsa::RsaPrivateKey::from_pkcs8_der(bytes)?,
      )),
    })
  }

  #[inline]
  fn sign<RNG>(&self, msg: &[u8], rng: &mut RNG) -> crate::Result<SigningOutput<Self::Signature>>
  where
    RNG: CryptoRng,
  {
    let (hash_ty, signature) = match self {
      RsaPssSigningKeyRuco::Sha256(el) => (HashTy::Sha256, el.try_sign_with_rng(rng, msg)?),
      RsaPssSigningKeyRuco::Sha384(el) => (HashTy::Sha384, el.try_sign_with_rng(rng, msg)?),
      RsaPssSigningKeyRuco::Sha512(el) => (HashTy::Sha512, el.try_sign_with_rng(rng, msg)?),
    };
    Ok(SigningOutput::new(hash_ty, signature.into()))
  }

  #[inline]
  fn validate(msg: &[u8], pk: &[u8], so: &SigningOutput<&[u8]>) -> crate::Result<()> {
    let rpk =
      RsaPublicKey::from_public_key_der(pk).or_else(|_| RsaPublicKey::from_pkcs1_der(pk))?;
    let sig = pss::Signature::try_from(&**so.signature())?;
    match so.hash_ty() {
      HashTy::Sha256 => pss::VerifyingKey::<sha2::Sha256>::new(rpk).verify(msg, &sig)?,
      HashTy::Sha384 => pss::VerifyingKey::<sha2::Sha384>::new(rpk).verify(msg, &sig)?,
      HashTy::Sha512 => pss::VerifyingKey::<sha2::Sha512>::new(rpk).verify(msg, &sig)?,
    }
    Ok(())
  }
}