bee_block/signature/
ed25519.rs1use core::{fmt, ops::Deref};
5
6use crypto::{
7 hashes::{blake2b::Blake2b256, Digest},
8 signatures::ed25519::{PublicKey, Signature, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH},
9};
10
11use crate::{address::Ed25519Address, Error};
12
13#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, packable::Packable)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub struct Ed25519Signature {
17 public_key: [u8; Self::PUBLIC_KEY_LENGTH],
18 #[cfg_attr(feature = "serde", serde(with = "serde_big_array::BigArray"))]
19 signature: [u8; Self::SIGNATURE_LENGTH],
20}
21
22impl Ed25519Signature {
23 pub const KIND: u8 = 0;
25 pub const PUBLIC_KEY_LENGTH: usize = PUBLIC_KEY_LENGTH;
27 pub const SIGNATURE_LENGTH: usize = SIGNATURE_LENGTH;
29
30 pub fn new(public_key: [u8; Self::PUBLIC_KEY_LENGTH], signature: [u8; Self::SIGNATURE_LENGTH]) -> Self {
32 Self { public_key, signature }
33 }
34
35 pub fn public_key(&self) -> &[u8; Self::PUBLIC_KEY_LENGTH] {
37 &self.public_key
38 }
39
40 pub fn signature(&self) -> &[u8; Self::SIGNATURE_LENGTH] {
42 &self.signature
43 }
44
45 pub fn is_valid(&self, message: &[u8], address: &Ed25519Address) -> Result<(), Error> {
47 let signature_address: [u8; PUBLIC_KEY_LENGTH] = Blake2b256::digest(self.public_key).into();
48
49 if address.deref() != &signature_address {
50 return Err(Error::SignaturePublicKeyMismatch {
51 expected: prefix_hex::encode(address.as_ref()),
52 actual: prefix_hex::encode(signature_address),
53 });
54 }
55
56 if !PublicKey::try_from_bytes(self.public_key)?.verify(&Signature::from_bytes(self.signature), message) {
57 return Err(Error::InvalidSignature);
58 }
59
60 Ok(())
61 }
62}
63
64impl fmt::Debug for Ed25519Signature {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 #[repr(transparent)]
67 struct UnquotedStr<'a>(&'a str);
68
69 impl<'a> fmt::Debug for UnquotedStr<'a> {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 write!(f, "{}", self.0)
72 }
73 }
74
75 f.debug_struct("Ed25519Signature")
76 .field("public_key", &UnquotedStr(&prefix_hex::encode(self.public_key)))
77 .field("signature", &UnquotedStr(&prefix_hex::encode(self.signature)))
78 .finish()
79 }
80}
81
82#[cfg(feature = "dto")]
83#[allow(missing_docs)]
84pub mod dto {
85 use serde::{Deserialize, Serialize};
86
87 use super::*;
88 use crate::error::dto::DtoError;
89
90 #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
92 pub struct Ed25519SignatureDto {
93 #[serde(rename = "type")]
94 pub kind: u8,
95 #[serde(rename = "publicKey")]
96 pub public_key: String,
97 pub signature: String,
98 }
99
100 impl From<&Ed25519Signature> for Ed25519SignatureDto {
101 fn from(value: &Ed25519Signature) -> Self {
102 Ed25519SignatureDto {
103 kind: Ed25519Signature::KIND,
104 public_key: prefix_hex::encode(value.public_key),
105 signature: prefix_hex::encode(value.signature),
106 }
107 }
108 }
109
110 impl TryFrom<&Ed25519SignatureDto> for Ed25519Signature {
111 type Error = DtoError;
112
113 fn try_from(value: &Ed25519SignatureDto) -> Result<Self, Self::Error> {
114 Ok(Ed25519Signature::new(
115 prefix_hex::decode(&value.public_key).map_err(|_| DtoError::InvalidField("publicKey"))?,
116 prefix_hex::decode(&value.signature).map_err(|_| DtoError::InvalidField("signature"))?,
117 ))
118 }
119 }
120}