1use std::{borrow::Cow, fmt, str::FromStr};
8
9use ed25519_dalek::{self as dalek, Signer, Verifier};
10use linera_witty::{
11 GuestPointer, HList, InstanceWithMemory, Layout, Memory, Runtime, RuntimeError, RuntimeMemory,
12 WitLoad, WitStore, WitType,
13};
14use serde::{Deserialize, Serialize};
15
16use super::{
17 le_bytes_to_u64_array, u64_array_to_le_bytes, BcsHashable, BcsSignable, CryptoError,
18 CryptoHash, HasTypeName, Hashable,
19};
20use crate::doc_scalar;
21
22const ED25519_SCHEME_LABEL: &str = "Ed25519";
24
25pub struct Ed25519SecretKey(pub(crate) dalek::SigningKey);
27
28#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Hash)]
30pub struct Ed25519PublicKey(pub [u8; dalek::PUBLIC_KEY_LENGTH]);
31
32#[derive(Eq, PartialEq, Copy, Clone)]
34pub struct Ed25519Signature(pub dalek::Signature);
35
36impl Ed25519SecretKey {
37 #[cfg(all(with_getrandom, with_testing))]
38 pub fn generate() -> Self {
42 let mut rng = rand::rngs::OsRng;
43 Self::generate_from(&mut rng)
44 }
45
46 #[cfg(with_getrandom)]
47 pub fn generate_from<R: super::CryptoRng>(rng: &mut R) -> Self {
49 let keypair = dalek::SigningKey::generate(rng);
50 Ed25519SecretKey(keypair)
51 }
52
53 pub fn public(&self) -> Ed25519PublicKey {
55 Ed25519PublicKey(self.0.verifying_key().to_bytes())
56 }
57
58 pub fn copy(&self) -> Ed25519SecretKey {
63 Ed25519SecretKey(self.0.clone())
64 }
65}
66
67impl Ed25519PublicKey {
68 #[cfg(with_testing)]
70 pub fn test_key(name: u8) -> Ed25519PublicKey {
71 let addr = [name; dalek::PUBLIC_KEY_LENGTH];
72 Ed25519PublicKey(addr)
73 }
74
75 pub fn as_bytes(&self) -> Vec<u8> {
77 self.0.to_vec()
78 }
79
80 pub fn from_slice(bytes: &[u8]) -> Result<Self, CryptoError> {
84 let key = bytes
85 .try_into()
86 .map_err(|_| CryptoError::IncorrectPublicKeySize {
87 scheme: ED25519_SCHEME_LABEL,
88 len: bytes.len(),
89 expected: dalek::PUBLIC_KEY_LENGTH,
90 })?;
91 Ok(Ed25519PublicKey(key))
92 }
93}
94
95impl Serialize for Ed25519PublicKey {
96 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
97 where
98 S: serde::ser::Serializer,
99 {
100 if serializer.is_human_readable() {
101 serializer.serialize_str(&hex::encode(self.as_bytes()))
102 } else {
103 serializer.serialize_newtype_struct("Ed25519PublicKey", &self.0)
104 }
105 }
106}
107
108impl<'de> Deserialize<'de> for Ed25519PublicKey {
109 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
110 where
111 D: serde::de::Deserializer<'de>,
112 {
113 if deserializer.is_human_readable() {
114 let s = String::deserialize(deserializer)?;
115 let value = hex::decode(s).map_err(serde::de::Error::custom)?;
116 Ok(Self::from_slice(&value).map_err(serde::de::Error::custom)?)
117 } else {
118 #[derive(Deserialize)]
119 #[serde(rename = "Ed25519PublicKey")]
120 struct PublicKey([u8; dalek::PUBLIC_KEY_LENGTH]);
121
122 let value = PublicKey::deserialize(deserializer)?;
123 Ok(Self(value.0))
124 }
125 }
126}
127
128impl Serialize for Ed25519SecretKey {
129 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
130 where
131 S: serde::ser::Serializer,
132 {
133 assert!(serializer.is_human_readable());
135 serializer.serialize_str(&hex::encode(self.0.to_bytes()))
136 }
137}
138
139impl<'de> Deserialize<'de> for Ed25519SecretKey {
140 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
141 where
142 D: serde::de::Deserializer<'de>,
143 {
144 assert!(deserializer.is_human_readable());
146 let s = String::deserialize(deserializer)?;
147 let value = hex::decode(s).map_err(serde::de::Error::custom)?;
148 let key =
149 dalek::SigningKey::from_bytes(value[..].try_into().map_err(serde::de::Error::custom)?);
150 Ok(Ed25519SecretKey(key))
151 }
152}
153
154impl FromStr for Ed25519PublicKey {
155 type Err = CryptoError;
156
157 fn from_str(s: &str) -> Result<Self, Self::Err> {
158 let value = hex::decode(s)?;
159 (value.as_slice()).try_into()
160 }
161}
162
163impl TryFrom<&[u8]> for Ed25519PublicKey {
164 type Error = CryptoError;
165
166 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
167 if value.len() != dalek::PUBLIC_KEY_LENGTH {
168 return Err(CryptoError::IncorrectPublicKeySize {
169 scheme: ED25519_SCHEME_LABEL,
170 len: value.len(),
171 expected: dalek::PUBLIC_KEY_LENGTH,
172 });
173 }
174 let mut pubkey = [0u8; dalek::PUBLIC_KEY_LENGTH];
175 pubkey.copy_from_slice(value);
176 Ok(Ed25519PublicKey(pubkey))
177 }
178}
179
180impl From<[u64; 4]> for Ed25519PublicKey {
181 fn from(integers: [u64; 4]) -> Self {
182 Ed25519PublicKey(u64_array_to_le_bytes(integers))
183 }
184}
185
186impl From<Ed25519PublicKey> for [u64; 4] {
187 fn from(pub_key: Ed25519PublicKey) -> Self {
188 le_bytes_to_u64_array(&pub_key.0)
189 }
190}
191
192impl fmt::Display for Ed25519PublicKey {
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 write!(f, "{}", hex::encode(&self.0[..]))
195 }
196}
197
198impl fmt::Debug for Ed25519PublicKey {
199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200 write!(f, "{}", hex::encode(&self.0[..8]))
201 }
202}
203
204impl WitType for Ed25519PublicKey {
205 const SIZE: u32 = <(u64, u64, u64, u64) as WitType>::SIZE;
206 type Layout = <(u64, u64, u64, u64) as WitType>::Layout;
207 type Dependencies = HList![];
208
209 fn wit_type_name() -> Cow<'static, str> {
210 "ed25519-public-key".into()
211 }
212
213 fn wit_type_declaration() -> Cow<'static, str> {
214 concat!(
215 " record ed25519-public-key {\n",
216 " part1: u64,\n",
217 " part2: u64,\n",
218 " part3: u64,\n",
219 " part4: u64,\n",
220 " }\n",
221 )
222 .into()
223 }
224}
225
226impl WitLoad for Ed25519PublicKey {
227 fn load<Instance>(
228 memory: &Memory<'_, Instance>,
229 location: GuestPointer,
230 ) -> Result<Self, RuntimeError>
231 where
232 Instance: InstanceWithMemory,
233 <Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
234 {
235 let (part1, part2, part3, part4) = WitLoad::load(memory, location)?;
236 Ok(Self::from([part1, part2, part3, part4]))
237 }
238
239 fn lift_from<Instance>(
240 flat_layout: <Self::Layout as Layout>::Flat,
241 memory: &Memory<'_, Instance>,
242 ) -> Result<Self, RuntimeError>
243 where
244 Instance: InstanceWithMemory,
245 <Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
246 {
247 let (part1, part2, part3, part4) = WitLoad::lift_from(flat_layout, memory)?;
248 Ok(Self::from([part1, part2, part3, part4]))
249 }
250}
251
252impl WitStore for Ed25519PublicKey {
253 fn store<Instance>(
254 &self,
255 memory: &mut Memory<'_, Instance>,
256 location: GuestPointer,
257 ) -> Result<(), RuntimeError>
258 where
259 Instance: InstanceWithMemory,
260 <Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
261 {
262 let [part1, part2, part3, part4] = (*self).into();
263 (part1, part2, part3, part4).store(memory, location)
264 }
265
266 fn lower<Instance>(
267 &self,
268 memory: &mut Memory<'_, Instance>,
269 ) -> Result<<Self::Layout as Layout>::Flat, RuntimeError>
270 where
271 Instance: InstanceWithMemory,
272 <Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
273 {
274 let [part1, part2, part3, part4] = (*self).into();
275 (part1, part2, part3, part4).lower(memory)
276 }
277}
278
279impl BcsHashable<'_> for Ed25519PublicKey {}
280
281impl Ed25519Signature {
282 pub fn new<'de, T>(value: &T, secret: &Ed25519SecretKey) -> Self
284 where
285 T: BcsSignable<'de>,
286 {
287 Self::sign_prehash(secret, CryptoHash::new(value))
288 }
289
290 pub fn sign_prehash(secret: &Ed25519SecretKey, prehash: CryptoHash) -> Self {
292 let signature = secret.0.sign(&prehash.as_bytes().0);
293 Ed25519Signature(signature)
294 }
295
296 pub fn from_slice(bytes: &[u8]) -> Result<Self, CryptoError> {
300 let sig = dalek::Signature::from_slice(bytes).map_err(|_| {
301 CryptoError::IncorrectSignatureBytes {
302 scheme: ED25519_SCHEME_LABEL,
303 len: bytes.len(),
304 expected: dalek::SIGNATURE_LENGTH,
305 }
306 })?;
307 Ok(Ed25519Signature(sig))
308 }
309
310 fn check_internal<'de, T>(
311 &self,
312 value: &T,
313 author: Ed25519PublicKey,
314 ) -> Result<(), dalek::SignatureError>
315 where
316 T: BcsSignable<'de>,
317 {
318 let prehash = CryptoHash::new(value).as_bytes().0;
319 let public_key = dalek::VerifyingKey::from_bytes(&author.0)?;
320 public_key.verify(&prehash, &self.0)
321 }
322
323 pub fn check<'de, T>(&self, value: &T, author: Ed25519PublicKey) -> Result<(), CryptoError>
325 where
326 T: BcsSignable<'de> + fmt::Debug,
327 {
328 self.check_internal(value, author)
329 .map_err(|error| CryptoError::InvalidSignature {
330 error: error.to_string(),
331 type_name: T::type_name().to_string(),
332 })
333 }
334
335 fn verify_batch_internal<'a, 'de, T, I>(
336 value: &'a T,
337 votes: I,
338 ) -> Result<(), dalek::SignatureError>
339 where
340 T: BcsSignable<'de>,
341 I: IntoIterator<Item = (&'a Ed25519PublicKey, &'a Ed25519Signature)>,
342 {
343 let mut msg = Vec::new();
344 value.write(&mut msg);
345 let mut messages = Vec::new();
346 let mut signatures = Vec::new();
347 let mut public_keys = Vec::new();
348 for (addr, sig) in votes {
349 messages.push(msg.as_slice());
350 signatures.push(sig.0);
351 public_keys.push(dalek::VerifyingKey::from_bytes(&addr.0)?);
352 }
353 dalek::verify_batch(&messages[..], &signatures[..], &public_keys[..])
354 }
355
356 #[allow(unused)]
359 pub fn verify_batch<'a, 'de, T, I>(value: &'a T, votes: I) -> Result<(), CryptoError>
360 where
361 T: BcsSignable<'de>,
362 I: IntoIterator<Item = (&'a Ed25519PublicKey, &'a Ed25519Signature)>,
363 {
364 Ed25519Signature::verify_batch_internal(value, votes).map_err(|error| {
365 CryptoError::InvalidSignature {
366 error: format!("batched {}", error),
367 type_name: T::type_name().to_string(),
368 }
369 })
370 }
371
372 pub fn as_bytes(&self) -> Vec<u8> {
374 self.0.to_bytes().to_vec()
375 }
376}
377
378impl Serialize for Ed25519Signature {
379 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
380 where
381 S: serde::ser::Serializer,
382 {
383 if serializer.is_human_readable() {
384 serializer.serialize_str(&hex::encode(self.0.to_bytes()))
385 } else {
386 serializer.serialize_newtype_struct("Ed25519Signature", &self.0)
387 }
388 }
389}
390
391impl<'de> Deserialize<'de> for Ed25519Signature {
392 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
393 where
394 D: serde::de::Deserializer<'de>,
395 {
396 if deserializer.is_human_readable() {
397 let s = String::deserialize(deserializer)?;
398 let value = hex::decode(s).map_err(serde::de::Error::custom)?;
399 Self::from_slice(&value).map_err(serde::de::Error::custom)
400 } else {
401 #[derive(Deserialize)]
402 #[serde(rename = "Ed25519Signature")]
403 struct Signature(dalek::Signature);
404
405 let value = Signature::deserialize(deserializer)?;
406 Ok(Self(value.0))
407 }
408 }
409}
410
411impl fmt::Display for Ed25519Signature {
412 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
413 let s = hex::encode(self.0.to_bytes());
414 write!(f, "{}", s)
415 }
416}
417
418impl fmt::Debug for Ed25519Signature {
419 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
420 write!(f, "{}", hex::encode(&self.0.to_bytes()[0..8]))
421 }
422}
423
424doc_scalar!(Ed25519Signature, "An Ed25519 signature value");
425doc_scalar!(Ed25519PublicKey, "A Ed25519 signature public key");
426
427#[cfg(with_testing)]
428mod tests {
429 #[test]
430 fn test_signatures() {
431 use serde::{Deserialize, Serialize};
432
433 use crate::crypto::{
434 ed25519::{Ed25519SecretKey, Ed25519Signature},
435 BcsSignable, TestString,
436 };
437
438 #[derive(Debug, Serialize, Deserialize)]
439 struct Foo(String);
440
441 impl BcsSignable<'_> for Foo {}
442
443 let key1 = Ed25519SecretKey::generate();
444 let addr1 = key1.public();
445 let key2 = Ed25519SecretKey::generate();
446 let addr2 = key2.public();
447
448 let ts = TestString("hello".into());
449 let tsx = TestString("hellox".into());
450 let foo = Foo("hello".into());
451
452 let s = Ed25519Signature::new(&ts, &key1);
453 assert!(s.check(&ts, addr1).is_ok());
454 assert!(s.check(&ts, addr2).is_err());
455 assert!(s.check(&tsx, addr1).is_err());
456 assert!(s.check(&foo, addr1).is_err());
457 }
458
459 #[test]
460 fn test_public_key_serialization() {
461 use crate::crypto::ed25519::Ed25519PublicKey;
462 let key_in = Ed25519PublicKey::test_key(0);
463 let s = serde_json::to_string(&key_in).unwrap();
464 let key_out: Ed25519PublicKey = serde_json::from_str(&s).unwrap();
465 assert_eq!(key_out, key_in);
466
467 let s = bcs::to_bytes(&key_in).unwrap();
468 let key_out: Ed25519PublicKey = bcs::from_bytes(&s).unwrap();
469 assert_eq!(key_out, key_in);
470 }
471
472 #[test]
473 fn test_secret_key_serialization() {
474 use crate::crypto::ed25519::Ed25519SecretKey;
475 let key_in = Ed25519SecretKey::generate();
476 let s = serde_json::to_string(&key_in).unwrap();
477 let key_out: Ed25519SecretKey = serde_json::from_str(&s).unwrap();
478 assert_eq!(key_out.0.to_bytes(), key_in.0.to_bytes());
479 }
480
481 #[test]
482 fn test_signature_serialization() {
483 use crate::crypto::ed25519::Ed25519Signature;
484 let sig_in = Ed25519Signature::from_slice(&[0u8; 64]).unwrap();
485 let s = serde_json::to_string(&sig_in).unwrap();
486 let sig_out: Ed25519Signature = serde_json::from_str(&s).unwrap();
487 assert_eq!(sig_out.0.to_bytes(), sig_in.0.to_bytes());
488
489 let s = bcs::to_bytes(&sig_in).unwrap();
490 let sig_out: Ed25519Signature = bcs::from_bytes(&s).unwrap();
491 assert_eq!(sig_out, sig_in);
492 }
493}