stellar_base/crypto/
signature.rs1use std::io::{Read, Write};
3
4use crate::crypto::{hash, PublicKey};
5use crate::error::{Error, Result};
6use crate::network::Network;
7use crate::transaction::TransactionEnvelope;
8use crate::xdr;
9use ed25519::Signature;
10
11#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct SignatureHint(pub [u8; 4]);
14
15#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct DecoratedSignature {
18 hint: SignatureHint,
19 signature: Signature,
20}
21
22#[derive(Debug, Clone, PartialEq, Eq)]
24pub struct PreAuthTxHash(Vec<u8>);
25
26#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct HashX(Vec<u8>);
29
30#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct SignerKeyEd25519SignedPayload {
33 pub ed25519: PublicKey,
34 pub payload: Vec<u8>,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq)]
39pub enum SignerKey {
40 Ed25519(PublicKey),
41 PreAuthTx(PreAuthTxHash),
42 HashX(HashX),
43 Ed25519SignedPayload(SignerKeyEd25519SignedPayload),
44}
45
46#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct Signer {
49 key: SignerKey,
50 weight: u32,
51}
52
53pub trait XdrSignature {
54 fn to_xdr(&self) -> Result<xdr::Signature>;
56
57 fn from_xdr(x: &xdr::Signature) -> Result<Signature>;
59}
60
61impl XdrSignature for Signature {
62 fn to_xdr(&self) -> Result<xdr::Signature> {
64 Ok(xdr::Signature(
65 self.to_bytes()
66 .try_into()
67 .map_err(|_| Error::InvalidSignature)?,
68 ))
69 }
70
71 fn from_xdr(x: &xdr::Signature) -> Result<Signature> {
73 Signature::from_slice(&x.0).map_err(|_| Error::InvalidSignature)
74 }
75}
76
77impl SignatureHint {
78 pub fn from_public_key(pk: &[u8]) -> SignatureHint {
80 let mut hint: [u8; 4] = Default::default();
81 let len = pk.len();
82 hint.copy_from_slice(&pk[len - 4..len]);
83 SignatureHint(hint)
84 }
85
86 pub fn from_slice(buf: &[u8]) -> Result<SignatureHint> {
88 let mut hint: [u8; 4] = Default::default();
89 if buf.len() != 4 {
90 return Err(Error::InvalidSignatureHint);
91 }
92 hint.copy_from_slice(&buf[0..4]);
93 Ok(SignatureHint(hint))
94 }
95
96 pub fn to_vec(&self) -> Vec<u8> {
98 self.0.to_vec()
99 }
100
101 pub fn to_xdr(&self) -> Result<xdr::SignatureHint> {
103 Ok(xdr::SignatureHint(self.0))
104 }
105
106 pub fn from_xdr(x: &xdr::SignatureHint) -> Result<SignatureHint> {
108 Ok(SignatureHint(x.0))
109 }
110}
111
112impl DecoratedSignature {
113 pub fn new(hint: SignatureHint, signature: Signature) -> DecoratedSignature {
115 DecoratedSignature { hint, signature }
116 }
117
118 pub fn new_from_preimage(preimage: &[u8]) -> Result<DecoratedSignature> {
120 let hint = SignatureHint::from_slice(&preimage[preimage.len() - 4..])?;
121 let signature = Signature::from_slice(preimage).map_err(|_| Error::InvalidSignature)?;
122 Ok(DecoratedSignature::new(hint, signature))
123 }
124
125 pub fn hint(&self) -> &SignatureHint {
127 &self.hint
128 }
129
130 pub fn hint_mut(&mut self) -> &mut SignatureHint {
132 &mut self.hint
133 }
134
135 pub fn signature(&self) -> &Signature {
137 &self.signature
138 }
139
140 pub fn signature_mut(&mut self) -> &mut Signature {
142 &mut self.signature
143 }
144
145 pub fn to_xdr(&self) -> Result<xdr::DecoratedSignature> {
147 let hint = self.hint.to_xdr()?;
148 let signature = self.signature.to_xdr()?;
149 Ok(xdr::DecoratedSignature { hint, signature })
150 }
151
152 pub fn from_xdr(x: &xdr::DecoratedSignature) -> Result<DecoratedSignature> {
154 let hint = SignatureHint::from_xdr(&x.hint)?;
155 let signature = Signature::from_xdr(&x.signature)?;
156 Ok(DecoratedSignature::new(hint, signature))
157 }
158}
159
160impl SignerKey {
161 pub fn new_from_public_key(key: PublicKey) -> SignerKey {
163 SignerKey::Ed25519(key)
164 }
165
166 pub fn new_from_hashx(hashx: HashX) -> SignerKey {
168 SignerKey::HashX(hashx)
169 }
170
171 pub fn new_with_hashx(preimage: &[u8]) -> SignerKey {
173 let hashx = HashX::new_from_preimage(preimage);
174 SignerKey::new_from_hashx(hashx)
175 }
176
177 pub fn new_from_pre_authorized_transaction(preauthtx: PreAuthTxHash) -> SignerKey {
179 SignerKey::PreAuthTx(preauthtx)
180 }
181
182 pub fn new_from_transaction_envelope(
184 tx: &TransactionEnvelope,
185 network: &Network,
186 ) -> Result<SignerKey> {
187 let preauthtx = PreAuthTxHash::new_from_transaction_envelope(tx, network)?;
188 Ok(SignerKey::new_from_pre_authorized_transaction(preauthtx))
189 }
190
191 pub fn as_ed25519(&self) -> Option<&PublicKey> {
193 match *self {
194 SignerKey::Ed25519(ref key) => Some(key),
195 _ => None,
196 }
197 }
198
199 pub fn as_ed25519_mut(&mut self) -> Option<&mut PublicKey> {
201 match *self {
202 SignerKey::Ed25519(ref mut key) => Some(key),
203 _ => None,
204 }
205 }
206
207 pub fn is_ed25519(&self) -> bool {
209 self.as_ed25519().is_some()
210 }
211
212 pub fn as_pre_authorized_transaction(&self) -> Option<&PreAuthTxHash> {
214 match *self {
215 SignerKey::PreAuthTx(ref hash) => Some(hash),
216 _ => None,
217 }
218 }
219
220 pub fn as_pre_authorized_transaction_mut(&mut self) -> Option<&mut PreAuthTxHash> {
222 match *self {
223 SignerKey::PreAuthTx(ref mut hash) => Some(hash),
224 _ => None,
225 }
226 }
227
228 pub fn is_pre_authorized_transaction(&self) -> bool {
230 self.as_pre_authorized_transaction().is_some()
231 }
232
233 pub fn as_hashx(&self) -> Option<&HashX> {
235 match *self {
236 SignerKey::HashX(ref hash) => Some(hash),
237 _ => None,
238 }
239 }
240
241 pub fn as_hashx_mut(&mut self) -> Option<&mut HashX> {
243 match *self {
244 SignerKey::HashX(ref mut hash) => Some(hash),
245 _ => None,
246 }
247 }
248
249 pub fn is_hashx(&self) -> bool {
251 self.as_hashx().is_some()
252 }
253
254 pub fn to_xdr(&self) -> Result<xdr::SignerKey> {
256 match self {
257 SignerKey::Ed25519(pk) => Ok(xdr::SignerKey::Ed25519(xdr::Uint256(pk.0))),
258 SignerKey::PreAuthTx(hash) => {
259 let inner: xdr::Uint256 = hash
260 .0
261 .as_slice()
262 .try_into()
263 .map_err(|_| Error::InvalidPreAuthTx)?;
264 Ok(xdr::SignerKey::PreAuthTx(inner))
265 }
266 SignerKey::HashX(hash) => {
267 let inner: xdr::Uint256 = hash
268 .0
269 .as_slice()
270 .try_into()
271 .map_err(|_| Error::InvalidHashX)?;
272 Ok(xdr::SignerKey::HashX(inner))
273 }
274 SignerKey::Ed25519SignedPayload(signed_payload) => {
275 let payload = signed_payload
276 .payload
277 .as_slice()
278 .try_into()
279 .map_err(|_| Error::InvalidPayload)?;
280 Ok(xdr::SignerKey::Ed25519SignedPayload(
281 xdr::SignerKeyEd25519SignedPayload {
282 ed25519: xdr::Uint256(signed_payload.ed25519.0),
283 payload,
284 },
285 ))
286 }
287 }
288 }
289
290 pub fn from_xdr(x: &xdr::SignerKey) -> Result<SignerKey> {
292 match x {
293 xdr::SignerKey::Ed25519(bytes) => {
294 let pk = PublicKey::from_slice(&bytes.0)?;
295 Ok(SignerKey::Ed25519(pk))
296 }
297 xdr::SignerKey::PreAuthTx(bytes) => {
298 let inner = PreAuthTxHash(bytes.0.to_vec());
299 Ok(SignerKey::PreAuthTx(inner))
300 }
301 xdr::SignerKey::HashX(bytes) => {
302 let inner = HashX(bytes.0.to_vec());
303 Ok(SignerKey::HashX(inner))
304 }
305 xdr::SignerKey::Ed25519SignedPayload(signed_payload) => {
306 let ed25519 = PublicKey::from_slice(&signed_payload.ed25519.0)?;
307 let payload = signed_payload.payload.to_vec();
308 Ok(SignerKey::Ed25519SignedPayload(
309 SignerKeyEd25519SignedPayload { ed25519, payload },
310 ))
311 }
312 }
313 }
314}
315
316impl Signer {
317 pub fn new(key: SignerKey, weight: u32) -> Signer {
319 Signer { key, weight }
320 }
321
322 pub fn key(&self) -> &SignerKey {
324 &self.key
325 }
326
327 pub fn key_mut(&mut self) -> &mut SignerKey {
329 &mut self.key
330 }
331
332 pub fn weight(&self) -> &u32 {
334 &self.weight
335 }
336
337 pub fn weight_mut(&mut self) -> &mut u32 {
339 &mut self.weight
340 }
341
342 pub fn to_xdr(&self) -> Result<xdr::Signer> {
344 let key = self.key.to_xdr()?;
345 Ok(xdr::Signer {
346 key,
347 weight: self.weight,
348 })
349 }
350
351 pub fn from_xdr(x: &xdr::Signer) -> Result<Signer> {
353 let key = SignerKey::from_xdr(&x.key)?;
354 Ok(Signer {
355 key,
356 weight: x.weight,
357 })
358 }
359}
360
361impl PreAuthTxHash {
362 pub fn new(hash: Vec<u8>) -> Result<PreAuthTxHash> {
366 if hash.len() != 32 {
367 return Err(Error::InvalidPreAuthTx);
368 }
369 Ok(PreAuthTxHash(hash))
370 }
371
372 pub fn new_from_transaction_envelope(
374 tx: &TransactionEnvelope,
375 network: &Network,
376 ) -> Result<PreAuthTxHash> {
377 let hash = tx.hash(network)?;
378 PreAuthTxHash::new(hash)
379 }
380
381 pub fn as_bytes(&self) -> &[u8] {
383 &self.0
384 }
385}
386
387impl HashX {
388 pub fn new(hashx: Vec<u8>) -> Result<HashX> {
392 if hashx.len() != 32 {
393 return Err(Error::InvalidHashX);
394 }
395 Ok(HashX(hashx))
396 }
397
398 pub fn new_from_preimage(preimage: &[u8]) -> HashX {
400 HashX(hash(preimage))
403 }
404
405 pub fn as_bytes(&self) -> &[u8] {
407 &self.0
408 }
409}
410
411impl xdr::WriteXdr for SignerKey {
412 fn write_xdr<W: Write>(&self, w: &mut xdr::Limited<W>) -> xdr::Result<()> {
413 let xdr = self.to_xdr().map_err(|_| xdr::Error::Invalid)?;
414 xdr.write_xdr(w)
415 }
416}
417
418impl xdr::ReadXdr for SignerKey {
419 fn read_xdr<R: Read>(r: &mut xdr::Limited<R>) -> xdr::Result<Self> {
420 let xdr_result = xdr::SignerKey::read_xdr(r)?;
421 Self::from_xdr(&xdr_result).map_err(|_| xdr::Error::Invalid)
422 }
423}
424
425impl xdr::WriteXdr for Signer {
426 fn write_xdr<W: Write>(&self, w: &mut xdr::Limited<W>) -> xdr::Result<()> {
427 let xdr = self.to_xdr().map_err(|_| xdr::Error::Invalid)?;
428 xdr.write_xdr(w)
429 }
430}
431
432impl xdr::ReadXdr for Signer {
433 fn read_xdr<R: Read>(r: &mut xdr::Limited<R>) -> xdr::Result<Self> {
434 let xdr_result = xdr::Signer::read_xdr(r)?;
435 Self::from_xdr(&xdr_result).map_err(|_| xdr::Error::Invalid)
436 }
437}
438
439#[cfg(test)]
440mod tests {
441 use super::SignerKey;
442 use crate::crypto::PublicKey;
443 use crate::network::Network;
444 use crate::transaction::TransactionEnvelope;
445 use crate::xdr::{XDRDeserialize as _, XDRSerialize as _};
446
447 #[test]
448 fn test_signer_key_from_public_key() {
449 let key =
450 PublicKey::from_account_id("GCEE2MAVLB3D5J64TTHR3T4ZYK4BZJEYIPE7FMG4NAXHY3VQRHW55BNX")
451 .unwrap();
452 let signer_key = SignerKey::new_from_public_key(key);
453 assert!(signer_key.is_ed25519());
454 assert!(!signer_key.is_pre_authorized_transaction());
455 assert!(!signer_key.is_hashx());
456
457 let xdr = signer_key.xdr_base64().unwrap();
458 let expected_xdr = "AAAAAIhNMBVYdj6n3JzPHc+ZwrgcpJhDyfKw3GgufG6wie3e";
459 assert_eq!(expected_xdr, xdr);
460
461 let back = SignerKey::from_xdr_base64(&xdr).unwrap();
462 assert_eq!(back, signer_key);
463 }
464
465 #[test]
466 fn test_signer_key_with_hashx() {
467 let data = "hello".to_string();
468 let signer_key = SignerKey::new_with_hashx(data.as_bytes());
469
470 assert!(!signer_key.is_ed25519());
471 assert!(!signer_key.is_pre_authorized_transaction());
472 assert!(signer_key.is_hashx());
473
474 let hashx = signer_key.as_hashx().unwrap();
475
476 assert_eq!(
477 "LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=".to_string(),
478 base64::Engine::encode(&base64::engine::general_purpose::STANDARD, hashx.as_bytes())
479 );
480
481 let xdr = signer_key.xdr_base64().unwrap();
482 let expected_xdr = "AAAAAizyTbpfsKMOJug7KsW54p4bFh5cH6dCXnMEM2KTi5gk";
483 assert_eq!(expected_xdr, xdr);
484
485 let back = SignerKey::from_xdr_base64(&xdr).unwrap();
486 assert_eq!(back, signer_key);
487 }
488
489 #[test]
490 fn test_signer_key_with_pre_authorized_transaction() {
491 let tx = TransactionEnvelope::from_xdr_base64("AAAAAgAAAACITTAVWHY+p9yczx3PmcK4HKSYQ8nysNxoLnxusInt3gAAAGQAAAAAAAAAewAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap();
492 let signer_key =
493 SignerKey::new_from_transaction_envelope(&tx, &Network::new_test()).unwrap();
494
495 assert!(!signer_key.is_ed25519());
496 assert!(signer_key.is_pre_authorized_transaction());
497 assert!(!signer_key.is_hashx());
498
499 let tx_hash = signer_key
500 .as_pre_authorized_transaction()
501 .unwrap()
502 .as_bytes();
503 assert_eq!(
505 "xkhj28AGwJ4ykWcbjN4347wQFhOKXg1qKFKwiXiKtzY=",
506 base64::Engine::encode(&base64::engine::general_purpose::STANDARD, tx_hash)
507 );
508
509 let xdr = signer_key.xdr_base64().unwrap();
510 let expected_xdr = "AAAAAcZIY9vABsCeMpFnG4zeN+O8EBYTil4NaihSsIl4irc2";
511 assert_eq!(expected_xdr, xdr);
512
513 let back = SignerKey::from_xdr_base64(&xdr).unwrap();
514 assert_eq!(back, signer_key);
515 }
516}