use crate::{jwk::alg_parameters::JwkOctetKeyPairParameters, errors::CustomError};
use serde::{Deserialize, Serialize};
use zkryptium::{schemes::algorithms::{BBS_BLS12381_SHA256, BBS_BLS12381_SHAKE256}, keys::pair::KeyPair};
use super::{alg_parameters::{JwkAlgorithmParameters, Algorithm}, types::KeyPairSubtype};
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Jwk {
#[serde(skip_serializing_if = "Option::is_none", default)]
pub kid: Option<String>,
#[serde(rename = "use", skip_serializing_if = "Option::is_none", default)]
pub pk_use: Option<PKUse>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub key_ops: Option<Vec<KeyOps>>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub alg: Option<Algorithm>,
#[serde(skip_serializing_if = "Option::is_none")]
pub x5u: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub x5c: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub x5t: Option<String>,
#[serde(flatten)]
pub key_params: JwkAlgorithmParameters,
}
impl Jwk {
pub fn generate(key_type: KeyPairSubtype) -> Result<Self, CustomError>{
match key_type {
KeyPairSubtype::BLS12381SHA256 => {
let keypair = KeyPair::<BBS_BLS12381_SHA256>::generate(None, None);
let pk = keypair.public_key().to_bytes();
let sk = keypair.private_key().to_bytes();
let okp_params = JwkOctetKeyPairParameters::new(super::curves::EllipticCurveTypes::Bls12381G2, pk.to_vec(), Some(sk.to_vec()));
let jwk_params = JwkAlgorithmParameters::OctetKeyPair(okp_params);
Ok(Self{kid: None, pk_use: None, key_ops: None, alg: None, x5u: None, x5c: None, x5t: None, key_params: jwk_params })
},
KeyPairSubtype::BLS12381SHAKE256 => {
let keypair = KeyPair::<BBS_BLS12381_SHAKE256>::generate(None, None);
let pk = keypair.public_key().to_bytes();
let sk = keypair.private_key().to_bytes();
let okp_params = JwkOctetKeyPairParameters::new(super::curves::EllipticCurveTypes::Bls12381G2, pk.to_vec(), Some(sk.to_vec()));
let jwk_params = JwkAlgorithmParameters::OctetKeyPair(okp_params);
Ok(Self{kid: None, pk_use: None, key_ops: None, alg: None, x5u: None, x5c: None, x5t: None, key_params: jwk_params })
},
}
}
pub fn set_kid(&mut self, kid: &str) {
self.kid = Some(kid.to_string());
}
pub fn set_pk_use(&mut self, pk_use: PKUse) {
self.pk_use = Some(pk_use);
}
pub fn set_key_ops(&mut self, key_ops: Vec<KeyOps>) {
self.key_ops = Some(key_ops);
}
pub fn set_alg(&mut self, alg: Algorithm) {
self.alg = Some(alg);
}
pub fn set_x5u(&mut self, x5u: &str) {
self.x5u = Some(x5u.to_string());
}
pub fn set_x5c(&mut self, x5c: Vec<&str>) {
self.x5c = Some(x5c.iter().map(|v| v.to_string()).collect());
}
pub fn set_x5t(&mut self, x5t: &str) {
self.x5t = Some(x5t.to_string());
}
pub fn is_public(&self) -> bool {
self.key_params.is_public()
}
pub fn is_private(&self) -> bool {
self.key_params.is_private()
}
pub fn from_key_params(key_params: JwkAlgorithmParameters) -> Self {
let params: JwkAlgorithmParameters = key_params.into();
Self{
kid: None,
pk_use: None,
key_ops: None,
alg: None,
x5u: None,
x5c: None,
x5t: None,
key_params: params,
}
}
pub fn to_public(&self) -> Option<Jwk> {
let mut public: Jwk = Jwk::from_key_params(self.key_params.to_public()?);
if let Some(value) = &self.kid {
public.set_kid(value);
}
if let Some(value) = self.pk_use {
public.set_pk_use(value);
}
if let Some(value) = &self.key_ops {
public.set_key_ops(value.iter().map(|op| op.inverse()).collect());
}
if let Some(value) = self.alg {
public.set_alg(value);
}
if let Some(value) = &self.x5u {
public.set_x5u(value);
}
if let Some(value) = &self.x5c {
public.set_x5c(value.iter().map(|x| x.as_str()).collect());
}
if let Some(value) = &self.x5t {
public.set_x5t(value);
}
Some(public)
}
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub enum KeyOps {
Sign,
Verify,
Encrypt,
Decrypt,
WrapKey,
UnwrapKey,
DeriveKey,
DeriveBits,
ProofGeneration,
ProofVerification
}
impl KeyOps {
pub const fn inverse(&self) -> Self {
match self {
Self::Sign => Self::Verify,
Self::Verify => Self::Sign,
Self::Encrypt => Self::Decrypt,
Self::Decrypt => Self::Encrypt,
Self::WrapKey => Self::UnwrapKey,
Self::UnwrapKey => Self::WrapKey,
Self::DeriveKey => Self::DeriveKey,
Self::DeriveBits => Self::DeriveBits,
Self::ProofGeneration => Self::ProofVerification,
Self::ProofVerification => Self::ProofVerification,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum PKUse {
#[serde(rename = "sig")]
Signature,
#[serde(rename = "enc")]
Encryption,
#[serde(rename = "proof")]
Proof
}