// -*- mode: rust; -*- // // This file is part of redjubjub. // Copyright (c) 2019-2021 Zcash Foundation // See LICENSE for licensing information. // // Authors: // - Deirdre Connolly // - Henry de Valence use std::{convert::TryFrom, hash::Hash}; use crate::{Error, Randomizer, SigType, Signature, SpendAuth}; /// A refinement type for `[u8; 32]` indicating that the bytes represent /// an encoding of a RedJubJub verification key. /// /// This is useful for representing a compressed verification key; the /// [`VerificationKey`] type in this library holds other decompressed state /// used in signature verification. #[derive(Copy, Clone, Hash, PartialEq, Eq, Debug)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct VerificationKeyBytes( pub(crate) reddsa::VerificationKeyBytes, ); impl From<[u8; 32]> for VerificationKeyBytes { fn from(bytes: [u8; 32]) -> VerificationKeyBytes { VerificationKeyBytes(reddsa::VerificationKeyBytes::from(bytes)) } } impl From> for [u8; 32] { fn from(refined: VerificationKeyBytes) -> [u8; 32] { refined.0.into() } } /// A valid RedJubJub verification key. /// /// This type holds decompressed state used in signature verification; if the /// verification key may not be used immediately, it is probably better to use /// [`VerificationKeyBytes`], which is a refinement type for `[u8; 32]`. /// /// ## Consensus properties /// /// The `TryFrom` conversion performs the following Zcash /// consensus rule checks: /// /// 1. The check that the bytes are a canonical encoding of a verification key; /// 2. The check that the verification key is not a point of small order. #[derive(PartialEq, Copy, Clone, Debug)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "serde", serde(try_from = "VerificationKeyBytes"))] #[cfg_attr(feature = "serde", serde(into = "VerificationKeyBytes"))] #[cfg_attr(feature = "serde", serde(bound = "T: SigType"))] pub struct VerificationKey(pub(crate) reddsa::VerificationKey); impl From> for VerificationKeyBytes { fn from(pk: VerificationKey) -> VerificationKeyBytes { VerificationKeyBytes(pk.0.into()) } } impl From> for [u8; 32] { fn from(pk: VerificationKey) -> [u8; 32] { pk.0.into() } } impl TryFrom> for VerificationKey { type Error = Error; fn try_from(bytes: VerificationKeyBytes) -> Result { let reddsa_vk = reddsa::VerificationKey::try_from(bytes.0)?; Ok(VerificationKey(reddsa_vk)) } } impl TryFrom<[u8; 32]> for VerificationKey { type Error = Error; fn try_from(bytes: [u8; 32]) -> Result { use std::convert::TryInto; VerificationKeyBytes::from(bytes).try_into() } } impl VerificationKey { /// Randomize this verification key with the given `randomizer`. /// /// Randomization is only supported for `SpendAuth` keys. pub fn randomize(&self, randomizer: &Randomizer) -> VerificationKey { VerificationKey(self.0.randomize(randomizer)) } } impl VerificationKey { /// Verify a purported `signature` over `msg` made by this verification key. // This is similar to impl signature::Verifier but without boxed errors pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), Error> { self.0.verify(msg, &signature.0).map_err(|e| e.into()) } }