k256/schnorr/
verifying.rs

1//! Taproot Schnorr verifying key.
2
3use super::{tagged_hash, Signature, CHALLENGE_TAG};
4use crate::{AffinePoint, FieldBytes, ProjectivePoint, PublicKey, Scalar};
5use elliptic_curve::{
6    bigint::U256,
7    group::prime::PrimeCurveAffine,
8    ops::{LinearCombination, Reduce},
9    point::DecompactPoint,
10};
11use sha2::{
12    digest::{consts::U32, FixedOutput},
13    Digest, Sha256,
14};
15use signature::{hazmat::PrehashVerifier, DigestVerifier, Error, Result, Verifier};
16
17#[cfg(feature = "serde")]
18use serdect::serde::{de, ser, Deserialize, Serialize};
19
20/// Taproot Schnorr verifying key.
21#[derive(Copy, Clone, Debug, Eq, PartialEq)]
22pub struct VerifyingKey {
23    /// Inner public key
24    pub(super) inner: PublicKey,
25}
26
27impl VerifyingKey {
28    /// Borrow the inner [`AffinePoint`] this type wraps.
29    pub fn as_affine(&self) -> &AffinePoint {
30        self.inner.as_affine()
31    }
32
33    /// Serialize as bytes.
34    pub fn to_bytes(&self) -> FieldBytes {
35        self.as_affine().x.to_bytes()
36    }
37
38    /// Compute Schnorr signature.
39    ///
40    /// # ⚠️ Warning
41    ///
42    /// This is a low-level interface intended only for unusual use cases
43    /// involving verifying pre-hashed messages, or "raw" messages where the
44    /// message is not hashed at all prior to being used to generate the
45    /// Schnorr signature.
46    ///
47    /// The preferred interfaces are the [`DigestVerifier`] or [`PrehashVerifier`] traits.
48    pub fn verify_raw(
49        &self,
50        message: &[u8],
51        signature: &Signature,
52    ) -> core::result::Result<(), Error> {
53        let (r, s) = signature.split();
54
55        let e = <Scalar as Reduce<U256>>::reduce_bytes(
56            &tagged_hash(CHALLENGE_TAG)
57                .chain_update(signature.r.to_bytes())
58                .chain_update(self.to_bytes())
59                .chain_update(message)
60                .finalize(),
61        );
62
63        let R = ProjectivePoint::lincomb(
64            &ProjectivePoint::GENERATOR,
65            s,
66            &self.inner.to_projective(),
67            &-e,
68        )
69        .to_affine();
70
71        if R.is_identity().into() || R.y.normalize().is_odd().into() || R.x.normalize() != *r {
72            return Err(Error::new());
73        }
74
75        Ok(())
76    }
77
78    /// Parse verifying key from big endian-encoded x-coordinate.
79    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
80        let maybe_affine_point = AffinePoint::decompact(FieldBytes::from_slice(bytes));
81        let affine_point = Option::from(maybe_affine_point).ok_or_else(Error::new)?;
82        PublicKey::from_affine(affine_point)
83            .map_err(|_| Error::new())?
84            .try_into()
85    }
86}
87
88//
89// `*Verifier` trait impls
90//
91
92impl<D> DigestVerifier<D, Signature> for VerifyingKey
93where
94    D: Digest + FixedOutput<OutputSize = U32>,
95{
96    fn verify_digest(&self, digest: D, signature: &Signature) -> Result<()> {
97        self.verify_prehash(digest.finalize_fixed().as_slice(), signature)
98    }
99}
100
101impl PrehashVerifier<Signature> for VerifyingKey {
102    fn verify_prehash(
103        &self,
104        prehash: &[u8],
105        signature: &Signature,
106    ) -> core::result::Result<(), Error> {
107        self.verify_raw(prehash, signature)
108    }
109}
110
111impl Verifier<Signature> for VerifyingKey {
112    fn verify(&self, msg: &[u8], signature: &Signature) -> Result<()> {
113        self.verify_digest(Sha256::new_with_prefix(msg), signature)
114    }
115}
116
117//
118// Other trait impls
119//
120
121impl From<VerifyingKey> for AffinePoint {
122    fn from(vk: VerifyingKey) -> AffinePoint {
123        *vk.as_affine()
124    }
125}
126
127impl From<&VerifyingKey> for AffinePoint {
128    fn from(vk: &VerifyingKey) -> AffinePoint {
129        *vk.as_affine()
130    }
131}
132
133impl From<VerifyingKey> for PublicKey {
134    fn from(vk: VerifyingKey) -> PublicKey {
135        vk.inner
136    }
137}
138
139impl From<&VerifyingKey> for PublicKey {
140    fn from(vk: &VerifyingKey) -> PublicKey {
141        vk.inner
142    }
143}
144
145impl TryFrom<PublicKey> for VerifyingKey {
146    type Error = Error;
147
148    fn try_from(public_key: PublicKey) -> Result<VerifyingKey> {
149        if public_key.as_affine().y.normalize().is_even().into() {
150            Ok(Self { inner: public_key })
151        } else {
152            Err(Error::new())
153        }
154    }
155}
156
157impl TryFrom<&PublicKey> for VerifyingKey {
158    type Error = Error;
159
160    fn try_from(public_key: &PublicKey) -> Result<VerifyingKey> {
161        Self::try_from(*public_key)
162    }
163}
164
165#[cfg(feature = "serde")]
166impl Serialize for VerifyingKey {
167    fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
168    where
169        S: ser::Serializer,
170    {
171        self.inner.serialize(serializer)
172    }
173}
174
175#[cfg(feature = "serde")]
176impl<'de> Deserialize<'de> for VerifyingKey {
177    fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
178    where
179        D: de::Deserializer<'de>,
180    {
181        VerifyingKey::try_from(PublicKey::deserialize(deserializer)?).map_err(de::Error::custom)
182    }
183}