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