Skip to main content

sia_core/
signing.rs

1use core::fmt;
2
3use crate::encoding::{self, SiaDecodable, SiaDecode, SiaEncodable, SiaEncode};
4use crate::encoding_async::AsyncSiaDecode;
5use crate::types::{Hash256, HexParseError};
6use ed25519_dalek::{Signature as ED25519Signature, Signer, SigningKey, Verifier, VerifyingKey};
7use serde::de::Error;
8use serde::{Deserialize, Serialize};
9use zeroize::ZeroizeOnDrop;
10
11/// An ed25519 public key that can be used to verify a signature
12#[derive(Debug, Eq, Hash, PartialEq, Clone, Copy, SiaEncode, SiaDecode, AsyncSiaDecode)]
13pub struct PublicKey([u8; 32]);
14
15impl PublicKey {
16    const PREFIX: &'static str = "ed25519:";
17}
18
19impl Serialize for PublicKey {
20    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
21        String::serialize(&self.to_string(), serializer)
22    }
23}
24
25impl<'de> Deserialize<'de> for PublicKey {
26    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
27    where
28        D: serde::Deserializer<'de>,
29    {
30        let s = String::deserialize(deserializer)?;
31        let result = s.parse().map_err(|e| Error::custom(format!("{e:?}")))?;
32        Ok(result)
33    }
34}
35
36impl std::str::FromStr for PublicKey {
37    type Err = crate::types::HexParseError;
38
39    fn from_str(s: &str) -> Result<Self, Self::Err> {
40        let s = s
41            .strip_prefix(Self::PREFIX)
42            .ok_or(HexParseError::MissingPrefix)?;
43        let mut pk = [0; 32];
44        hex::decode_to_slice(s, &mut pk)?;
45        Ok(Self::new(pk))
46    }
47}
48
49impl fmt::Display for PublicKey {
50    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51        write!(f, "{}{}", Self::PREFIX, hex::encode(self.0))
52    }
53}
54
55impl PublicKey {
56    pub const fn new(buf: [u8; 32]) -> Self {
57        PublicKey(buf)
58    }
59
60    /// verifies a message against the signature using this public key
61    pub fn verify(&self, msg: &[u8], signature: &Signature) -> bool {
62        let pk = VerifyingKey::from_bytes(&self.0).unwrap();
63        pk.verify(msg, &ED25519Signature::from_bytes(signature.as_ref()))
64            .is_ok()
65    }
66}
67
68impl From<PublicKey> for [u8; 32] {
69    fn from(val: PublicKey) -> Self {
70        val.0
71    }
72}
73
74impl AsRef<[u8]> for PublicKey {
75    fn as_ref(&self) -> &[u8] {
76        &self.0
77    }
78}
79
80/// An ed25519 private key that can be used to sign a hash
81#[derive(Debug, PartialEq, Clone, ZeroizeOnDrop)]
82pub struct PrivateKey([u8; 64]);
83
84impl PrivateKey {
85    pub fn from_seed(seed: &[u8; 32]) -> Self {
86        let sk = SigningKey::from_bytes(seed);
87        PrivateKey(sk.to_keypair_bytes())
88    }
89
90    pub fn public_key(&self) -> PublicKey {
91        let mut buf = [0u8; 32];
92        buf.copy_from_slice(&self.0[32..]);
93        PublicKey::new(buf)
94    }
95
96    pub fn sign(&self, h: &[u8]) -> Signature {
97        let sk = SigningKey::from_bytes(&self.0[..32].try_into().unwrap());
98        Signature::new(sk.sign(h).to_bytes())
99    }
100}
101
102impl AsRef<[u8]> for PrivateKey {
103    fn as_ref(&self) -> &[u8] {
104        &self.0
105    }
106}
107
108impl From<[u8; 64]> for PrivateKey {
109    fn from(key: [u8; 64]) -> Self {
110        PrivateKey(key)
111    }
112}
113
114impl From<Hash256> for PrivateKey {
115    fn from(hash: Hash256) -> Self {
116        PrivateKey::from_seed(hash.as_ref())
117    }
118}
119
120#[derive(Debug, Clone, PartialEq, Eq, SiaEncode, SiaDecode, AsyncSiaDecode)]
121pub struct Signature([u8; 64]);
122
123impl Serialize for Signature {
124    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
125        String::serialize(&hex::encode(self.0), serializer)
126    }
127}
128
129impl<'de> Deserialize<'de> for Signature {
130    fn deserialize<D>(deserializer: D) -> Result<Signature, D::Error>
131    where
132        D: serde::Deserializer<'de>,
133    {
134        let buf = hex::decode(String::deserialize(deserializer)?)
135            .map_err(|e| D::Error::custom(format!("{e:?}")))?;
136        if buf.len() != 64 {
137            return Err(D::Error::custom("Invalid signature length"));
138        }
139        Ok(Signature(buf.try_into().unwrap()))
140    }
141}
142
143impl Signature {
144    pub const fn new(sig: [u8; 64]) -> Self {
145        Signature(sig)
146    }
147
148    pub fn data(&self) -> &[u8] {
149        &self.0
150    }
151}
152
153impl Default for Signature {
154    fn default() -> Self {
155        Signature([0; 64])
156    }
157}
158
159impl AsRef<[u8; 64]> for Signature {
160    fn as_ref(&self) -> &[u8; 64] {
161        &self.0
162    }
163}
164
165impl From<[u8; 64]> for Signature {
166    fn from(buf: [u8; 64]) -> Self {
167        Signature(buf)
168    }
169}
170
171impl std::str::FromStr for Signature {
172    type Err = crate::types::HexParseError;
173
174    fn from_str(s: &str) -> Result<Self, Self::Err> {
175        let data = hex::decode(s).map_err(HexParseError::HexError)?;
176        if data.len() != 64 {
177            return Err(HexParseError::InvalidLength(data.len()));
178        }
179
180        let mut sig = [0u8; 64];
181        sig.copy_from_slice(&data);
182        Ok(Signature(sig))
183    }
184}
185
186/// Converts a slice of bytes into a Signature.
187/// # Errors
188/// Returns an error if the slice is not exactly 64 bytes long.
189impl TryFrom<&[u8]> for Signature {
190    type Error = encoding::Error;
191    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
192        if value.len() != 64 {
193            return Err(encoding::Error::InvalidLength(value.len()));
194        }
195        let mut sig = [0u8; 64];
196        sig.copy_from_slice(value);
197        Ok(Signature(sig))
198    }
199}
200
201impl fmt::Display for Signature {
202    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
203        write!(f, "{}", hex::encode(self.0))
204    }
205}
206
207#[cfg(test)]
208mod tests {
209    use super::*;
210
211    #[test]
212    fn test_serialize_publickey() {
213        let public_key_str = "9aac1ffb1cfd1079a8c6c87b47da1d567e35b97234993c288c1ad0db1d1ce1b6";
214        let public_key = PublicKey::new(hex::decode(public_key_str).unwrap().try_into().unwrap());
215
216        // binary
217        let mut public_key_serialized = Vec::new();
218        public_key.encode(&mut public_key_serialized).unwrap();
219        assert_eq!(public_key_serialized, hex::decode(public_key_str).unwrap());
220        let public_key_deserialized =
221            PublicKey::decode(&mut public_key_serialized.as_slice()).unwrap();
222        assert_eq!(public_key_deserialized, public_key);
223
224        // json
225        let public_key_serialized = serde_json::to_string(&public_key).unwrap();
226        let public_key_deserialized: PublicKey =
227            serde_json::from_str(&public_key_serialized).unwrap();
228        assert_eq!(
229            public_key_serialized,
230            format!("\"ed25519:{public_key_str}\"")
231        );
232        assert_eq!(public_key_deserialized, public_key);
233    }
234}