use super::{Algorithm, PublicKey, ring_like::signature};
use crate::error::{ProtoError, ProtoResult};
#[derive(Clone, Copy, PartialEq, Eq)]
pub(super) struct ECPublicKey {
buf: [u8; MAX_LEN],
len: usize,
pub(crate) algorithm: Algorithm,
}
const MAX_LEN: usize = 1 + (2 * 48);
impl ECPublicKey {
pub(super) fn from_public_bytes(public_key: &[u8], algorithm: Algorithm) -> ProtoResult<Self> {
Self::from_unprefixed(public_key, algorithm)
}
pub(super) fn from_unprefixed(
without_prefix: &[u8],
algorithm: Algorithm,
) -> ProtoResult<Self> {
let field_len = match algorithm {
Algorithm::ECDSAP256SHA256 => 32,
Algorithm::ECDSAP384SHA384 => 48,
_ => return Err("only ECDSAP256SHA256 and ECDSAP384SHA384 are supported by Ec".into()),
};
let len = 1 + (2 * field_len);
if len - 1 != without_prefix.len() {
return Err("EC public key is the wrong length".into());
}
let mut buf = [0x04u8; MAX_LEN];
buf[1..len].copy_from_slice(without_prefix);
Ok(Self {
buf,
len,
algorithm,
})
}
pub(super) fn prefixed_bytes(&self) -> &[u8] {
&self.buf[..self.len]
}
pub(super) fn unprefixed_bytes(&self) -> &[u8] {
&self.buf[1..self.len]
}
}
impl PublicKey for ECPublicKey {
fn public_bytes(&self) -> &[u8] {
self.unprefixed_bytes()
}
fn verify(&self, message: &[u8], signature: &[u8]) -> ProtoResult<()> {
let alg = match self.algorithm {
Algorithm::ECDSAP256SHA256 => &signature::ECDSA_P256_SHA256_FIXED,
Algorithm::ECDSAP384SHA384 => &signature::ECDSA_P384_SHA384_FIXED,
_ => return Err("only ECDSAP256SHA256 and ECDSAP384SHA384 are supported by Ec".into()),
};
let public_key = signature::UnparsedPublicKey::new(alg, self.prefixed_bytes());
public_key
.verify(message, signature)
.map_err(|_| ProtoError::Crypto("ECDSA signature verification failed"))
}
fn algorithm(&self) -> Algorithm {
self.algorithm
}
}