1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

Prepare the private JWK

This commit is contained in:
Quentin Gliech
2022-08-26 18:25:25 +02:00
parent 956556b0ff
commit 6636cdcf49
4 changed files with 578 additions and 199 deletions

View File

@ -14,13 +14,10 @@
//! Ref: <https://www.rfc-editor.org/rfc/rfc7517.html>
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<UrlSafe, Unpadded>")]
n: Vec<u8>,
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
e: Vec<u8>,
},
#[serde(rename = "EC")]
Ec {
crv: JsonWebKeyEcEllipticCurve,
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
x: Vec<u8>,
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
y: Vec<u8>,
},
#[serde(rename = "OKP")]
Okp {
crv: JsonWebKeyOkpEllipticCurve,
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
x: Vec<u8>,
},
}
impl TryFrom<JsonWebKeyParameters> for ecdsa::VerifyingKey<NistP256> {
type Error = anyhow::Error;
fn try_from(params: JsonWebKeyParameters) -> Result<Self, Self::Error> {
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<ecdsa::VerifyingKey<NistP256>> for JsonWebKeyParameters {
fn from(key: ecdsa::VerifyingKey<NistP256>) -> 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<JsonWebKeyParameters> for rsa::RsaPublicKey {
type Error = anyhow::Error;
fn try_from(params: JsonWebKeyParameters) -> Result<Self, Self::Error> {
let (n, e) = match &params {
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<rsa::RsaPublicKey> 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::*;

View File

@ -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<UrlSafe, Unpadded>")]
k: Vec<u8>,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct RsaPrivateParameters {
/// Modulus
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
n: Vec<u8>,
/// Exponent
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
e: Vec<u8>,
/// Private Exponent
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
d: Vec<u8>,
/// First Prime Factor
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
p: Vec<u8>,
/// Second Prime Factor
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
q: Vec<u8>,
/// First Factor CRT Exponent
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
dp: Vec<u8>,
/// Second Factor CRT Exponent
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
dq: Vec<u8>,
/// First CRT Coefficient
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
qi: Vec<u8>,
/// Other Primes Info
#[serde(skip_serializing_if = "Option::is_none")]
oth: Option<Vec<RsaOtherPrimeInfo>>,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
struct RsaOtherPrimeInfo {
/// Prime Factor
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
r: Vec<u8>,
/// Factor CRT Exponent
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
d: Vec<u8>,
/// Factor CRT Coefficient
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
t: Vec<u8>,
}
mod rsa_impls {
use rsa::{BigUint, RsaPrivateKey};
use super::RsaPrivateParameters;
impl TryInto<RsaPrivateKey> for RsaPrivateParameters {
type Error = rsa::errors::Error;
fn try_into(self) -> Result<RsaPrivateKey, Self::Error> {
(&self).try_into()
}
}
impl TryInto<RsaPrivateKey> for &RsaPrivateParameters {
type Error = rsa::errors::Error;
#[allow(clippy::many_single_char_names)]
fn try_into(self) -> Result<RsaPrivateKey, Self::Error> {
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<UrlSafe, Unpadded>")]
x: Vec<u8>,
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
y: Vec<u8>,
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
d: Vec<u8>,
}
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<C> TryInto<SecretKey<C>> for EcPrivateParameters
where
C: Curve + ValidatePublicKey,
FieldSize<C>: ModulusSize,
{
type Error = elliptic_curve::Error;
fn try_into(self) -> Result<SecretKey<C>, Self::Error> {
(&self).try_into()
}
}
impl<C> TryInto<SecretKey<C>> for &EcPrivateParameters
where
C: Curve + ValidatePublicKey,
FieldSize<C>: ModulusSize,
{
type Error = elliptic_curve::Error;
fn try_into(self) -> Result<SecretKey<C>, Self::Error> {
let x = self
.x
.get(..FieldSize::<C>::USIZE)
.ok_or(elliptic_curve::Error)?;
let y = self
.x
.get(..FieldSize::<C>::USIZE)
.ok_or(elliptic_curve::Error)?;
let x = FieldBytes::<C>::from_slice(x);
let y = FieldBytes::<C>::from_slice(y);
let pubkey = EncodedPoint::<C>::from_affine_coordinates(x, y, false);
let privkey = SecretKey::from_be_bytes(&self.d)?;
C::validate_public_key(&privkey, &pubkey)?;
Ok(privkey)
}
}
impl<C> From<SecretKey<C>> for EcPrivateParameters
where
C: Curve + elliptic_curve::ProjectiveArithmetic + JwkEcCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
fn from(key: SecretKey<C>) -> Self {
(&key).into()
}
}
impl<C> From<&SecretKey<C>> for EcPrivateParameters
where
C: Curve + elliptic_curve::ProjectiveArithmetic + JwkEcCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
fn from(key: &SecretKey<C>) -> 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<UrlSafe, Unpadded>")]
x: Vec<u8>,
}

View File

@ -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<UrlSafe, Unpadded>")]
n: Vec<u8>,
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
e: Vec<u8>,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct EcPublicParameters {
pub(crate) crv: JsonWebKeyEcEllipticCurve,
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
x: Vec<u8>,
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
y: Vec<u8>,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct OkpPublicParameters {
crv: JsonWebKeyOkpEllipticCurve,
#[schemars(with = "String")]
#[serde_as(as = "Base64<UrlSafe, Unpadded>")]
x: Vec<u8>,
}
impl EcPublicParameters {
pub const fn crv(&self) -> JsonWebKeyEcEllipticCurve {
self.crv
}
}
mod rsa_impls {
use rsa::{BigUint, RsaPublicKey};
use super::RsaPublicParameters;
impl TryFrom<RsaPublicParameters> for RsaPublicKey {
type Error = rsa::errors::Error;
fn try_from(value: RsaPublicParameters) -> Result<Self, Self::Error> {
(&value).try_into()
}
}
impl TryFrom<&RsaPublicParameters> for RsaPublicKey {
type Error = rsa::errors::Error;
fn try_from(value: &RsaPublicParameters) -> Result<Self, Self::Error> {
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<C> TryFrom<EcPublicParameters> for VerifyingKey<C>
where
C: PrimeCurve + ProjectiveArithmetic + JwkEcCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
type Error = ecdsa::Error;
fn try_from(value: EcPublicParameters) -> Result<Self, Self::Error> {
(&value).try_into()
}
}
impl<C> TryFrom<&EcPublicParameters> for VerifyingKey<C>
where
C: PrimeCurve + ProjectiveArithmetic + JwkEcCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
type Error = ecdsa::Error;
fn try_from(value: &EcPublicParameters) -> Result<Self, Self::Error> {
if value.crv() != C::CRV {
return Err(Self::Error::default());
}
let x = value
.x
.get(..FieldSize::<C>::USIZE)
.ok_or_else(Self::Error::default)?;
let y = value
.x
.get(..FieldSize::<C>::USIZE)
.ok_or_else(Self::Error::default)?;
let x = FieldBytes::<C>::from_slice(x);
let y = FieldBytes::<C>::from_slice(y);
let pubkey = EncodedPoint::<C>::from_affine_coordinates(x, y, false);
let pubkey = VerifyingKey::from_encoded_point(&pubkey)?;
Ok(pubkey)
}
}
impl<C> From<PublicKey<C>> for EcPublicParameters
where
C: Curve + elliptic_curve::ProjectiveArithmetic + JwkEcCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
fn from(key: PublicKey<C>) -> Self {
(&key).into()
}
}
impl<C> From<&PublicKey<C>> for EcPublicParameters
where
C: Curve + elliptic_curve::ProjectiveArithmetic + JwkEcCurve,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
FieldSize<C>: ModulusSize,
{
fn from(key: &PublicKey<C>) -> 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<JsonWebKeyPublicParameters> for ecdsa::VerifyingKey<NistP256> {
type Error = anyhow::Error;
fn try_from(params: JsonWebKeyPublicParameters) -> Result<Self, Self::Error> {
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<ecdsa::VerifyingKey<NistP256>> for JsonWebKeyPublicParameters {
fn from(key: ecdsa::VerifyingKey<NistP256>) -> 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<JsonWebKeyPublicParameters> for rsa::RsaPublicKey {
type Error = anyhow::Error;
fn try_from(params: JsonWebKeyPublicParameters) -> Result<Self, Self::Error> {
let (n, e) = match &params {
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<rsa::RsaPublicKey> for JsonWebKeyPublicParameters {
fn from(key: rsa::RsaPublicKey) -> Self {
JsonWebKeyPublicParameters::Rsa(RsaPublicParameters {
n: key.n().to_bytes_be(),
e: key.e().to_bytes_be(),
})
}
}
}

View File

@ -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<Self, VerifierFromJwkError> {
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,
})