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_unchecked, FromStr},
10};
11#[cfg(feature = "alloc")]
12extern crate alloc;
13#[cfg(feature = "std")]
14extern crate std;
15#[cfg(feature = "std")]
16use std::{error::Error, vec::Vec};
17#[cfg(feature = "serde")]
18use {
19 serde_big_array::BigArray,
20 serde_derive::{Deserialize, Serialize},
21};
22
23pub mod error;
24
25pub const SIGNATURE_BYTES: usize = 64;
27const MAX_BASE58_SIGNATURE_LEN: usize = 88;
29
30#[repr(transparent)]
31#[cfg_attr(feature = "frozen-abi", derive(solana_frozen_abi_macro::AbiExample))]
32#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
33#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
34pub struct Signature(
35 #[cfg_attr(feature = "serde", serde(with = "BigArray"))] [u8; SIGNATURE_BYTES],
36);
37
38impl Default for Signature {
39 fn default() -> Self {
40 Self([0u8; 64])
41 }
42}
43
44impl solana_sanitize::Sanitize for Signature {}
45
46impl Signature {
47 #[inline(always)]
49 pub const fn as_array(&self) -> &[u8; SIGNATURE_BYTES] {
50 &self.0
51 }
52}
53
54#[cfg(feature = "rand")]
55impl Signature {
56 pub fn new_unique() -> Self {
57 Self::from(core::array::from_fn(|_| rand::random()))
58 }
59}
60
61#[cfg(any(test, feature = "verify"))]
62impl Signature {
63 pub(self) fn verify_verbose(
64 &self,
65 pubkey_bytes: &[u8],
66 message_bytes: &[u8],
67 ) -> Result<(), ed25519_dalek::SignatureError> {
68 let publickey = ed25519_dalek::PublicKey::from_bytes(pubkey_bytes)?;
69 let signature = self.0.as_slice().try_into()?;
70 publickey.verify_strict(message_bytes, &signature)
71 }
72
73 pub fn verify(&self, pubkey_bytes: &[u8], message_bytes: &[u8]) -> bool {
74 self.verify_verbose(pubkey_bytes, message_bytes).is_ok()
75 }
76}
77
78impl AsRef<[u8]> for Signature {
79 fn as_ref(&self) -> &[u8] {
80 &self.0[..]
81 }
82}
83
84fn write_as_base58(f: &mut fmt::Formatter, s: &Signature) -> fmt::Result {
85 let mut out = [0u8; MAX_BASE58_SIGNATURE_LEN];
86 let len = five8::encode_64(&s.0, &mut out) as usize;
87 let as_str = unsafe { from_utf8_unchecked(&out[..len]) };
89 f.write_str(as_str)
90}
91
92impl fmt::Debug for Signature {
93 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94 write_as_base58(f, self)
95 }
96}
97
98impl fmt::Display for Signature {
99 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100 write_as_base58(f, self)
101 }
102}
103
104impl From<Signature> for [u8; 64] {
105 fn from(signature: Signature) -> Self {
106 signature.0
107 }
108}
109
110impl From<[u8; SIGNATURE_BYTES]> for Signature {
111 #[inline]
112 fn from(signature: [u8; SIGNATURE_BYTES]) -> Self {
113 Self(signature)
114 }
115}
116
117impl<'a> TryFrom<&'a [u8]> for Signature {
118 type Error = <[u8; SIGNATURE_BYTES] as TryFrom<&'a [u8]>>::Error;
119
120 #[inline]
121 fn try_from(signature: &'a [u8]) -> Result<Self, Self::Error> {
122 <[u8; SIGNATURE_BYTES]>::try_from(signature).map(Self::from)
123 }
124}
125
126#[cfg(feature = "std")]
127impl TryFrom<Vec<u8>> for Signature {
128 type Error = <[u8; SIGNATURE_BYTES] as TryFrom<Vec<u8>>>::Error;
129
130 #[inline]
131 fn try_from(signature: Vec<u8>) -> Result<Self, Self::Error> {
132 <[u8; SIGNATURE_BYTES]>::try_from(signature).map(Self::from)
133 }
134}
135
136#[derive(Debug, Clone, PartialEq, Eq)]
137pub enum ParseSignatureError {
138 WrongSize,
139 Invalid,
140}
141
142#[cfg(feature = "std")]
143impl Error for ParseSignatureError {}
144
145impl fmt::Display for ParseSignatureError {
146 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147 match self {
148 ParseSignatureError::WrongSize => {
149 f.write_str("string decoded to wrong size for signature")
150 }
151 ParseSignatureError::Invalid => f.write_str("failed to decode string to signature"),
152 }
153 }
154}
155
156impl FromStr for Signature {
157 type Err = ParseSignatureError;
158
159 fn from_str(s: &str) -> Result<Self, Self::Err> {
160 use five8::DecodeError;
161 if s.len() > MAX_BASE58_SIGNATURE_LEN {
162 return Err(ParseSignatureError::WrongSize);
163 }
164 let mut bytes = [0; SIGNATURE_BYTES];
165 five8::decode_64(s, &mut bytes).map_err(|e| match e {
166 DecodeError::InvalidChar(_) => ParseSignatureError::Invalid,
167 DecodeError::TooLong
168 | DecodeError::TooShort
169 | DecodeError::LargestTermTooHigh
170 | DecodeError::OutputTooLong => ParseSignatureError::WrongSize,
171 })?;
172 Ok(Self::from(bytes))
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use {
179 super::*,
180 serde_derive::{Deserialize, Serialize},
181 solana_pubkey::Pubkey,
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 = "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}