mirror of
https://git.proxmox.com/git/proxmox
synced 2025-08-05 06:26:41 +00:00
67 lines
1.7 KiB
Rust
67 lines
1.7 KiB
Rust
use openssl::hash::MessageDigest;
|
|
use openssl::pkey::{HasPrivate, PKeyRef};
|
|
use openssl::sign::Signer;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::key::Jwk;
|
|
use crate::{b64u, Error};
|
|
|
|
#[derive(Debug, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
struct Protected {
|
|
alg: &'static str,
|
|
url: String,
|
|
kid: String,
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct ExternalAccountBinding {
|
|
protected: String,
|
|
payload: String,
|
|
signature: String,
|
|
}
|
|
|
|
impl ExternalAccountBinding {
|
|
pub fn new<P>(
|
|
eab_kid: &str,
|
|
eab_hmac_key: &PKeyRef<P>,
|
|
jwk: Jwk,
|
|
url: String,
|
|
) -> Result<Self, Error>
|
|
where
|
|
P: HasPrivate,
|
|
{
|
|
let protected = Protected {
|
|
alg: "HS256",
|
|
kid: eab_kid.to_string(),
|
|
url,
|
|
};
|
|
let payload = b64u::encode(serde_json::to_string(&jwk)?.as_bytes());
|
|
let protected_data = b64u::encode(serde_json::to_string(&protected)?.as_bytes());
|
|
let signature = {
|
|
let protected = protected_data.as_bytes();
|
|
let payload = payload.as_bytes();
|
|
Self::sign_hmac(eab_hmac_key, protected, payload)?
|
|
};
|
|
|
|
let signature = b64u::encode(&signature);
|
|
Ok(ExternalAccountBinding {
|
|
protected: protected_data,
|
|
payload,
|
|
signature,
|
|
})
|
|
}
|
|
|
|
fn sign_hmac<P>(key: &PKeyRef<P>, protected: &[u8], payload: &[u8]) -> Result<Vec<u8>, Error>
|
|
where
|
|
P: HasPrivate,
|
|
{
|
|
let mut signer = Signer::new(MessageDigest::sha256(), key)?;
|
|
signer.update(protected)?;
|
|
signer.update(b".")?;
|
|
signer.update(payload)?;
|
|
Ok(signer.sign_to_vec()?)
|
|
}
|
|
}
|