diff --git a/crates/jose/src/jwk.rs b/crates/jose/src/jwk/mod.rs similarity index 86% rename from crates/jose/src/jwk.rs rename to crates/jose/src/jwk/mod.rs index b8f42b82..acbe9dfe 100644 --- a/crates/jose/src/jwk.rs +++ b/crates/jose/src/jwk/mod.rs @@ -14,13 +14,10 @@ //! Ref: -use anyhow::bail; use mas_iana::jose::{ - JsonWebKeyEcEllipticCurve, JsonWebKeyOkpEllipticCurve, JsonWebKeyOperation, JsonWebKeyType, - JsonWebKeyUse, JsonWebSignatureAlg, + JsonWebKeyEcEllipticCurve, JsonWebKeyOperation, JsonWebKeyType, JsonWebKeyUse, + JsonWebSignatureAlg, }; -use p256::NistP256; -use rsa::{BigUint, PublicKeyParts}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_with::{ @@ -32,6 +29,27 @@ use url::Url; use crate::constraints::Constrainable; +pub(crate) mod private_parameters; +pub(crate) mod public_parameters; + +pub use self::public_parameters::JsonWebKeyPublicParameters as JsonWebKeyParameters; + +trait JwkEcCurve { + const CRV: JsonWebKeyEcEllipticCurve; +} + +impl JwkEcCurve for p256::NistP256 { + const CRV: JsonWebKeyEcEllipticCurve = JsonWebKeyEcEllipticCurve::P256; +} + +impl JwkEcCurve for p384::NistP384 { + const CRV: JsonWebKeyEcEllipticCurve = JsonWebKeyEcEllipticCurve::P384; +} + +impl JwkEcCurve for k256::Secp256k1 { + const CRV: JsonWebKeyEcEllipticCurve = JsonWebKeyEcEllipticCurve::Secp256K1; +} + #[serde_as] #[skip_serializing_none] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] @@ -139,7 +157,7 @@ impl Constrainable for JsonWebKey { if let Some(alg) = self.alg { Some(vec![alg]) } else { - match self.parameters { + match &self.parameters { JsonWebKeyParameters::Rsa { .. } => Some(vec![ JsonWebSignatureAlg::Rs256, JsonWebSignatureAlg::Rs384, @@ -148,22 +166,12 @@ impl Constrainable for JsonWebKey { JsonWebSignatureAlg::Ps384, JsonWebSignatureAlg::Ps512, ]), - JsonWebKeyParameters::Ec { - crv: JsonWebKeyEcEllipticCurve::P256, - .. - } => Some(vec![JsonWebSignatureAlg::Es256]), - JsonWebKeyParameters::Ec { - crv: JsonWebKeyEcEllipticCurve::P384, - .. - } => Some(vec![JsonWebSignatureAlg::Es384]), - JsonWebKeyParameters::Ec { - crv: JsonWebKeyEcEllipticCurve::P521, - .. - } => Some(vec![JsonWebSignatureAlg::Es512]), - JsonWebKeyParameters::Ec { - crv: JsonWebKeyEcEllipticCurve::Secp256K1, - .. - } => Some(vec![JsonWebSignatureAlg::Es256K]), + JsonWebKeyParameters::Ec(params) => match params.crv() { + JsonWebKeyEcEllipticCurve::P256 => Some(vec![JsonWebSignatureAlg::Es256]), + JsonWebKeyEcEllipticCurve::P384 => Some(vec![JsonWebSignatureAlg::Es384]), + JsonWebKeyEcEllipticCurve::P521 => Some(vec![JsonWebSignatureAlg::Es512]), + JsonWebKeyEcEllipticCurve::Secp256K1 => Some(vec![JsonWebSignatureAlg::Es256K]), + }, JsonWebKeyParameters::Okp { .. } => Some(vec![JsonWebSignatureAlg::EdDsa]), } } @@ -194,100 +202,6 @@ impl JsonWebKeySet { } } -#[serde_as] -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] -#[serde(tag = "kty")] -pub enum JsonWebKeyParameters { - #[serde(rename = "RSA")] - Rsa { - #[schemars(with = "String")] - #[serde_as(as = "Base64")] - n: Vec, - - #[schemars(with = "String")] - #[serde_as(as = "Base64")] - e: Vec, - }, - #[serde(rename = "EC")] - Ec { - crv: JsonWebKeyEcEllipticCurve, - - #[schemars(with = "String")] - #[serde_as(as = "Base64")] - x: Vec, - - #[schemars(with = "String")] - #[serde_as(as = "Base64")] - y: Vec, - }, - #[serde(rename = "OKP")] - Okp { - crv: JsonWebKeyOkpEllipticCurve, - - #[schemars(with = "String")] - #[serde_as(as = "Base64")] - x: Vec, - }, -} - -impl TryFrom for ecdsa::VerifyingKey { - type Error = anyhow::Error; - - fn try_from(params: JsonWebKeyParameters) -> Result { - let (x, y): ([u8; 32], [u8; 32]) = match params { - JsonWebKeyParameters::Ec { - x, - y, - crv: JsonWebKeyEcEllipticCurve::P256, - } => ( - x.try_into() - .map_err(|_| anyhow::anyhow!("invalid curve parameter x"))?, - y.try_into() - .map_err(|_| anyhow::anyhow!("invalid curve parameter y"))?, - ), - _ => bail!("Wrong key type"), - }; - - let point = sec1::EncodedPoint::from_affine_coordinates(&x.into(), &y.into(), false); - let key = ecdsa::VerifyingKey::from_encoded_point(&point)?; - Ok(key) - } -} - -impl From> for JsonWebKeyParameters { - fn from(key: ecdsa::VerifyingKey) -> Self { - let points = key.to_encoded_point(false); - JsonWebKeyParameters::Ec { - x: points.x().unwrap().to_vec(), - y: points.y().unwrap().to_vec(), - crv: JsonWebKeyEcEllipticCurve::P256, - } - } -} - -impl TryFrom for rsa::RsaPublicKey { - type Error = anyhow::Error; - - fn try_from(params: JsonWebKeyParameters) -> Result { - let (n, e) = match ¶ms { - JsonWebKeyParameters::Rsa { n, e } => (n, e), - _ => bail!("Wrong key type"), - }; - let n = BigUint::from_bytes_be(n); - let e = BigUint::from_bytes_be(e); - Ok(rsa::RsaPublicKey::new(n, e)?) - } -} - -impl From for JsonWebKeyParameters { - fn from(key: rsa::RsaPublicKey) -> Self { - JsonWebKeyParameters::Rsa { - n: key.n().to_bytes_be(), - e: key.e().to_bytes_be(), - } - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/jose/src/jwk/private_parameters.rs b/crates/jose/src/jwk/private_parameters.rs new file mode 100644 index 00000000..2656f3ff --- /dev/null +++ b/crates/jose/src/jwk/private_parameters.rs @@ -0,0 +1,257 @@ +// Copyright 2022 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use mas_iana::jose::{JsonWebKeyEcEllipticCurve, JsonWebKeyOkpEllipticCurve}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use serde_with::{ + base64::{Base64, UrlSafe}, + formats::Unpadded, + serde_as, +}; + +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +#[serde(tag = "kty")] +pub enum JsonWebKeyPrivateParameters { + #[serde(rename = "oct")] + Oct(OctPrivateParameters), + + #[serde(rename = "RSA")] + Rsa(RsaPrivateParameters), + + #[serde(rename = "EC")] + Ec(EcPrivateParameters), + + #[serde(rename = "OKP")] + Okp(OkpPrivateParameters), +} + +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub struct OctPrivateParameters { + /// Key Value + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + k: Vec, +} + +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub struct RsaPrivateParameters { + /// Modulus + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + n: Vec, + + /// Exponent + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + e: Vec, + + /// Private Exponent + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + d: Vec, + + /// First Prime Factor + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + p: Vec, + + /// Second Prime Factor + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + q: Vec, + + /// First Factor CRT Exponent + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + dp: Vec, + + /// Second Factor CRT Exponent + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + dq: Vec, + + /// First CRT Coefficient + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + qi: Vec, + + /// Other Primes Info + #[serde(skip_serializing_if = "Option::is_none")] + oth: Option>, +} + +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +struct RsaOtherPrimeInfo { + /// Prime Factor + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + r: Vec, + + /// Factor CRT Exponent + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + d: Vec, + + /// Factor CRT Coefficient + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + t: Vec, +} + +mod rsa_impls { + use rsa::{BigUint, RsaPrivateKey}; + + use super::RsaPrivateParameters; + + impl TryInto for RsaPrivateParameters { + type Error = rsa::errors::Error; + fn try_into(self) -> Result { + (&self).try_into() + } + } + + impl TryInto for &RsaPrivateParameters { + type Error = rsa::errors::Error; + + #[allow(clippy::many_single_char_names)] + fn try_into(self) -> Result { + let n = BigUint::from_bytes_be(&self.n); + let e = BigUint::from_bytes_be(&self.e); + let d = BigUint::from_bytes_be(&self.d); + + let primes = [&self.p, &self.q] + .into_iter() + .chain(self.oth.iter().flatten().map(|o| &o.r)) + .map(|i| BigUint::from_bytes_be(i)) + .collect(); + + RsaPrivateKey::from_components(n, e, d, primes) + } + } +} + +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub struct EcPrivateParameters { + crv: JsonWebKeyEcEllipticCurve, + + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + x: Vec, + + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + y: Vec, + + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + d: Vec, +} + +mod ec_impls { + use digest::typenum::Unsigned; + use ecdsa::EncodedPoint; + use elliptic_curve::{ + sec1::{Coordinates, FromEncodedPoint, ModulusSize, ToEncodedPoint, ValidatePublicKey}, + AffinePoint, Curve, FieldBytes, FieldSize, SecretKey, + }; + + use super::{super::JwkEcCurve, EcPrivateParameters}; + + impl TryInto> for EcPrivateParameters + where + C: Curve + ValidatePublicKey, + FieldSize: ModulusSize, + { + type Error = elliptic_curve::Error; + fn try_into(self) -> Result, Self::Error> { + (&self).try_into() + } + } + + impl TryInto> for &EcPrivateParameters + where + C: Curve + ValidatePublicKey, + FieldSize: ModulusSize, + { + type Error = elliptic_curve::Error; + + fn try_into(self) -> Result, Self::Error> { + let x = self + .x + .get(..FieldSize::::USIZE) + .ok_or(elliptic_curve::Error)?; + let y = self + .x + .get(..FieldSize::::USIZE) + .ok_or(elliptic_curve::Error)?; + + let x = FieldBytes::::from_slice(x); + let y = FieldBytes::::from_slice(y); + let pubkey = EncodedPoint::::from_affine_coordinates(x, y, false); + let privkey = SecretKey::from_be_bytes(&self.d)?; + C::validate_public_key(&privkey, &pubkey)?; + Ok(privkey) + } + } + + impl From> for EcPrivateParameters + where + C: Curve + elliptic_curve::ProjectiveArithmetic + JwkEcCurve, + AffinePoint: FromEncodedPoint + ToEncodedPoint, + FieldSize: ModulusSize, + { + fn from(key: SecretKey) -> Self { + (&key).into() + } + } + + impl From<&SecretKey> for EcPrivateParameters + where + C: Curve + elliptic_curve::ProjectiveArithmetic + JwkEcCurve, + AffinePoint: FromEncodedPoint + ToEncodedPoint, + FieldSize: ModulusSize, + { + fn from(key: &SecretKey) -> Self { + let point = key.public_key().to_encoded_point(false); + let (x, y) = match point.coordinates() { + Coordinates::Uncompressed { x, y } => (x, y), + _ => unreachable!(), + }; + let d = key.to_be_bytes(); + EcPrivateParameters { + crv: C::CRV, + x: x.to_vec(), + y: y.to_vec(), + d: d.to_vec(), + } + } + } +} + +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub struct OkpPrivateParameters { + crv: JsonWebKeyOkpEllipticCurve, + + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + x: Vec, +} + diff --git a/crates/jose/src/jwk/public_parameters.rs b/crates/jose/src/jwk/public_parameters.rs new file mode 100644 index 00000000..7c1dfb12 --- /dev/null +++ b/crates/jose/src/jwk/public_parameters.rs @@ -0,0 +1,253 @@ +// Copyright 2022 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use mas_iana::jose::{JsonWebKeyEcEllipticCurve, JsonWebKeyOkpEllipticCurve}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use serde_with::{ + base64::{Base64, UrlSafe}, + formats::Unpadded, + serde_as, +}; + +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +#[serde(tag = "kty")] +pub enum JsonWebKeyPublicParameters { + #[serde(rename = "RSA")] + Rsa(RsaPublicParameters), + + #[serde(rename = "EC")] + Ec(EcPublicParameters), + + #[serde(rename = "OKP")] + Okp(OkpPublicParameters), +} + +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub struct RsaPublicParameters { + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + n: Vec, + + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + e: Vec, +} + +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub struct EcPublicParameters { + pub(crate) crv: JsonWebKeyEcEllipticCurve, + + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + x: Vec, + + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + y: Vec, +} + +#[serde_as] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +pub struct OkpPublicParameters { + crv: JsonWebKeyOkpEllipticCurve, + + #[schemars(with = "String")] + #[serde_as(as = "Base64")] + x: Vec, +} + +impl EcPublicParameters { + pub const fn crv(&self) -> JsonWebKeyEcEllipticCurve { + self.crv + } +} + +mod rsa_impls { + use rsa::{BigUint, RsaPublicKey}; + + use super::RsaPublicParameters; + + impl TryFrom for RsaPublicKey { + type Error = rsa::errors::Error; + fn try_from(value: RsaPublicParameters) -> Result { + (&value).try_into() + } + } + + impl TryFrom<&RsaPublicParameters> for RsaPublicKey { + type Error = rsa::errors::Error; + fn try_from(value: &RsaPublicParameters) -> Result { + let n = BigUint::from_bytes_be(&value.n); + let e = BigUint::from_bytes_be(&value.e); + let key = RsaPublicKey::new(n, e)?; + Ok(key) + } + } +} + +mod ec_impls { + use digest::typenum::Unsigned; + use ecdsa::{EncodedPoint, PrimeCurve, VerifyingKey}; + use elliptic_curve::{ + sec1::{Coordinates, FromEncodedPoint, ModulusSize, ToEncodedPoint}, + AffinePoint, Curve, FieldBytes, FieldSize, ProjectiveArithmetic, PublicKey, + }; + + use super::{super::JwkEcCurve, EcPublicParameters}; + + impl TryFrom for VerifyingKey + where + C: PrimeCurve + ProjectiveArithmetic + JwkEcCurve, + AffinePoint: FromEncodedPoint + ToEncodedPoint, + FieldSize: ModulusSize, + { + type Error = ecdsa::Error; + fn try_from(value: EcPublicParameters) -> Result { + (&value).try_into() + } + } + + impl TryFrom<&EcPublicParameters> for VerifyingKey + where + C: PrimeCurve + ProjectiveArithmetic + JwkEcCurve, + AffinePoint: FromEncodedPoint + ToEncodedPoint, + FieldSize: ModulusSize, + { + type Error = ecdsa::Error; + + fn try_from(value: &EcPublicParameters) -> Result { + if value.crv() != C::CRV { + return Err(Self::Error::default()); + } + + let x = value + .x + .get(..FieldSize::::USIZE) + .ok_or_else(Self::Error::default)?; + let y = value + .x + .get(..FieldSize::::USIZE) + .ok_or_else(Self::Error::default)?; + + let x = FieldBytes::::from_slice(x); + let y = FieldBytes::::from_slice(y); + let pubkey = EncodedPoint::::from_affine_coordinates(x, y, false); + let pubkey = VerifyingKey::from_encoded_point(&pubkey)?; + Ok(pubkey) + } + } + + impl From> for EcPublicParameters + where + C: Curve + elliptic_curve::ProjectiveArithmetic + JwkEcCurve, + AffinePoint: FromEncodedPoint + ToEncodedPoint, + FieldSize: ModulusSize, + { + fn from(key: PublicKey) -> Self { + (&key).into() + } + } + + impl From<&PublicKey> for EcPublicParameters + where + C: Curve + elliptic_curve::ProjectiveArithmetic + JwkEcCurve, + AffinePoint: FromEncodedPoint + ToEncodedPoint, + FieldSize: ModulusSize, + { + fn from(key: &PublicKey) -> Self { + let point = key.to_encoded_point(false); + let (x, y) = match point.coordinates() { + Coordinates::Uncompressed { x, y } => (x, y), + _ => unreachable!(), + }; + EcPublicParameters { + crv: C::CRV, + x: x.to_vec(), + y: y.to_vec(), + } + } + } +} + +/// Some legacy implementations to remove +mod legacy { + use anyhow::bail; + use mas_iana::jose::JsonWebKeyEcEllipticCurve; + use p256::NistP256; + use rsa::{BigUint, PublicKeyParts}; + + use super::{EcPublicParameters, JsonWebKeyPublicParameters, RsaPublicParameters}; + + impl TryFrom for ecdsa::VerifyingKey { + type Error = anyhow::Error; + + fn try_from(params: JsonWebKeyPublicParameters) -> Result { + let (x, y): ([u8; 32], [u8; 32]) = match params { + JsonWebKeyPublicParameters::Ec(EcPublicParameters { + x, + y, + crv: JsonWebKeyEcEllipticCurve::P256, + }) => ( + x.try_into() + .map_err(|_| anyhow::anyhow!("invalid curve parameter x"))?, + y.try_into() + .map_err(|_| anyhow::anyhow!("invalid curve parameter y"))?, + ), + _ => bail!("Wrong key type"), + }; + + let point = sec1::EncodedPoint::from_affine_coordinates(&x.into(), &y.into(), false); + let key = ecdsa::VerifyingKey::from_encoded_point(&point)?; + Ok(key) + } + } + + impl From> for JsonWebKeyPublicParameters { + fn from(key: ecdsa::VerifyingKey) -> Self { + let points = key.to_encoded_point(false); + JsonWebKeyPublicParameters::Ec(EcPublicParameters { + x: points.x().unwrap().to_vec(), + y: points.y().unwrap().to_vec(), + crv: JsonWebKeyEcEllipticCurve::P256, + }) + } + } + + impl TryFrom for rsa::RsaPublicKey { + type Error = anyhow::Error; + + fn try_from(params: JsonWebKeyPublicParameters) -> Result { + let (n, e) = match ¶ms { + JsonWebKeyPublicParameters::Rsa(RsaPublicParameters { n, e }) => (n, e), + _ => bail!("Wrong key type"), + }; + let n = BigUint::from_bytes_be(n); + let e = BigUint::from_bytes_be(e); + Ok(rsa::RsaPublicKey::new(n, e)?) + } + } + + impl From for JsonWebKeyPublicParameters { + fn from(key: rsa::RsaPublicKey) -> Self { + JsonWebKeyPublicParameters::Rsa(RsaPublicParameters { + n: key.n().to_bytes_be(), + e: key.e().to_bytes_be(), + }) + } + } +} diff --git a/crates/jose/src/verifier.rs b/crates/jose/src/verifier.rs index 8318f16e..556dde45 100644 --- a/crates/jose/src/verifier.rs +++ b/crates/jose/src/verifier.rs @@ -13,12 +13,11 @@ // limitations under the License. use mas_iana::jose::{JsonWebKeyEcEllipticCurve, JsonWebSignatureAlg}; -use rsa::BigUint; use sha2::{Sha256, Sha384, Sha512}; use signature::Signature; use thiserror::Error; -use crate::jwk::JsonWebKeyParameters; +use crate::jwk::{public_parameters::EcPublicParameters, JsonWebKeyParameters}; pub enum Verifier { Hs256 { @@ -104,135 +103,91 @@ impl Verifier { } } - #[allow(clippy::too_many_lines)] pub fn for_jwk_and_alg( key: &JsonWebKeyParameters, alg: JsonWebSignatureAlg, ) -> Result { match (key, alg) { - (JsonWebKeyParameters::Rsa { n, e }, JsonWebSignatureAlg::Rs256) => { - let n = BigUint::from_bytes_be(n); - let e = BigUint::from_bytes_be(e); - let key = rsa::RsaPublicKey::new(n, e)?; + (JsonWebKeyParameters::Rsa(params), JsonWebSignatureAlg::Rs256) => { + let key = rsa::RsaPublicKey::try_from(params)?; Ok(Self::Rs256 { key: key.into() }) } - (JsonWebKeyParameters::Rsa { n, e }, JsonWebSignatureAlg::Rs384) => { - let n = BigUint::from_bytes_be(n); - let e = BigUint::from_bytes_be(e); - let key = rsa::RsaPublicKey::new(n, e)?; + (JsonWebKeyParameters::Rsa(params), JsonWebSignatureAlg::Rs384) => { + let key = rsa::RsaPublicKey::try_from(params)?; Ok(Self::Rs384 { key: key.into() }) } - (JsonWebKeyParameters::Rsa { n, e }, JsonWebSignatureAlg::Rs512) => { - let n = BigUint::from_bytes_be(n); - let e = BigUint::from_bytes_be(e); - let key = rsa::RsaPublicKey::new(n, e)?; + (JsonWebKeyParameters::Rsa(params), JsonWebSignatureAlg::Rs512) => { + let key = rsa::RsaPublicKey::try_from(params)?; Ok(Self::Rs512 { key: key.into() }) } - (JsonWebKeyParameters::Rsa { n, e }, JsonWebSignatureAlg::Ps256) => { - let n = BigUint::from_bytes_be(n); - let e = BigUint::from_bytes_be(e); - let key = rsa::RsaPublicKey::new(n, e)?; + (JsonWebKeyParameters::Rsa(params), JsonWebSignatureAlg::Ps256) => { + let key = rsa::RsaPublicKey::try_from(params)?; Ok(Self::Ps256 { key: key.into() }) } - (JsonWebKeyParameters::Rsa { n, e }, JsonWebSignatureAlg::Ps384) => { - let n = BigUint::from_bytes_be(n); - let e = BigUint::from_bytes_be(e); - let key = rsa::RsaPublicKey::new(n, e)?; + (JsonWebKeyParameters::Rsa(params), JsonWebSignatureAlg::Ps384) => { + let key = rsa::RsaPublicKey::try_from(params)?; Ok(Self::Ps384 { key: key.into() }) } - (JsonWebKeyParameters::Rsa { n, e }, JsonWebSignatureAlg::Ps512) => { - let n = BigUint::from_bytes_be(n); - let e = BigUint::from_bytes_be(e); - let key = rsa::RsaPublicKey::new(n, e)?; + (JsonWebKeyParameters::Rsa(params), JsonWebSignatureAlg::Ps512) => { + let key = rsa::RsaPublicKey::try_from(params)?; Ok(Self::Ps512 { key: key.into() }) } ( - JsonWebKeyParameters::Ec { - crv: JsonWebKeyEcEllipticCurve::P256, - x, - y, - }, + JsonWebKeyParameters::Ec( + params @ EcPublicParameters { + crv: JsonWebKeyEcEllipticCurve::P256, + .. + }, + ), JsonWebSignatureAlg::Es256, ) => { - let x: &[u8; 32] = x - .as_slice() - .try_into() - .map_err(|_| VerifierFromJwkError::InvalidCurveParameterX)?; - let y: &[u8; 32] = y - .as_slice() - .try_into() - .map_err(|_| VerifierFromJwkError::InvalidCurveParameterY)?; - - let point = sec1::EncodedPoint::from_affine_coordinates(x.into(), y.into(), false); - let key = ecdsa::VerifyingKey::from_encoded_point(&point)?; - + let key = ecdsa::VerifyingKey::try_from(params)?; Ok(Self::Es256 { key }) } ( - JsonWebKeyParameters::Ec { - crv: JsonWebKeyEcEllipticCurve::P384, - x, - y, - }, + JsonWebKeyParameters::Ec( + params @ EcPublicParameters { + crv: JsonWebKeyEcEllipticCurve::P384, + .. + }, + ), JsonWebSignatureAlg::Es384, ) => { - let x: &[u8; 48] = x - .as_slice() - .try_into() - .map_err(|_| VerifierFromJwkError::InvalidCurveParameterX)?; - let y: &[u8; 48] = y - .as_slice() - .try_into() - .map_err(|_| VerifierFromJwkError::InvalidCurveParameterY)?; - - let point = sec1::EncodedPoint::from_affine_coordinates(x.into(), y.into(), false); - let key = ecdsa::VerifyingKey::from_encoded_point(&point)?; - + let key = ecdsa::VerifyingKey::try_from(params)?; Ok(Self::Es384 { key }) } ( - JsonWebKeyParameters::Ec { + JsonWebKeyParameters::Ec(EcPublicParameters { crv: JsonWebKeyEcEllipticCurve::P521, - x: _, - y: _, - }, + .. + }), JsonWebSignatureAlg::Es512, ) => Err(VerifierFromJwkError::UnsupportedAlgorithm { algorithm: JsonWebSignatureAlg::Es512, }), ( - JsonWebKeyParameters::Ec { - crv: JsonWebKeyEcEllipticCurve::Secp256K1, - x, - y, - }, + JsonWebKeyParameters::Ec( + params @ EcPublicParameters { + crv: JsonWebKeyEcEllipticCurve::Secp256K1, + .. + }, + ), JsonWebSignatureAlg::Es256K, ) => { - let x: &[u8; 32] = x - .as_slice() - .try_into() - .map_err(|_| VerifierFromJwkError::InvalidCurveParameterX)?; - let y: &[u8; 32] = y - .as_slice() - .try_into() - .map_err(|_| VerifierFromJwkError::InvalidCurveParameterY)?; - - let point = sec1::EncodedPoint::from_affine_coordinates(x.into(), y.into(), false); - let key = ecdsa::VerifyingKey::from_encoded_point(&point)?; - + let key = ecdsa::VerifyingKey::try_from(params)?; Ok(Self::Es256K { key }) } - (JsonWebKeyParameters::Okp { crv: _, x: _ }, JsonWebSignatureAlg::EdDsa) => { + (JsonWebKeyParameters::Okp(_params), JsonWebSignatureAlg::EdDsa) => { Err(VerifierFromJwkError::UnsupportedAlgorithm { algorithm: JsonWebSignatureAlg::EdDsa, })