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