use alloc::collections::BTreeMap;
use alloc::vec::Vec;
use ed25519_dalek::{Signer as _, SigningKey, VerifyingKey};
use p256::ecdsa::signature::Verifier as _;
use p256::ecdsa::{
Signature as P256Signature, SigningKey as P256SigningKey, VerifyingKey as P256VerifyingKey,
};
use x25519_dalek::{PublicKey, StaticSecret};
use zeroize::Zeroizing;
use crate::alg::SignatureAlgorithm;
use crate::codec;
use crate::error::{OpenError, SignError, VerifyError};
use crate::kdf;
use crate::traits::{OpenRequest, Recipient, Signer, Verifier};
use crate::types::{KeyId, Signature};
pub struct Ed25519Signer {
key: SigningKey,
key_id: KeyId,
}
impl Ed25519Signer {
#[must_use]
pub fn from_secret_bytes(key_id: KeyId, secret: &Zeroizing<[u8; 32]>) -> Self {
Self {
key: SigningKey::from_bytes(secret),
key_id,
}
}
#[must_use]
pub fn public_key_bytes(&self) -> [u8; 32] {
self.key.verifying_key().to_bytes()
}
}
impl Signer for Ed25519Signer {
fn key_id(&self) -> &KeyId {
&self.key_id
}
fn algorithm(&self) -> SignatureAlgorithm {
SignatureAlgorithm::EdDsa
}
async fn sign(&self, sig_structure: &[u8]) -> Result<Signature, SignError> {
let sig = self.key.sign(sig_structure);
Signature::from_bytes(sig.to_bytes().to_vec()).map_err(|_| SignError::Provider {
message: alloc::string::String::from("empty signature"),
})
}
}
pub struct Ed25519Verifier {
keys: BTreeMap<KeyId, VerifyingKey>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KeyError {
InvalidPublicKey,
InvalidPrivateKey,
}
impl core::fmt::Display for KeyError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::InvalidPublicKey => write!(f, "invalid public key"),
Self::InvalidPrivateKey => write!(f, "invalid private key"),
}
}
}
impl core::error::Error for KeyError {}
impl Ed25519Verifier {
pub fn from_key(key_id: KeyId, public: &[u8; 32]) -> Result<Self, KeyError> {
let mut keys = BTreeMap::new();
keys.insert(
key_id,
VerifyingKey::from_bytes(public).map_err(|_| KeyError::InvalidPublicKey)?,
);
Ok(Self { keys })
}
pub fn add_key(&mut self, key_id: KeyId, public: &[u8; 32]) -> Result<(), KeyError> {
self.keys.insert(
key_id,
VerifyingKey::from_bytes(public).map_err(|_| KeyError::InvalidPublicKey)?,
);
Ok(())
}
}
impl Verifier for Ed25519Verifier {
async fn verify(
&self,
key_id: &KeyId,
algorithm: SignatureAlgorithm,
_protected_headers: &crate::claims::ProtectedHeaders,
sig_structure: &[u8],
signature: &Signature,
) -> Result<(), VerifyError> {
if algorithm != SignatureAlgorithm::EdDsa {
return Err(VerifyError::AlgorithmMismatch);
}
let key = self.keys.get(key_id).ok_or(VerifyError::UnknownKeyId)?;
let sig_bytes: [u8; 64] = signature
.as_bytes()
.try_into()
.map_err(|_| VerifyError::SignatureInvalid)?;
let sig = ed25519_dalek::Signature::from_bytes(&sig_bytes);
key.verify_strict(sig_structure, &sig)
.map_err(|_| VerifyError::SignatureInvalid)
}
}
pub struct Es256Signer {
key: P256SigningKey,
key_id: KeyId,
}
impl Es256Signer {
pub fn from_secret_bytes(
key_id: KeyId,
secret: &Zeroizing<[u8; 32]>,
) -> Result<Self, KeyError> {
let key = P256SigningKey::from_slice(secret.as_slice())
.map_err(|_| KeyError::InvalidPrivateKey)?;
Ok(Self { key, key_id })
}
#[must_use]
pub fn public_key_sec1(&self) -> Vec<u8> {
self.key
.verifying_key()
.to_encoded_point(false)
.as_bytes()
.to_vec()
}
}
impl Signer for Es256Signer {
fn key_id(&self) -> &KeyId {
&self.key_id
}
fn algorithm(&self) -> SignatureAlgorithm {
SignatureAlgorithm::Es256
}
async fn sign(&self, sig_structure: &[u8]) -> Result<Signature, SignError> {
let sig: P256Signature =
self.key
.try_sign(sig_structure)
.map_err(|_| SignError::Provider {
message: alloc::string::String::from("ecdsa signing failed"),
})?;
Signature::from_bytes(sig.to_bytes().to_vec()).map_err(|_| SignError::Provider {
message: alloc::string::String::from("empty signature"),
})
}
}
pub struct P256Verifier {
keys: BTreeMap<KeyId, P256VerifyingKey>,
}
impl P256Verifier {
pub fn from_sec1(key_id: KeyId, public: &[u8]) -> Result<Self, KeyError> {
let mut keys = BTreeMap::new();
keys.insert(
key_id,
P256VerifyingKey::from_sec1_bytes(public).map_err(|_| KeyError::InvalidPublicKey)?,
);
Ok(Self { keys })
}
pub fn add_key(&mut self, key_id: KeyId, public: &[u8]) -> Result<(), KeyError> {
self.keys.insert(
key_id,
P256VerifyingKey::from_sec1_bytes(public).map_err(|_| KeyError::InvalidPublicKey)?,
);
Ok(())
}
}
impl Verifier for P256Verifier {
async fn verify(
&self,
key_id: &KeyId,
algorithm: SignatureAlgorithm,
_protected_headers: &crate::claims::ProtectedHeaders,
sig_structure: &[u8],
signature: &Signature,
) -> Result<(), VerifyError> {
if algorithm != SignatureAlgorithm::Es256 {
return Err(VerifyError::AlgorithmMismatch);
}
let key = self.keys.get(key_id).ok_or(VerifyError::UnknownKeyId)?;
let sig = P256Signature::from_slice(signature.as_bytes())
.map_err(|_| VerifyError::SignatureInvalid)?;
key.verify(sig_structure, &sig)
.map_err(|_| VerifyError::SignatureInvalid)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct X25519RecipientPublic {
pub key_id: KeyId,
pub public: [u8; 32],
}
pub struct X25519Recipient {
private: Zeroizing<[u8; 32]>,
key_id: KeyId,
}
impl X25519Recipient {
#[must_use]
pub const fn new(key_id: KeyId, private: Zeroizing<[u8; 32]>) -> Self {
Self { private, key_id }
}
pub fn from_private_slice(key_id: KeyId, bytes: &[u8]) -> Result<Self, KeyLengthError> {
let arr: [u8; 32] = bytes.try_into().map_err(|_| KeyLengthError {
actual: bytes.len(),
})?;
Ok(Self::new(key_id, Zeroizing::new(arr)))
}
#[must_use]
pub fn public(&self) -> X25519RecipientPublic {
let secret = StaticSecret::from(*self.private);
X25519RecipientPublic {
key_id: self.key_id.clone(),
public: PublicKey::from(&secret).to_bytes(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct KeyLengthError {
pub actual: usize,
}
impl core::fmt::Display for KeyLengthError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"X25519 private key must be 32 bytes, got {}",
self.actual
)
}
}
impl core::error::Error for KeyLengthError {}
impl Recipient for X25519Recipient {
fn key_id(&self) -> &KeyId {
&self.key_id
}
async fn open(&self, request: &OpenRequest<'_>) -> Result<Zeroizing<Vec<u8>>, OpenError> {
open_local(self, request)
}
}
fn open_local(
recipient: &X25519Recipient,
request: &OpenRequest<'_>,
) -> Result<Zeroizing<Vec<u8>>, OpenError> {
let decoded = decode_any_encrypt(request.cose_encrypt)?;
if decoded.recipient_kid != recipient.key_id {
return Err(OpenError::RecipientKeyMismatch);
}
if let Some(expected) = request.expected_parties
&& *expected != decoded.parties
{
return Err(OpenError::PartyMismatch);
}
let secret = StaticSecret::from(*recipient.private);
let ephemeral = PublicKey::from(decoded.ephemeral_x);
let shared_secret = secret.diffie_hellman(&ephemeral);
if !shared_secret.was_contributory() {
return Err(OpenError::OpenFailed);
}
let shared = Zeroizing::new(shared_secret.to_bytes());
let info = codec::kdf_context(
decoded.content_algorithm,
&decoded.parties,
&decoded.recipient_protected,
)
.map_err(|codec::CodecError| OpenError::OpenFailed)?;
let cek = kdf::derive_cek(&shared, &info).map_err(|kdf::KdfFailed| OpenError::OpenFailed)?;
let aad = codec::enc_structure(&decoded.protected, request.external_aad.as_bytes())
.map_err(|codec::CodecError| OpenError::OpenFailed)?;
crate::encrypt::aead_open(
decoded.content_algorithm,
&cek,
&decoded.iv,
&decoded.ciphertext,
&aad,
)
}
fn decode_any_encrypt(bytes: &[u8]) -> Result<codec::DecodedEncrypt, OpenError> {
match codec::decode_encrypt_strict(bytes, codec::ClaimsExpectation::Optional) {
Ok(d) => Ok(d),
Err(e) => Err(OpenError::Decode(e)),
}
}