diff --git a/Cargo.toml b/Cargo.toml index 8add4a3..b927c5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jsonwebkey" -version = "0.3.0" +version = "0.3.1" authors = ["Nick Hynes "] description = "JSON Web Key (JWK) (de)serialization, generation, and conversion." readme = "README.md" @@ -11,7 +11,6 @@ edition = "2018" [dependencies] base64 = "0.12" bitflags = "1.2" -derive_more = "0.99" generic-array = "0.14" jsonwebtoken = { version = "7.2", optional = true } num-bigint = { version = "0.2", optional = true } diff --git a/src/byte_array.rs b/src/byte_array.rs index 6ea6485..0043577 100644 --- a/src/byte_array.rs +++ b/src/byte_array.rs @@ -1,15 +1,23 @@ -use derive_more::{AsRef, Deref}; use generic_array::{ArrayLength, GenericArray}; -use serde::de::{self, Deserialize, Deserializer}; +use serde::{ + de::{self, Deserializer}, + Deserialize, Serialize, +}; use zeroize::{Zeroize, Zeroizing}; /// A zeroizing-on-drop container for a `[u8; N]` that deserializes from base64. -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deref, AsRef)] +#[derive(Clone, PartialEq, Eq, Serialize)] #[serde(transparent)] pub struct ByteArray>( - #[serde(serialize_with = "crate::utils::serde_base64::serialize")] pub GenericArray, + #[serde(serialize_with = "crate::utils::serde_base64::serialize")] GenericArray, ); +impl> std::fmt::Debug for ByteArray { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&crate::utils::base64_encode(&self.0)) + } +} + impl, T: Into>> From for ByteArray { fn from(arr: T) -> Self { Self(arr.into()) @@ -22,6 +30,19 @@ impl> Drop for ByteArray { } } +impl> AsRef<[u8]> for ByteArray { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +impl> std::ops::Deref for ByteArray { + type Target = [u8]; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl> ByteArray { /// An unwrapping version of `try_from_slice`. pub fn from_slice(bytes: impl AsRef<[u8]>) -> Self { @@ -73,7 +94,7 @@ mod tests { let b64 = serde_json::to_string(&arr).unwrap(); assert_eq!(b64, BASE64_JSON); let bytes: ByteArray = serde_json::from_str(&b64).unwrap(); - assert_eq!(bytes.as_slice(), BYTES); + assert_eq!(bytes.as_ref(), BYTES); } #[test] diff --git a/src/byte_vec.rs b/src/byte_vec.rs index b7b85e4..fab3a4a 100644 --- a/src/byte_vec.rs +++ b/src/byte_vec.rs @@ -1,21 +1,34 @@ -use std::fmt; - -use derive_more::{AsRef, Deref, From}; +use serde::{Deserialize, Serialize}; use zeroize::Zeroize; /// A zeroizing-on-drop container for a `Vec` that deserializes from base64. -#[derive(Clone, PartialEq, Eq, Zeroize, Serialize, Deserialize, Deref, AsRef, From)] +#[derive(Clone, PartialEq, Eq, Zeroize, Serialize, Deserialize)] #[zeroize(drop)] #[serde(transparent)] -pub struct ByteVec(#[serde(with = "crate::utils::serde_base64")] pub Vec); +pub struct ByteVec(#[serde(with = "crate::utils::serde_base64")] Vec); -impl fmt::Debug for ByteVec { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if cfg!(debug_assertions) { - write!(f, "{:?}", self.0) - } else { - write!(f, "ByteVec") - } +impl std::fmt::Debug for ByteVec { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&crate::utils::base64_encode(&self.0)) + } +} + +impl>> From for ByteVec { + fn from(into_vec: T) -> Self { + Self(into_vec.into()) + } +} + +impl AsRef<[u8]> for ByteVec { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +impl std::ops::Deref for ByteVec { + type Target = [u8]; + fn deref(&self) -> &Self::Target { + &self.0 } } @@ -31,6 +44,6 @@ mod tests { let b64 = serde_json::to_string(&ByteVec(BYTES.to_vec())).unwrap(); assert_eq!(b64, BASE64_JSON); let bytes: ByteVec = serde_json::from_str(&b64).unwrap(); - assert_eq!(bytes.as_slice(), BYTES); + assert_eq!(bytes.as_ref(), BYTES); } } diff --git a/src/lib.rs b/src/lib.rs index 7b05270..4a4b805 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -58,9 +58,6 @@ //! This pulls in the [p256](https://crates.io/crates/p256) and [rand](https://crates.io/crates/rand) crates. //! * `jsonwebtoken` - enables conversions to types in the [jsonwebtoken](https://crates.io/crates/jsonwebtoken) crate. -#[macro_use] -extern crate serde; - mod byte_array; mod byte_vec; mod key_ops; @@ -69,6 +66,7 @@ mod tests; mod utils; use std::borrow::Cow; +use std::fmt; use generic_array::typenum::U32; use serde::{Deserialize, Serialize}; @@ -308,7 +306,7 @@ impl Key { ]); let oids = &[Some(&rsa_encryption_oid), None]; let write_bytevec = |writer: DERWriter<'_>, vec: &ByteVec| { - let bigint = BigUint::from_bytes_be(vec.as_slice()); + let bigint = BigUint::from_bytes_be(&vec); writer.write_biguint(&bigint); }; @@ -435,7 +433,7 @@ impl Key { } } -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(tag = "crv")] pub enum Curve { /// Parameters of the prime256v1 (P256) curve. @@ -451,6 +449,18 @@ pub enum Curve { }, } +impl fmt::Debug for Curve { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::P256 { x, y, .. } => f + .debug_struct("Curve:P256") + .field("x", x) + .field("y", y) + .finish(), + } + } +} + #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct RsaPublic { /// The standard public exponent, 65537. @@ -487,7 +497,7 @@ impl<'de> Deserialize<'de> for PublicExponent { } } -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct RsaPrivate { /// Private exponent. pub d: ByteVec, @@ -508,6 +518,12 @@ pub struct RsaPrivate { pub qi: Option, } +impl fmt::Debug for RsaPrivate { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("RsaPrivate") + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum KeyUse { #[serde(rename = "sig")] diff --git a/src/utils.rs b/src/utils.rs index 426e1ea..9a171a4 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -8,7 +8,7 @@ fn base64_config() -> base64::Config { base64::Config::new(base64::CharacterSet::UrlSafe, false /* pad */) } -fn base64_encode(bytes: impl AsRef<[u8]>) -> String { +pub(crate) fn base64_encode(bytes: impl AsRef<[u8]>) -> String { base64::encode_config(bytes, base64_config()) }