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