chik_secp/secp256r1/
public_key.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use std::fmt;
use std::hash::{Hash, Hasher};

use chik_sha2::Sha256;
use p256::ecdsa::signature::hazmat::PrehashVerifier;
use p256::ecdsa::{Error, VerifyingKey};

use super::R1Signature;

#[derive(Clone, Copy, PartialEq, Eq)]
pub struct R1PublicKey(pub(crate) VerifyingKey);

impl Hash for R1PublicKey {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.to_bytes().hash(state);
    }
}

impl fmt::Debug for R1PublicKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "R1PublicKey({self})")
    }
}

impl fmt::Display for R1PublicKey {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", hex::encode(self.to_bytes()))
    }
}

#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for R1PublicKey {
    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
        Self::from_bytes(&u.arbitrary()?).map_err(|_| arbitrary::Error::IncorrectFormat)
    }
}

impl R1PublicKey {
    pub const SIZE: usize = 33;

    pub fn to_bytes(&self) -> [u8; Self::SIZE] {
        self.0.to_encoded_point(true).as_ref().try_into().unwrap()
    }

    pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> Result<Self, Error> {
        Ok(Self(VerifyingKey::from_sec1_bytes(bytes)?))
    }

    pub fn verify_prehashed(&self, message_hash: &[u8; 32], signature: &R1Signature) -> bool {
        self.0.verify_prehash(message_hash, &signature.0).is_ok()
    }

    pub fn fingerprint(&self) -> u32 {
        let mut hasher = Sha256::new();
        hasher.update(self.to_bytes());
        let hash = hasher.finalize();
        u32::from_be_bytes(hash[0..4].try_into().unwrap())
    }
}