ed25519_zebra/
verification_key.rs1use core::convert::{TryFrom, TryInto};
2use curve25519_dalek::{
3 digest::Update,
4 edwards::{CompressedEdwardsY, EdwardsPoint},
5 scalar::Scalar,
6 traits::IsIdentity,
7};
8use sha2::Sha512;
9use zeroize::DefaultIsZeroes;
10
11pub use ed25519::{
12 signature::{Signer, Verifier},
13 Signature,
14};
15
16#[cfg(feature = "pkcs8")]
17use pkcs8::der::asn1::BitStringRef;
18#[cfg(feature = "pkcs8")]
19use pkcs8::spki::{
20 AlgorithmIdentifierRef, DecodePublicKey, EncodePublicKey, SubjectPublicKeyInfoRef,
21};
22#[cfg(feature = "pkcs8")]
23use pkcs8::{Document, ObjectIdentifier};
24
25use crate::Error;
26
27#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
48#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
49pub struct VerificationKeyBytes(pub(crate) [u8; 32]);
50
51impl core::fmt::Debug for VerificationKeyBytes {
52 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
53 fmt.debug_tuple("VerificationKeyBytes")
54 .field(&hex::encode(self.0))
55 .finish()
56 }
57}
58
59impl AsRef<[u8]> for VerificationKeyBytes {
60 fn as_ref(&self) -> &[u8] {
61 &self.0[..]
62 }
63}
64
65impl TryFrom<&[u8]> for VerificationKeyBytes {
66 type Error = Error;
67 fn try_from(slice: &[u8]) -> Result<VerificationKeyBytes, Self::Error> {
68 if slice.len() == 32 {
69 let mut bytes = [0u8; 32];
70 bytes[..].copy_from_slice(slice);
71 Ok(bytes.into())
72 } else {
73 Err(Error::InvalidSliceLength)
74 }
75 }
76}
77
78impl From<[u8; 32]> for VerificationKeyBytes {
79 fn from(bytes: [u8; 32]) -> VerificationKeyBytes {
80 VerificationKeyBytes(bytes)
81 }
82}
83
84impl From<VerificationKeyBytes> for [u8; 32] {
85 fn from(refined: VerificationKeyBytes) -> [u8; 32] {
86 refined.0
87 }
88}
89
90#[cfg(feature = "pkcs8")]
91impl<'a> TryFrom<SubjectPublicKeyInfoRef<'a>> for VerificationKeyBytes {
92 type Error = Error;
93
94 fn try_from(spki: SubjectPublicKeyInfoRef) -> Result<VerificationKeyBytes, Error> {
95 Ok(VerificationKeyBytes::try_from(spki.subject_public_key.as_bytes().unwrap()).unwrap())
96 }
97}
98
99#[derive(Copy, Clone, Debug)]
117#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
118#[cfg_attr(feature = "serde", serde(try_from = "VerificationKeyBytes"))]
119#[cfg_attr(feature = "serde", serde(into = "VerificationKeyBytes"))]
120#[allow(non_snake_case)]
121pub struct VerificationKey {
122 pub(crate) A_bytes: VerificationKeyBytes,
123 pub(crate) minus_A: EdwardsPoint,
124}
125
126impl From<VerificationKey> for VerificationKeyBytes {
127 fn from(vk: VerificationKey) -> VerificationKeyBytes {
128 vk.A_bytes
129 }
130}
131
132impl AsRef<[u8]> for VerificationKey {
133 fn as_ref(&self) -> &[u8] {
134 &self.A_bytes.0[..]
135 }
136}
137
138impl Default for VerificationKey {
139 fn default() -> VerificationKey {
140 let identity: EdwardsPoint = Default::default();
141 let identity_bytes = identity.compress().to_bytes();
142
143 VerificationKey {
144 A_bytes: VerificationKeyBytes::from(identity_bytes),
145 minus_A: -identity,
146 }
147 }
148}
149
150impl DefaultIsZeroes for VerificationKey {}
151
152impl From<VerificationKey> for [u8; 32] {
153 fn from(vk: VerificationKey) -> [u8; 32] {
154 vk.A_bytes.0
155 }
156}
157
158impl TryFrom<VerificationKeyBytes> for VerificationKey {
159 type Error = Error;
160 #[allow(non_snake_case)]
161 fn try_from(bytes: VerificationKeyBytes) -> Result<Self, Self::Error> {
162 let A = CompressedEdwardsY(bytes.0)
165 .decompress()
166 .ok_or(Error::MalformedPublicKey)?;
167
168 Ok(VerificationKey {
169 A_bytes: bytes,
170 minus_A: -A,
171 })
172 }
173}
174
175impl TryFrom<&[u8]> for VerificationKey {
176 type Error = Error;
177 fn try_from(slice: &[u8]) -> Result<VerificationKey, Error> {
178 VerificationKeyBytes::try_from(slice).and_then(|vkb| vkb.try_into())
179 }
180}
181
182impl TryFrom<[u8; 32]> for VerificationKey {
183 type Error = Error;
184 fn try_from(bytes: [u8; 32]) -> Result<Self, Self::Error> {
185 VerificationKeyBytes::from(bytes).try_into()
186 }
187}
188
189#[cfg(feature = "pkcs8")]
190impl EncodePublicKey for VerificationKey {
191 fn to_public_key_der(&self) -> pkcs8::spki::Result<Document> {
193 let alg_info = AlgorithmIdentifierRef {
194 oid: ObjectIdentifier::new_unwrap("1.3.101.112"), parameters: None,
196 };
197 SubjectPublicKeyInfoRef {
198 algorithm: alg_info,
199 subject_public_key: BitStringRef::from_bytes(&self.A_bytes.0[..])?,
200 }
201 .try_into()
202 }
203}
204
205#[cfg(feature = "pkcs8")]
206impl DecodePublicKey for VerificationKey {
207 fn from_public_key_der(bytes: &[u8]) -> Result<Self, pkcs8::spki::Error> {
209 let spki = SubjectPublicKeyInfoRef::try_from(bytes).unwrap();
210 let pk_bytes = spki.subject_public_key.as_bytes().unwrap();
211 Ok(Self::try_from(pk_bytes).unwrap())
212 }
213}
214
215impl Verifier<Signature> for VerificationKey {
216 fn verify(
218 &self,
219 message: &[u8],
220 signature: &Signature,
221 ) -> Result<(), ed25519::signature::Error> {
222 self.verify(signature, message)
223 .map_err(|_| ed25519::signature::Error::new())
224 }
225}
226
227impl VerificationKey {
228 pub fn verify(&self, signature: &Signature, msg: &[u8]) -> Result<(), Error> {
250 let k = Scalar::from_hash(
251 Sha512::default()
252 .chain(&signature.r_bytes()[..])
253 .chain(&self.A_bytes.0[..])
254 .chain(msg),
255 );
256 self.verify_prehashed(signature, k)
257 }
258
259 #[allow(non_snake_case)]
262 pub(crate) fn verify_prehashed(&self, signature: &Signature, k: Scalar) -> Result<(), Error> {
263 let s = Option::<Scalar>::from(Scalar::from_canonical_bytes(*signature.s_bytes()))
265 .ok_or(Error::InvalidSignature)?;
266 let R = CompressedEdwardsY(*signature.r_bytes())
268 .decompress()
269 .ok_or(Error::InvalidSignature)?;
270 let R_prime = EdwardsPoint::vartime_double_scalar_mul_basepoint(&k, &self.minus_A, &s);
277
278 if (R - R_prime).mul_by_cofactor().is_identity() {
279 Ok(())
280 } else {
281 Err(Error::InvalidSignature)
282 }
283 }
284}