mod serde_utils;
mod source;
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
use bon::Builder;
use serde::{Deserialize, Serialize};
use sha2::{Digest as _, Sha256};
pub use source::JwksSource;
use zeroize::Zeroize;
use crate::jwk::serde_utils::{
base64url, base64url_uint, option_base64url, option_base64url_uint, trim_leading_zeros,
};
#[non_exhaustive]
#[derive(Debug, Serialize, PartialEq, Clone)]
pub struct PublicJwks {
pub keys: Vec<PublicJwk>,
}
impl PublicJwks {
#[must_use]
pub fn new(keys: Vec<PublicJwk>) -> Self {
Self { keys }
}
}
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, Builder, PartialEq, Clone)]
#[builder(derive(Into))]
pub struct PublicJwk {
#[builder(into)]
#[serde(flatten)]
pub key: PublicKey,
#[serde(rename = "use", skip_serializing_if = "Option::is_none")]
pub key_use: Option<KeyUse>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(with = <_>::from_iter)]
#[serde(rename = "key_ops")]
pub key_operations: Option<Vec<KeyOperation>>,
#[builder(into)]
#[serde(rename = "alg", skip_serializing_if = "Option::is_none")]
pub algorithm: Option<String>,
#[builder(into)]
#[serde(skip_serializing_if = "Option::is_none")]
pub kid: Option<String>,
#[builder(skip)]
#[serde(rename = "x5u", default, skip_serializing)]
pub x5u: Option<String>,
}
impl PublicJwk {
#[must_use]
pub fn thumbprint(&self) -> String {
let canonical_form = match &self.key {
PublicKey::Rsa(rsa) => rsa.canonical_form(),
PublicKey::Ec(ec) => ec.canonical_form(),
PublicKey::Okp(okp) => okp.canonical_form(),
};
let mut hasher = Sha256::new();
hasher.update(canonical_form.as_bytes());
URL_SAFE_NO_PAD.encode(hasher.finalize())
}
}
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy)]
pub enum KeyUse {
#[serde(rename = "sig")]
Sign,
#[serde(rename = "enc")]
Encrypt,
#[serde(skip_serializing, other)]
Unknown,
}
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy)]
#[serde(rename_all = "camelCase")]
pub enum KeyOperation {
Sign,
Verify,
Encrypt,
Decrypt,
WrapKey,
UnwrapKey,
DeriveKey,
DeriveBits,
#[serde(skip_serializing, other)]
Unknown,
}
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
#[serde(tag = "kty")] pub enum PublicKey {
#[serde(rename = "RSA")]
Rsa(RsaPublicKey),
#[serde(rename = "EC")]
Ec(EcPublicKey),
#[serde(rename = "OKP")]
Okp(OkpPublicKey),
}
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, Builder, PartialEq, Clone)]
#[builder(derive(Into))]
pub struct RsaPublicKey {
#[builder(with = <_>::from_iter)]
#[serde(with = "base64url_uint")]
pub n: Vec<u8>,
#[builder(with = <_>::from_iter)]
#[serde(with = "base64url_uint")]
pub e: Vec<u8>,
}
impl RsaPublicKey {
pub(super) fn canonical_form(&self) -> String {
let e = URL_SAFE_NO_PAD.encode(trim_leading_zeros(&self.e));
let n = URL_SAFE_NO_PAD.encode(trim_leading_zeros(&self.n));
format!(r#"{{"e":"{e}","kty":"RSA","n":"{n}"}}"#)
}
}
impl From<RsaPublicKey> for PublicKey {
fn from(value: RsaPublicKey) -> Self {
Self::Rsa(value)
}
}
impl<S: rsa_public_key_builder::State> From<RsaPublicKeyBuilder<S>> for PublicKey
where
S: rsa_public_key_builder::IsComplete,
{
fn from(value: RsaPublicKeyBuilder<S>) -> Self {
Self::Rsa(value.build())
}
}
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, Builder, PartialEq, Clone)]
#[builder(derive(Into))]
pub struct EcPublicKey {
#[builder(into)]
pub crv: String,
#[builder(with = <_>::from_iter)]
#[serde(with = "base64url")]
pub x: Vec<u8>,
#[builder(with = <_>::from_iter)]
#[serde(with = "base64url")]
pub y: Vec<u8>,
}
impl EcPublicKey {
pub(super) fn canonical_form(&self) -> String {
let crv = serde_json::to_string(&self.crv).unwrap();
let x = URL_SAFE_NO_PAD.encode(&self.x);
let y = URL_SAFE_NO_PAD.encode(&self.y);
format!(r#"{{"crv":{crv},"kty":"EC","x":"{x}","y":"{y}"}}"#)
}
}
impl From<EcPublicKey> for PublicKey {
fn from(value: EcPublicKey) -> Self {
Self::Ec(value)
}
}
impl<S: ec_public_key_builder::State> From<EcPublicKeyBuilder<S>> for PublicKey
where
S: ec_public_key_builder::IsComplete,
{
fn from(value: EcPublicKeyBuilder<S>) -> Self {
Self::Ec(value.build())
}
}
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, Builder, PartialEq, Clone)]
#[builder(derive(Into))]
pub struct OkpPublicKey {
#[builder(into)]
pub crv: String,
#[builder(with = <_>::from_iter)]
#[serde(with = "base64url")]
pub x: Vec<u8>,
}
impl OkpPublicKey {
pub(super) fn canonical_form(&self) -> String {
let crv = serde_json::to_string(&self.crv).unwrap();
let x = URL_SAFE_NO_PAD.encode(&self.x);
format!(r#"{{"crv":{crv},"kty":"OKP","x":"{x}"}}"#)
}
}
impl From<OkpPublicKey> for PublicKey {
fn from(value: OkpPublicKey) -> Self {
Self::Okp(value)
}
}
impl<S: okp_public_key_builder::State> From<OkpPublicKeyBuilder<S>> for PublicKey
where
S: okp_public_key_builder::IsComplete,
{
fn from(value: OkpPublicKeyBuilder<S>) -> Self {
Self::Okp(value.build())
}
}
#[non_exhaustive]
#[derive(Serialize, Deserialize, Builder, PartialEq, Clone)]
pub struct OtherPrimeInfo {
#[builder(with = <_>::from_iter)]
#[serde(with = "base64url_uint")]
pub r: Vec<u8>,
#[builder(with = <_>::from_iter)]
#[serde(with = "base64url_uint")]
pub d: Vec<u8>,
#[builder(with = <_>::from_iter)]
#[serde(with = "base64url_uint")]
pub t: Vec<u8>,
}
impl std::fmt::Debug for OtherPrimeInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OtherPrimeInfo").finish_non_exhaustive()
}
}
impl Zeroize for OtherPrimeInfo {
fn zeroize(&mut self) {
self.r.zeroize();
self.d.zeroize();
self.t.zeroize();
}
}
impl Drop for OtherPrimeInfo {
fn drop(&mut self) {
self.zeroize();
}
}
#[non_exhaustive]
#[derive(Serialize, Deserialize, Builder, PartialEq, Clone)]
#[builder(derive(Into))]
pub struct RsaKey {
#[serde(flatten)]
#[builder(into)]
pub public: RsaPublicKey,
#[builder(with = <_>::from_iter)]
#[serde(
with = "option_base64url_uint",
skip_serializing_if = "Option::is_none",
default
)]
pub d: Option<Vec<u8>>,
#[builder(with = <_>::from_iter)]
#[serde(
with = "option_base64url_uint",
skip_serializing_if = "Option::is_none",
default
)]
pub p: Option<Vec<u8>>,
#[builder(with = <_>::from_iter)]
#[serde(
with = "option_base64url_uint",
skip_serializing_if = "Option::is_none",
default
)]
pub q: Option<Vec<u8>>,
#[builder(with = <_>::from_iter)]
#[serde(
with = "option_base64url_uint",
skip_serializing_if = "Option::is_none",
default
)]
pub dp: Option<Vec<u8>>,
#[builder(with = <_>::from_iter)]
#[serde(
with = "option_base64url_uint",
skip_serializing_if = "Option::is_none",
default
)]
pub dq: Option<Vec<u8>>,
#[builder(with = <_>::from_iter)]
#[serde(
with = "option_base64url_uint",
skip_serializing_if = "Option::is_none",
default
)]
pub qi: Option<Vec<u8>>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub oth: Option<Vec<OtherPrimeInfo>>,
}
impl std::fmt::Debug for RsaKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RsaKey")
.field("public", &self.public)
.finish_non_exhaustive()
}
}
impl Zeroize for RsaKey {
fn zeroize(&mut self) {
self.d.zeroize();
self.p.zeroize();
self.q.zeroize();
self.dp.zeroize();
self.dq.zeroize();
self.qi.zeroize();
if let Some(oth) = &mut self.oth {
for info in oth.iter_mut() {
info.zeroize();
}
}
}
}
impl Drop for RsaKey {
fn drop(&mut self) {
self.zeroize();
}
}
impl From<RsaKey> for RsaPublicKey {
fn from(mut key: RsaKey) -> Self {
std::mem::replace(
&mut key.public,
RsaPublicKey {
n: vec![],
e: vec![],
},
)
}
}
impl From<RsaKey> for Key {
fn from(value: RsaKey) -> Self {
Self::Rsa(value)
}
}
impl<S: rsa_key_builder::State> From<RsaKeyBuilder<S>> for Key
where
S: rsa_key_builder::IsComplete,
{
fn from(value: RsaKeyBuilder<S>) -> Self {
Self::Rsa(value.build())
}
}
#[non_exhaustive]
#[derive(Serialize, Deserialize, Builder, PartialEq, Clone)]
#[builder(derive(Into))]
pub struct EcKey {
#[serde(flatten)]
#[builder(into)]
pub public: EcPublicKey,
#[builder(with = <_>::from_iter)]
#[serde(
with = "option_base64url",
skip_serializing_if = "Option::is_none",
default
)]
pub d: Option<Vec<u8>>,
}
impl std::fmt::Debug for EcKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EcKey")
.field("public", &self.public)
.finish_non_exhaustive()
}
}
impl Zeroize for EcKey {
fn zeroize(&mut self) {
self.d.zeroize();
}
}
impl Drop for EcKey {
fn drop(&mut self) {
self.zeroize();
}
}
impl From<EcKey> for EcPublicKey {
fn from(mut key: EcKey) -> Self {
std::mem::replace(
&mut key.public,
EcPublicKey {
crv: String::new(),
x: vec![],
y: vec![],
},
)
}
}
impl From<EcKey> for Key {
fn from(value: EcKey) -> Self {
Self::Ec(value)
}
}
impl<S: ec_key_builder::State> From<EcKeyBuilder<S>> for Key
where
S: ec_key_builder::IsComplete,
{
fn from(value: EcKeyBuilder<S>) -> Self {
Self::Ec(value.build())
}
}
#[non_exhaustive]
#[derive(Serialize, Deserialize, Builder, PartialEq, Clone)]
#[builder(derive(Into))]
pub struct OkpKey {
#[serde(flatten)]
#[builder(into)]
pub public: OkpPublicKey,
#[builder(with = <_>::from_iter)]
#[serde(
with = "option_base64url",
skip_serializing_if = "Option::is_none",
default
)]
pub d: Option<Vec<u8>>,
}
impl std::fmt::Debug for OkpKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OkpKey")
.field("public", &self.public)
.finish_non_exhaustive()
}
}
impl Zeroize for OkpKey {
fn zeroize(&mut self) {
self.d.zeroize();
}
}
impl Drop for OkpKey {
fn drop(&mut self) {
self.zeroize();
}
}
impl From<OkpKey> for OkpPublicKey {
fn from(mut key: OkpKey) -> Self {
std::mem::replace(
&mut key.public,
OkpPublicKey {
crv: String::new(),
x: vec![],
},
)
}
}
impl From<OkpKey> for Key {
fn from(value: OkpKey) -> Self {
Self::Okp(value)
}
}
impl<S: okp_key_builder::State> From<OkpKeyBuilder<S>> for Key
where
S: okp_key_builder::IsComplete,
{
fn from(value: OkpKeyBuilder<S>) -> Self {
Self::Okp(value.build())
}
}
#[non_exhaustive]
#[derive(Serialize, Deserialize, Builder, PartialEq, Clone)]
#[builder(derive(Into))]
pub struct OctKey {
#[builder(with = <_>::from_iter)]
#[serde(with = "base64url")]
pub k: Vec<u8>,
}
impl std::fmt::Debug for OctKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OctKey").finish_non_exhaustive()
}
}
impl Zeroize for OctKey {
fn zeroize(&mut self) {
self.k.zeroize();
}
}
impl Drop for OctKey {
fn drop(&mut self) {
self.zeroize();
}
}
impl From<OctKey> for Key {
fn from(value: OctKey) -> Self {
Self::Oct(value)
}
}
impl<S: oct_key_builder::State> From<OctKeyBuilder<S>> for Key
where
S: oct_key_builder::IsComplete,
{
fn from(value: OctKeyBuilder<S>) -> Self {
Self::Oct(value.build())
}
}
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
#[serde(tag = "kty")]
pub enum Key {
#[serde(rename = "RSA")]
Rsa(RsaKey),
#[serde(rename = "EC")]
Ec(EcKey),
#[serde(rename = "OKP")]
Okp(OkpKey),
#[serde(rename = "oct")]
Oct(OctKey),
#[serde(skip_serializing, other)]
Unknown,
}
impl Key {
#[must_use]
pub fn public_key(&self) -> Option<PublicKey> {
match self {
Key::Rsa(rsa) => Some(PublicKey::Rsa(rsa.public.clone())),
Key::Ec(ec) => Some(PublicKey::Ec(ec.public.clone())),
Key::Okp(okp) => Some(PublicKey::Okp(okp.public.clone())),
Key::Oct(_) | Key::Unknown => None,
}
}
#[must_use]
pub fn private_key(&self) -> Option<PrivateKey> {
match self {
Key::Rsa(rsa) => rsa.private_key().map(PrivateKey::Rsa),
Key::Ec(ec) => ec.private_key().map(PrivateKey::Ec),
Key::Okp(okp) => okp.private_key().map(PrivateKey::Okp),
Key::Oct(_) | Key::Unknown => None,
}
}
}
#[non_exhaustive]
#[derive(PartialEq, Clone)]
pub struct RsaPrivateKey {
pub public: RsaPublicKey,
pub d: Vec<u8>,
pub p: Option<Vec<u8>>,
pub q: Option<Vec<u8>>,
pub dp: Option<Vec<u8>>,
pub dq: Option<Vec<u8>>,
pub qi: Option<Vec<u8>>,
pub oth: Option<Vec<OtherPrimeInfo>>,
}
impl std::fmt::Debug for RsaPrivateKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RsaPrivateKey")
.field("public", &self.public)
.finish_non_exhaustive()
}
}
impl Zeroize for RsaPrivateKey {
fn zeroize(&mut self) {
self.d.zeroize();
self.p.zeroize();
self.q.zeroize();
self.dp.zeroize();
self.dq.zeroize();
self.qi.zeroize();
if let Some(oth) = &mut self.oth {
for info in oth.iter_mut() {
info.zeroize();
}
}
}
}
impl Drop for RsaPrivateKey {
fn drop(&mut self) {
self.zeroize();
}
}
#[non_exhaustive]
#[derive(PartialEq, Clone)]
pub struct EcPrivateKey {
pub public: EcPublicKey,
pub d: Vec<u8>,
}
impl std::fmt::Debug for EcPrivateKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EcPrivateKey")
.field("public", &self.public)
.finish_non_exhaustive()
}
}
impl Zeroize for EcPrivateKey {
fn zeroize(&mut self) {
self.d.zeroize();
}
}
impl Drop for EcPrivateKey {
fn drop(&mut self) {
self.zeroize();
}
}
#[non_exhaustive]
#[derive(PartialEq, Clone)]
pub struct OkpPrivateKey {
pub public: OkpPublicKey,
pub d: Vec<u8>,
}
impl std::fmt::Debug for OkpPrivateKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OkpPrivateKey")
.field("public", &self.public)
.finish_non_exhaustive()
}
}
impl Zeroize for OkpPrivateKey {
fn zeroize(&mut self) {
self.d.zeroize();
}
}
impl Drop for OkpPrivateKey {
fn drop(&mut self) {
self.zeroize();
}
}
#[non_exhaustive]
#[derive(Debug, PartialEq, Clone)]
pub enum PrivateKey {
Rsa(RsaPrivateKey),
Ec(EcPrivateKey),
Okp(OkpPrivateKey),
}
impl PrivateKey {
#[must_use]
pub fn public_key(&self) -> PublicKey {
match self {
PrivateKey::Rsa(rsa) => PublicKey::Rsa(rsa.public.clone()),
PrivateKey::Ec(ec) => PublicKey::Ec(ec.public.clone()),
PrivateKey::Okp(okp) => PublicKey::Okp(okp.public.clone()),
}
}
}
impl From<RsaPrivateKey> for PrivateKey {
fn from(value: RsaPrivateKey) -> Self {
Self::Rsa(value)
}
}
impl From<EcPrivateKey> for PrivateKey {
fn from(value: EcPrivateKey) -> Self {
Self::Ec(value)
}
}
impl From<OkpPrivateKey> for PrivateKey {
fn from(value: OkpPrivateKey) -> Self {
Self::Okp(value)
}
}
impl From<RsaPrivateKey> for RsaKey {
fn from(mut key: RsaPrivateKey) -> Self {
Self {
public: std::mem::replace(
&mut key.public,
RsaPublicKey {
n: vec![],
e: vec![],
},
),
d: Some(std::mem::take(&mut key.d)),
p: key.p.take(),
q: key.q.take(),
dp: key.dp.take(),
dq: key.dq.take(),
qi: key.qi.take(),
oth: key.oth.take(),
}
}
}
impl From<EcPrivateKey> for EcKey {
fn from(mut key: EcPrivateKey) -> Self {
Self {
public: std::mem::replace(
&mut key.public,
EcPublicKey {
crv: String::new(),
x: vec![],
y: vec![],
},
),
d: Some(std::mem::take(&mut key.d)),
}
}
}
impl From<OkpPrivateKey> for OkpKey {
fn from(mut key: OkpPrivateKey) -> Self {
Self {
public: std::mem::replace(
&mut key.public,
OkpPublicKey {
crv: String::new(),
x: vec![],
},
),
d: Some(std::mem::take(&mut key.d)),
}
}
}
impl From<PrivateKey> for Key {
fn from(value: PrivateKey) -> Self {
match value {
PrivateKey::Rsa(rsa) => Key::Rsa(rsa.into()),
PrivateKey::Ec(ec) => Key::Ec(ec.into()),
PrivateKey::Okp(okp) => Key::Okp(okp.into()),
}
}
}
impl From<RsaPrivateKey> for RsaPublicKey {
fn from(mut key: RsaPrivateKey) -> Self {
std::mem::replace(
&mut key.public,
RsaPublicKey {
n: vec![],
e: vec![],
},
)
}
}
impl From<EcPrivateKey> for EcPublicKey {
fn from(mut key: EcPrivateKey) -> Self {
std::mem::replace(
&mut key.public,
EcPublicKey {
crv: String::new(),
x: vec![],
y: vec![],
},
)
}
}
impl From<OkpPrivateKey> for OkpPublicKey {
fn from(mut key: OkpPrivateKey) -> Self {
std::mem::replace(
&mut key.public,
OkpPublicKey {
crv: String::new(),
x: vec![],
},
)
}
}
impl From<PrivateKey> for PublicKey {
fn from(value: PrivateKey) -> Self {
value.public_key()
}
}
impl RsaKey {
#[must_use]
pub fn private_key(&self) -> Option<RsaPrivateKey> {
Some(RsaPrivateKey {
public: self.public.clone(),
d: self.d.clone()?,
p: self.p.clone(),
q: self.q.clone(),
dp: self.dp.clone(),
dq: self.dq.clone(),
qi: self.qi.clone(),
oth: self.oth.clone(),
})
}
}
impl EcKey {
#[must_use]
pub fn private_key(&self) -> Option<EcPrivateKey> {
Some(EcPrivateKey {
public: self.public.clone(),
d: self.d.clone()?,
})
}
}
impl OkpKey {
#[must_use]
pub fn private_key(&self) -> Option<OkpPrivateKey> {
Some(OkpPrivateKey {
public: self.public.clone(),
d: self.d.clone()?,
})
}
}
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, Builder, PartialEq, Clone)]
#[builder(derive(Into))]
pub struct Jwk {
#[builder(into)]
#[serde(flatten)]
pub key: Key,
#[serde(rename = "use", skip_serializing_if = "Option::is_none")]
pub key_use: Option<KeyUse>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(with = <_>::from_iter)]
#[serde(rename = "key_ops")]
pub key_operations: Option<Vec<KeyOperation>>,
#[builder(into)]
#[serde(rename = "alg", skip_serializing_if = "Option::is_none")]
pub algorithm: Option<String>,
#[builder(into)]
#[serde(skip_serializing_if = "Option::is_none")]
pub kid: Option<String>,
#[builder(skip)]
#[serde(rename = "x5u", default, skip_serializing)]
pub x5u: Option<String>,
}
impl Jwk {
#[must_use]
pub fn public_jwk(&self) -> Option<PublicJwk> {
self.key.public_key().map(|key| PublicJwk {
key,
key_use: self.key_use,
key_operations: self.key_operations.clone(),
algorithm: self.algorithm.clone(),
kid: self.kid.clone(),
x5u: self.x5u.clone(),
})
}
#[must_use]
pub fn private_key(&self) -> Option<PrivateKey> {
self.key.private_key()
}
#[must_use]
pub fn private_jwk(&self) -> Option<PrivateJwk> {
self.key.private_key().map(|key| PrivateJwk {
key,
key_use: self.key_use,
key_operations: self.key_operations.clone(),
algorithm: self.algorithm.clone(),
kid: self.kid.clone(),
x5u: self.x5u.clone(),
})
}
}
#[non_exhaustive]
#[derive(Debug, Builder, PartialEq, Clone)]
#[builder(derive(Into))]
pub struct PrivateJwk {
#[builder(into)]
pub key: PrivateKey,
pub key_use: Option<KeyUse>,
#[builder(with = <_>::from_iter)]
pub key_operations: Option<Vec<KeyOperation>>,
#[builder(into)]
pub algorithm: Option<String>,
#[builder(into)]
pub kid: Option<String>,
#[builder(skip)]
pub x5u: Option<String>,
}
impl PrivateJwk {
#[must_use]
pub fn public_jwk(&self) -> PublicJwk {
PublicJwk {
key: self.key.public_key(),
key_use: self.key_use,
key_operations: self.key_operations.clone(),
algorithm: self.algorithm.clone(),
kid: self.kid.clone(),
x5u: self.x5u.clone(),
}
}
#[must_use]
pub fn thumbprint(&self) -> String {
self.public_jwk().thumbprint()
}
}
impl From<PrivateJwk> for Jwk {
fn from(pjwk: PrivateJwk) -> Self {
Self {
key: pjwk.key.into(),
key_use: pjwk.key_use,
key_operations: pjwk.key_operations,
algorithm: pjwk.algorithm,
kid: pjwk.kid,
x5u: pjwk.x5u,
}
}
}
impl From<PrivateJwk> for PublicJwk {
fn from(pjwk: PrivateJwk) -> Self {
pjwk.public_jwk()
}
}
#[non_exhaustive]
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct Jwks {
pub keys: Vec<Jwk>,
}
impl Jwks {
#[must_use]
pub fn new(keys: Vec<Jwk>) -> Self {
Self { keys }
}
}
impl From<Jwks> for PublicJwks {
fn from(jwks: Jwks) -> Self {
PublicJwks::new(jwks.keys.iter().filter_map(Jwk::public_jwk).collect())
}
}
#[cfg(test)]
mod tests;