1#![no_std]
3#![cfg_attr(docsrs, feature(doc_auto_cfg))]
4#![cfg_attr(feature = "frozen-abi", feature(min_specialization))]
5#[cfg(any(test, feature = "verify"))]
6use core::convert::TryInto;
7use core::{
8 fmt,
9 str::{from_utf8, FromStr},
10};
11#[cfg(feature = "std")]
12extern crate std;
13#[cfg(feature = "std")]
14use std::{error::Error, vec::Vec};
15#[cfg(feature = "serde")]
16use {
17 serde_big_array::BigArray,
18 serde_derive::{Deserialize, Serialize},
19};
20
21pub const SIGNATURE_BYTES: usize = 64;
23const MAX_BASE58_SIGNATURE_LEN: usize = 88;
25
26#[repr(transparent)]
27#[cfg_attr(
28 feature = "frozen-abi",
29 derive(clone_solana_frozen_abi_macro::AbiExample)
30)]
31#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
32#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
33pub struct Signature(
34 #[cfg_attr(feature = "serde", serde(with = "BigArray"))] [u8; SIGNATURE_BYTES],
35);
36
37impl Default for Signature {
38 fn default() -> Self {
39 Self([0u8; 64])
40 }
41}
42
43impl clone_solana_sanitize::Sanitize for Signature {}
44
45impl Signature {
46 #[inline(always)]
48 pub const fn as_array(&self) -> &[u8; SIGNATURE_BYTES] {
49 &self.0
50 }
51}
52
53#[cfg(feature = "rand")]
54impl Signature {
55 pub fn new_unique() -> Self {
56 Self::from(core::array::from_fn(|_| rand::random()))
57 }
58}
59
60#[cfg(any(test, feature = "verify"))]
61impl Signature {
62 pub(self) fn verify_verbose(
63 &self,
64 pubkey_bytes: &[u8],
65 message_bytes: &[u8],
66 ) -> Result<(), ed25519_dalek::SignatureError> {
67 let publickey = ed25519_dalek::PublicKey::from_bytes(pubkey_bytes)?;
68 let signature = self.0.as_slice().try_into()?;
69 publickey.verify_strict(message_bytes, &signature)
70 }
71
72 pub fn verify(&self, pubkey_bytes: &[u8], message_bytes: &[u8]) -> bool {
73 self.verify_verbose(pubkey_bytes, message_bytes).is_ok()
74 }
75}
76
77impl AsRef<[u8]> for Signature {
78 fn as_ref(&self) -> &[u8] {
79 &self.0[..]
80 }
81}
82
83fn write_as_base58(f: &mut fmt::Formatter, s: &Signature) -> fmt::Result {
84 let mut out = [0u8; MAX_BASE58_SIGNATURE_LEN];
85 let out_slice: &mut [u8] = &mut out;
86 let len = bs58::encode(s.0).onto(out_slice).unwrap();
89 let as_str = from_utf8(&out[..len]).unwrap();
90 f.write_str(as_str)
91}
92
93impl fmt::Debug for Signature {
94 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95 write_as_base58(f, self)
96 }
97}
98
99impl fmt::Display for Signature {
100 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101 write_as_base58(f, self)
102 }
103}
104
105impl From<Signature> for [u8; 64] {
106 fn from(signature: Signature) -> Self {
107 signature.0
108 }
109}
110
111impl From<[u8; SIGNATURE_BYTES]> for Signature {
112 #[inline]
113 fn from(signature: [u8; SIGNATURE_BYTES]) -> Self {
114 Self(signature)
115 }
116}
117
118impl<'a> TryFrom<&'a [u8]> for Signature {
119 type Error = <[u8; SIGNATURE_BYTES] as TryFrom<&'a [u8]>>::Error;
120
121 #[inline]
122 fn try_from(signature: &'a [u8]) -> Result<Self, Self::Error> {
123 <[u8; SIGNATURE_BYTES]>::try_from(signature).map(Self::from)
124 }
125}
126
127#[cfg(feature = "std")]
128impl TryFrom<Vec<u8>> for Signature {
129 type Error = <[u8; SIGNATURE_BYTES] as TryFrom<Vec<u8>>>::Error;
130
131 #[inline]
132 fn try_from(signature: Vec<u8>) -> Result<Self, Self::Error> {
133 <[u8; SIGNATURE_BYTES]>::try_from(signature).map(Self::from)
134 }
135}
136
137#[derive(Debug, Clone, PartialEq, Eq)]
138pub enum ParseSignatureError {
139 WrongSize,
140 Invalid,
141}
142
143#[cfg(feature = "std")]
144impl Error for ParseSignatureError {}
145
146impl fmt::Display for ParseSignatureError {
147 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
148 match self {
149 ParseSignatureError::WrongSize => {
150 f.write_str("string decoded to wrong size for signature")
151 }
152 ParseSignatureError::Invalid => f.write_str("failed to decode string to signature"),
153 }
154 }
155}
156
157impl FromStr for Signature {
158 type Err = ParseSignatureError;
159
160 fn from_str(s: &str) -> Result<Self, Self::Err> {
161 if s.len() > MAX_BASE58_SIGNATURE_LEN {
162 return Err(ParseSignatureError::WrongSize);
163 }
164 let mut bytes = [0; SIGNATURE_BYTES];
165 let decoded_size = bs58::decode(s)
166 .onto(&mut bytes)
167 .map_err(|_| ParseSignatureError::Invalid)?;
168 if decoded_size != SIGNATURE_BYTES {
169 Err(ParseSignatureError::WrongSize)
170 } else {
171 Ok(bytes.into())
172 }
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use {
179 super::*,
180 clone_solana_pubkey::Pubkey,
181 serde_derive::{Deserialize, Serialize},
182 };
183
184 #[test]
185 fn test_off_curve_pubkey_verify_fails() {
186 let off_curve_bytes = bs58::decode("9z5nJyQar1FUxVJxpBXzon6kHehbomeYiDaLi9WAMhCq")
188 .into_vec()
189 .unwrap();
190
191 let mut off_curve_bits = [0u8; 32];
193 off_curve_bits.copy_from_slice(&off_curve_bytes);
194 let off_curve_point = curve25519_dalek::edwards::CompressedEdwardsY(off_curve_bits);
195 assert_eq!(off_curve_point.decompress(), None);
196
197 let pubkey = Pubkey::try_from(off_curve_bytes).unwrap();
198 let signature = Signature::default();
199 assert!(signature.verify_verbose(pubkey.as_ref(), &[0u8]).is_err());
203 }
204
205 #[test]
206 fn test_short_vec() {
207 #[derive(Debug, Deserialize, Serialize, PartialEq)]
208 struct SigShortVec {
209 #[serde(with = "clone_solana_short_vec")]
210 pub signatures: Vec<Signature>,
211 }
212 let sig = Signature::from([
213 120, 138, 162, 185, 59, 209, 241, 157, 71, 157, 74, 131, 4, 87, 54, 28, 38, 180, 222,
214 82, 64, 62, 61, 62, 22, 46, 17, 203, 187, 136, 62, 43, 11, 38, 235, 17, 239, 82, 240,
215 139, 130, 217, 227, 214, 9, 242, 141, 223, 94, 29, 184, 110, 62, 32, 87, 137, 63, 139,
216 100, 221, 20, 137, 4, 5,
217 ]);
218 let to_serialize = SigShortVec {
219 signatures: std::vec![sig],
220 };
221 let json_serialized = serde_json::to_string(&to_serialize).unwrap();
222 assert_eq!(json_serialized, "{\"signatures\":[[1],[120,138,162,185,59,209,241,157,71,157,74,131,4,87,54,28,38,180,222,82,64,62,61,62,22,46,17,203,187,136,62,43,11,38,235,17,239,82,240,139,130,217,227,214,9,242,141,223,94,29,184,110,62,32,87,137,63,139,100,221,20,137,4,5]]}");
223 let json_deserialized: SigShortVec = serde_json::from_str(&json_serialized).unwrap();
224 assert_eq!(json_deserialized, to_serialize);
225 let bincode_serialized = bincode::serialize(&to_serialize).unwrap();
226 assert_eq!(
227 bincode_serialized,
228 [
229 1, 120, 138, 162, 185, 59, 209, 241, 157, 71, 157, 74, 131, 4, 87, 54, 28, 38, 180,
230 222, 82, 64, 62, 61, 62, 22, 46, 17, 203, 187, 136, 62, 43, 11, 38, 235, 17, 239,
231 82, 240, 139, 130, 217, 227, 214, 9, 242, 141, 223, 94, 29, 184, 110, 62, 32, 87,
232 137, 63, 139, 100, 221, 20, 137, 4, 5
233 ]
234 );
235 let bincode_deserialized: SigShortVec = bincode::deserialize(&bincode_serialized).unwrap();
236 assert_eq!(bincode_deserialized, to_serialize);
237 }
238
239 #[test]
240 fn test_signature_fromstr() {
241 let signature = Signature::from([
242 103, 7, 88, 96, 203, 140, 191, 47, 231, 37, 30, 220, 61, 35, 93, 112, 225, 2, 5, 11,
243 158, 105, 246, 147, 133, 64, 109, 252, 119, 73, 108, 248, 167, 240, 160, 18, 222, 3, 1,
244 48, 51, 67, 94, 19, 91, 108, 227, 126, 100, 25, 212, 135, 90, 60, 61, 78, 186, 104, 22,
245 58, 242, 74, 148, 6,
246 ]);
247
248 let mut signature_base58_str = bs58::encode(signature).into_string();
249
250 assert_eq!(signature_base58_str.parse::<Signature>(), Ok(signature));
251
252 signature_base58_str.push_str(&bs58::encode(<[u8; 64]>::from(signature)).into_string());
253 assert_eq!(
254 signature_base58_str.parse::<Signature>(),
255 Err(ParseSignatureError::WrongSize)
256 );
257
258 signature_base58_str.truncate(signature_base58_str.len() / 2);
259 assert_eq!(signature_base58_str.parse::<Signature>(), Ok(signature));
260
261 signature_base58_str.truncate(signature_base58_str.len() / 2);
262 assert_eq!(
263 signature_base58_str.parse::<Signature>(),
264 Err(ParseSignatureError::WrongSize)
265 );
266
267 let mut signature_base58_str = bs58::encode(<[u8; 64]>::from(signature)).into_string();
268 assert_eq!(signature_base58_str.parse::<Signature>(), Ok(signature));
269
270 signature_base58_str.replace_range(..1, "I");
272 assert_eq!(
273 signature_base58_str.parse::<Signature>(),
274 Err(ParseSignatureError::Invalid)
275 );
276
277 let mut too_long = bs58::encode(&[255u8; SIGNATURE_BYTES]).into_string();
280 too_long.push('1');
282 assert_eq!(
283 too_long.parse::<Signature>(),
284 Err(ParseSignatureError::WrongSize)
285 );
286 }
287
288 #[test]
289 fn test_as_array() {
290 let bytes = [1u8; 64];
291 let signature = Signature::from(bytes);
292 assert_eq!(signature.as_array(), &bytes);
293 assert_eq!(
294 signature.as_array(),
295 &<Signature as Into<[u8; 64]>>::into(signature)
296 );
297 assert_eq!(signature.as_array().as_ptr(), signature.0.as_ptr());
299 }
300}