| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  | //! The `signature` module provides functionality for public, and private keys.
 | 
					
						
							| 
									
										
										
										
											2020-10-24 08:39:28 -07:00
										 |  |  | #![cfg(feature = "full")]
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  | use crate::{pubkey::Pubkey, transaction::TransactionError};
 | 
					
						
							| 
									
										
										
										
											2020-07-23 17:23:51 -06:00
										 |  |  | use ed25519_dalek::Signer as DalekSigner;
 | 
					
						
							| 
									
										
										
										
											2019-11-07 17:08:10 -08:00
										 |  |  | use generic_array::{typenum::U64, GenericArray};
 | 
					
						
							| 
									
										
										
										
											2019-11-22 10:20:40 -05:00
										 |  |  | use hmac::Hmac;
 | 
					
						
							| 
									
										
										
										
											2020-05-18 19:31:45 -06:00
										 |  |  | use itertools::Itertools;
 | 
					
						
							| 
									
										
										
										
											2020-02-12 14:15:12 -07:00
										 |  |  | use rand::{rngs::OsRng, CryptoRng, RngCore};
 | 
					
						
							| 
									
										
										
										
											2019-11-07 17:08:10 -08:00
										 |  |  | use std::{
 | 
					
						
							|  |  |  |     borrow::{Borrow, Cow},
 | 
					
						
							| 
									
										
										
										
											2020-07-23 17:23:51 -06:00
										 |  |  |     convert::TryInto,
 | 
					
						
							| 
									
										
										
										
											2019-11-07 17:08:10 -08:00
										 |  |  |     error, fmt,
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:26:21 -07:00
										 |  |  |     fs::{self, File, OpenOptions},
 | 
					
						
							| 
									
										
										
										
											2019-11-07 17:08:10 -08:00
										 |  |  |     io::{Read, Write},
 | 
					
						
							|  |  |  |     mem,
 | 
					
						
							|  |  |  |     path::Path,
 | 
					
						
							|  |  |  |     str::FromStr,
 | 
					
						
							|  |  |  | };
 | 
					
						
							| 
									
										
										
										
											2020-02-13 17:53:09 -07:00
										 |  |  | use thiserror::Error;
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-23 17:23:51 -06:00
										 |  |  | #[derive(Debug)]
 | 
					
						
							| 
									
										
										
										
											2020-02-12 14:15:12 -07:00
										 |  |  | pub struct Keypair(ed25519_dalek::Keypair);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl Keypair {
 | 
					
						
							|  |  |  |     pub fn generate<R>(csprng: &mut R) -> Self
 | 
					
						
							|  |  |  |     where
 | 
					
						
							|  |  |  |         R: CryptoRng + RngCore,
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         Self(ed25519_dalek::Keypair::generate(csprng))
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /// Return a new ED25519 keypair
 | 
					
						
							|  |  |  |     pub fn new() -> Self {
 | 
					
						
							| 
									
										
										
										
											2020-04-27 09:33:33 -07:00
										 |  |  |         let mut rng = OsRng::default();
 | 
					
						
							| 
									
										
										
										
											2020-02-12 14:15:12 -07:00
										 |  |  |         Self::generate(&mut rng)
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn from_bytes(bytes: &[u8]) -> Result<Self, ed25519_dalek::SignatureError> {
 | 
					
						
							|  |  |  |         ed25519_dalek::Keypair::from_bytes(bytes).map(Self)
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn to_bytes(&self) -> [u8; 64] {
 | 
					
						
							|  |  |  |         self.0.to_bytes()
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-19 16:37:03 +09:00
										 |  |  |     pub fn from_base58_string(s: &str) -> Self {
 | 
					
						
							|  |  |  |         Self::from_bytes(&bs58::decode(s).into_vec().unwrap()).unwrap()
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn to_base58_string(&self) -> String {
 | 
					
						
							|  |  |  |         // Remove .iter() once we're rust 1.47+
 | 
					
						
							|  |  |  |         bs58::encode(&self.0.to_bytes().iter()).into_string()
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-12 14:15:12 -07:00
										 |  |  |     pub fn secret(&self) -> &ed25519_dalek::SecretKey {
 | 
					
						
							|  |  |  |         &self.0.secret
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-15 13:17:17 -06:00
										 |  |  | #[repr(transparent)]
 | 
					
						
							| 
									
										
										
										
											2020-07-06 20:22:23 +09:00
										 |  |  | #[derive(
 | 
					
						
							|  |  |  |     Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash, AbiExample,
 | 
					
						
							|  |  |  | )]
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  | pub struct Signature(GenericArray<u8, U64>);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-27 11:06:00 -07:00
										 |  |  | impl crate::sanitize::Sanitize for Signature {}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  | impl Signature {
 | 
					
						
							|  |  |  |     pub fn new(signature_slice: &[u8]) -> Self {
 | 
					
						
							| 
									
										
										
										
											2019-03-17 19:48:12 -07:00
										 |  |  |         Self(GenericArray::clone_from_slice(&signature_slice))
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-30 18:10:41 -06:00
										 |  |  |     pub(self) fn verify_verbose(
 | 
					
						
							|  |  |  |         &self,
 | 
					
						
							|  |  |  |         pubkey_bytes: &[u8],
 | 
					
						
							|  |  |  |         message_bytes: &[u8],
 | 
					
						
							|  |  |  |     ) -> Result<(), ed25519_dalek::SignatureError> {
 | 
					
						
							|  |  |  |         let publickey = ed25519_dalek::PublicKey::from_bytes(pubkey_bytes)?;
 | 
					
						
							|  |  |  |         let signature = self.0.as_slice().try_into()?;
 | 
					
						
							|  |  |  |         publickey.verify_strict(message_bytes, &signature)
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  |     pub fn verify(&self, pubkey_bytes: &[u8], message_bytes: &[u8]) -> bool {
 | 
					
						
							| 
									
										
										
										
											2020-07-30 18:10:41 -06:00
										 |  |  |         self.verify_verbose(pubkey_bytes, message_bytes).is_ok()
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-01 12:00:30 -08:00
										 |  |  | pub trait Signable {
 | 
					
						
							|  |  |  |     fn sign(&mut self, keypair: &Keypair) {
 | 
					
						
							| 
									
										
										
										
											2019-06-12 16:43:05 -07:00
										 |  |  |         let signature = keypair.sign_message(self.signable_data().borrow());
 | 
					
						
							|  |  |  |         self.set_signature(signature);
 | 
					
						
							| 
									
										
										
										
											2018-12-01 12:00:30 -08:00
										 |  |  |     }
 | 
					
						
							|  |  |  |     fn verify(&self) -> bool {
 | 
					
						
							|  |  |  |         self.get_signature()
 | 
					
						
							| 
									
										
										
										
											2019-06-12 16:43:05 -07:00
										 |  |  |             .verify(&self.pubkey().as_ref(), self.signable_data().borrow())
 | 
					
						
							| 
									
										
										
										
											2018-12-01 12:00:30 -08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fn pubkey(&self) -> Pubkey;
 | 
					
						
							| 
									
										
										
										
											2019-06-12 16:43:05 -07:00
										 |  |  |     fn signable_data(&self) -> Cow<[u8]>;
 | 
					
						
							| 
									
										
										
										
											2018-12-01 12:00:30 -08:00
										 |  |  |     fn get_signature(&self) -> Signature;
 | 
					
						
							|  |  |  |     fn set_signature(&mut self, signature: Signature);
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  | impl AsRef<[u8]> for Signature {
 | 
					
						
							|  |  |  |     fn as_ref(&self) -> &[u8] {
 | 
					
						
							|  |  |  |         &self.0[..]
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl fmt::Debug for Signature {
 | 
					
						
							|  |  |  |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
					
						
							|  |  |  |         write!(f, "{}", bs58::encode(self.0).into_string())
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl fmt::Display for Signature {
 | 
					
						
							|  |  |  |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
					
						
							|  |  |  |         write!(f, "{}", bs58::encode(self.0).into_string())
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-15 13:17:17 -06:00
										 |  |  | impl Into<[u8; 64]> for Signature {
 | 
					
						
							|  |  |  |     fn into(self) -> [u8; 64] {
 | 
					
						
							|  |  |  |         <GenericArray<u8, U64> as Into<[u8; 64]>>::into(self.0)
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-13 00:20:49 -06:00
										 |  |  | #[derive(Debug, Clone, PartialEq, Eq, Error)]
 | 
					
						
							| 
									
										
										
										
											2019-05-16 14:54:31 -07:00
										 |  |  | pub enum ParseSignatureError {
 | 
					
						
							| 
									
										
										
										
											2020-03-13 00:20:49 -06:00
										 |  |  |     #[error("string decoded to wrong size for signature")]
 | 
					
						
							| 
									
										
										
										
											2019-05-16 14:54:31 -07:00
										 |  |  |     WrongSize,
 | 
					
						
							| 
									
										
										
										
											2020-03-13 00:20:49 -06:00
										 |  |  |     #[error("failed to decode string to signature")]
 | 
					
						
							| 
									
										
										
										
											2019-05-16 14:54:31 -07:00
										 |  |  |     Invalid,
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl FromStr for Signature {
 | 
					
						
							|  |  |  |     type Err = ParseSignatureError;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fn from_str(s: &str) -> Result<Self, Self::Err> {
 | 
					
						
							|  |  |  |         let bytes = bs58::decode(s)
 | 
					
						
							|  |  |  |             .into_vec()
 | 
					
						
							|  |  |  |             .map_err(|_| ParseSignatureError::Invalid)?;
 | 
					
						
							|  |  |  |         if bytes.len() != mem::size_of::<Signature>() {
 | 
					
						
							|  |  |  |             Err(ParseSignatureError::WrongSize)
 | 
					
						
							|  |  |  |         } else {
 | 
					
						
							|  |  |  |             Ok(Signature::new(&bytes))
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 14:28:55 -07:00
										 |  |  | pub trait Signer {
 | 
					
						
							| 
									
										
										
										
											2020-02-13 14:08:35 -07:00
										 |  |  |     fn pubkey(&self) -> Pubkey {
 | 
					
						
							|  |  |  |         self.try_pubkey().unwrap_or_default()
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  |     fn try_pubkey(&self) -> Result<Pubkey, SignerError>;
 | 
					
						
							| 
									
										
										
										
											2020-02-13 14:08:35 -07:00
										 |  |  |     fn sign_message(&self, message: &[u8]) -> Signature {
 | 
					
						
							|  |  |  |         self.try_sign_message(message).unwrap_or_default()
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  |     fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError>;
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-21 14:55:53 -07:00
										 |  |  | impl PartialEq for dyn Signer {
 | 
					
						
							|  |  |  |     fn eq(&self, other: &dyn Signer) -> bool {
 | 
					
						
							|  |  |  |         self.pubkey() == other.pubkey()
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl std::fmt::Debug for dyn Signer {
 | 
					
						
							|  |  |  |     fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
 | 
					
						
							|  |  |  |         write!(fmt, "Signer: {:?}", self.pubkey())
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-18 19:31:45 -06:00
										 |  |  | /// Remove duplicates signers while preserving order. O(n²)
 | 
					
						
							|  |  |  | pub fn unique_signers(signers: Vec<&dyn Signer>) -> Vec<&dyn Signer> {
 | 
					
						
							|  |  |  |     signers.into_iter().unique_by(|s| s.pubkey()).collect()
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 14:28:55 -07:00
										 |  |  | impl Signer for Keypair {
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  |     /// Return the public key for the given keypair
 | 
					
						
							|  |  |  |     fn pubkey(&self) -> Pubkey {
 | 
					
						
							| 
									
										
										
										
											2020-02-12 14:15:12 -07:00
										 |  |  |         Pubkey::new(self.0.public.as_ref())
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2019-01-25 23:41:20 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  |     fn try_pubkey(&self) -> Result<Pubkey, SignerError> {
 | 
					
						
							| 
									
										
										
										
											2020-02-13 14:08:35 -07:00
										 |  |  |         Ok(self.pubkey())
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-25 23:41:20 -07:00
										 |  |  |     fn sign_message(&self, message: &[u8]) -> Signature {
 | 
					
						
							| 
									
										
										
										
											2020-02-12 14:15:12 -07:00
										 |  |  |         Signature::new(&self.0.sign(message).to_bytes())
 | 
					
						
							| 
									
										
										
										
											2019-01-25 23:41:20 -07:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-02-13 14:08:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  |     fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError> {
 | 
					
						
							| 
									
										
										
										
											2020-02-13 14:08:35 -07:00
										 |  |  |         Ok(self.sign_message(message))
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-13 17:53:09 -07:00
										 |  |  | impl<T> PartialEq<T> for Keypair
 | 
					
						
							|  |  |  | where
 | 
					
						
							| 
									
										
										
										
											2020-02-20 14:28:55 -07:00
										 |  |  |     T: Signer,
 | 
					
						
							| 
									
										
										
										
											2020-02-13 17:53:09 -07:00
										 |  |  | {
 | 
					
						
							|  |  |  |     fn eq(&self, other: &T) -> bool {
 | 
					
						
							|  |  |  |         self.pubkey() == other.pubkey()
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-21 14:55:53 -07:00
										 |  |  | impl<T> From<T> for Box<dyn Signer>
 | 
					
						
							|  |  |  | where
 | 
					
						
							|  |  |  |     T: Signer + 'static,
 | 
					
						
							|  |  |  | {
 | 
					
						
							| 
									
										
										
										
											2020-02-24 17:03:30 -07:00
										 |  |  |     fn from(signer: T) -> Self {
 | 
					
						
							|  |  |  |         Box::new(signer)
 | 
					
						
							| 
									
										
										
										
											2020-02-21 14:55:53 -07:00
										 |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  | #[derive(Debug, Error, PartialEq)]
 | 
					
						
							|  |  |  | pub enum SignerError {
 | 
					
						
							|  |  |  |     #[error("keypair-pubkey mismatch")]
 | 
					
						
							|  |  |  |     KeypairPubkeyMismatch,
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[error("not enough signers")]
 | 
					
						
							|  |  |  |     NotEnoughSigners,
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[error("transaction error")]
 | 
					
						
							|  |  |  |     TransactionError(#[from] TransactionError),
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[error("custom error: {0}")]
 | 
					
						
							| 
									
										
										
										
											2020-04-01 11:13:31 -07:00
										 |  |  |     Custom(String),
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Presigner-specific Errors
 | 
					
						
							|  |  |  |     #[error("presigner error")]
 | 
					
						
							|  |  |  |     PresignerError(#[from] PresignerError),
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Remote Keypair-specific Errors
 | 
					
						
							|  |  |  |     #[error("connection error: {0}")]
 | 
					
						
							| 
									
										
										
										
											2020-04-01 11:13:31 -07:00
										 |  |  |     Connection(String),
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     #[error("invalid input: {0}")]
 | 
					
						
							|  |  |  |     InvalidInput(String),
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[error("no device found")]
 | 
					
						
							|  |  |  |     NoDeviceFound,
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-14 22:52:11 -06:00
										 |  |  |     #[error("{0}")]
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  |     Protocol(String),
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-27 12:23:13 -07:00
										 |  |  |     #[error("{0}")]
 | 
					
						
							|  |  |  |     UserCancel(String),
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-21 14:55:53 -07:00
										 |  |  | #[derive(Clone, Debug, Default)]
 | 
					
						
							| 
									
										
										
										
											2020-02-13 17:53:09 -07:00
										 |  |  | pub struct Presigner {
 | 
					
						
							|  |  |  |     pubkey: Pubkey,
 | 
					
						
							|  |  |  |     signature: Signature,
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl Presigner {
 | 
					
						
							| 
									
										
										
										
											2020-02-21 14:55:53 -07:00
										 |  |  |     pub fn new(pubkey: &Pubkey, signature: &Signature) -> Self {
 | 
					
						
							| 
									
										
										
										
											2020-02-13 17:53:09 -07:00
										 |  |  |         Self {
 | 
					
						
							|  |  |  |             pubkey: *pubkey,
 | 
					
						
							|  |  |  |             signature: *signature,
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #[derive(Debug, Error, PartialEq)]
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  | pub enum PresignerError {
 | 
					
						
							| 
									
										
										
										
											2020-02-13 17:53:09 -07:00
										 |  |  |     #[error("pre-generated signature cannot verify data")]
 | 
					
						
							|  |  |  |     VerificationFailure,
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 14:28:55 -07:00
										 |  |  | impl Signer for Presigner {
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  |     fn try_pubkey(&self) -> Result<Pubkey, SignerError> {
 | 
					
						
							| 
									
										
										
										
											2020-02-13 17:53:09 -07:00
										 |  |  |         Ok(self.pubkey)
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 20:04:53 -07:00
										 |  |  |     fn try_sign_message(&self, message: &[u8]) -> Result<Signature, SignerError> {
 | 
					
						
							| 
									
										
										
										
											2020-02-13 17:53:09 -07:00
										 |  |  |         if self.signature.verify(self.pubkey.as_ref(), message) {
 | 
					
						
							|  |  |  |             Ok(self.signature)
 | 
					
						
							|  |  |  |         } else {
 | 
					
						
							|  |  |  |             Err(PresignerError::VerificationFailure.into())
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl<T> PartialEq<T> for Presigner
 | 
					
						
							|  |  |  | where
 | 
					
						
							| 
									
										
										
										
											2020-02-20 14:28:55 -07:00
										 |  |  |     T: Signer,
 | 
					
						
							| 
									
										
										
										
											2020-02-13 17:53:09 -07:00
										 |  |  | {
 | 
					
						
							|  |  |  |     fn eq(&self, other: &T) -> bool {
 | 
					
						
							|  |  |  |         self.pubkey() == other.pubkey()
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-18 21:49:38 -06:00
										 |  |  | /// NullSigner - A `Signer` implementation that always produces `Signature::default()`.
 | 
					
						
							|  |  |  | /// Used as a placeholder for absentee signers whose 'Pubkey` is required to construct
 | 
					
						
							|  |  |  | /// the transaction
 | 
					
						
							|  |  |  | #[derive(Clone, Debug, Default)]
 | 
					
						
							|  |  |  | pub struct NullSigner {
 | 
					
						
							|  |  |  |     pubkey: Pubkey,
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl NullSigner {
 | 
					
						
							|  |  |  |     pub fn new(pubkey: &Pubkey) -> Self {
 | 
					
						
							|  |  |  |         Self { pubkey: *pubkey }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl Signer for NullSigner {
 | 
					
						
							|  |  |  |     fn try_pubkey(&self) -> Result<Pubkey, SignerError> {
 | 
					
						
							|  |  |  |         Ok(self.pubkey)
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fn try_sign_message(&self, _message: &[u8]) -> Result<Signature, SignerError> {
 | 
					
						
							|  |  |  |         Ok(Signature::default())
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl<T> PartialEq<T> for NullSigner
 | 
					
						
							|  |  |  | where
 | 
					
						
							|  |  |  |     T: Signer,
 | 
					
						
							|  |  |  | {
 | 
					
						
							|  |  |  |     fn eq(&self, other: &T) -> bool {
 | 
					
						
							|  |  |  |         self.pubkey == other.pubkey()
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-10 17:01:03 -06:00
										 |  |  | pub fn read_keypair<R: Read>(reader: &mut R) -> Result<Keypair, Box<dyn error::Error>> {
 | 
					
						
							|  |  |  |     let bytes: Vec<u8> = serde_json::from_reader(reader)?;
 | 
					
						
							| 
									
										
										
										
											2020-02-12 14:15:12 -07:00
										 |  |  |     let dalek_keypair = ed25519_dalek::Keypair::from_bytes(&bytes)
 | 
					
						
							| 
									
										
										
										
											2019-05-09 11:03:14 -07:00
										 |  |  |         .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
 | 
					
						
							| 
									
										
										
										
											2020-02-12 14:15:12 -07:00
										 |  |  |     Ok(Keypair(dalek_keypair))
 | 
					
						
							| 
									
										
										
										
											2018-11-16 08:04:46 -08:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2018-12-12 13:13:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 10:29:23 -08:00
										 |  |  | pub fn read_keypair_file<F: AsRef<Path>>(path: F) -> Result<Keypair, Box<dyn error::Error>> {
 | 
					
						
							|  |  |  |     let mut file = File::open(path.as_ref())?;
 | 
					
						
							| 
									
										
										
										
											2019-10-10 17:01:03 -06:00
										 |  |  |     read_keypair(&mut file)
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | pub fn write_keypair<W: Write>(
 | 
					
						
							|  |  |  |     keypair: &Keypair,
 | 
					
						
							|  |  |  |     writer: &mut W,
 | 
					
						
							|  |  |  | ) -> Result<String, Box<dyn error::Error>> {
 | 
					
						
							| 
									
										
										
										
											2020-02-12 14:15:12 -07:00
										 |  |  |     let keypair_bytes = keypair.0.to_bytes();
 | 
					
						
							| 
									
										
										
										
											2019-04-18 14:37:20 -06:00
										 |  |  |     let serialized = serde_json::to_string(&keypair_bytes.to_vec())?;
 | 
					
						
							| 
									
										
										
										
											2019-10-10 17:01:03 -06:00
										 |  |  |     writer.write_all(&serialized.clone().into_bytes())?;
 | 
					
						
							|  |  |  |     Ok(serialized)
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2018-12-12 13:13:18 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 10:29:23 -08:00
										 |  |  | pub fn write_keypair_file<F: AsRef<Path>>(
 | 
					
						
							| 
									
										
										
										
											2019-10-10 17:01:03 -06:00
										 |  |  |     keypair: &Keypair,
 | 
					
						
							| 
									
										
										
										
											2020-12-16 10:29:23 -08:00
										 |  |  |     outfile: F,
 | 
					
						
							| 
									
										
										
										
											2019-10-10 17:01:03 -06:00
										 |  |  | ) -> Result<String, Box<dyn error::Error>> {
 | 
					
						
							| 
									
										
										
										
											2020-12-16 10:29:23 -08:00
										 |  |  |     let outfile = outfile.as_ref();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if let Some(outdir) = outfile.parent() {
 | 
					
						
							| 
									
										
										
										
											2019-10-10 17:01:03 -06:00
										 |  |  |         fs::create_dir_all(outdir)?;
 | 
					
						
							| 
									
										
										
										
											2018-12-12 13:13:18 -08:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:26:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     let mut f = {
 | 
					
						
							|  |  |  |         #[cfg(not(unix))]
 | 
					
						
							|  |  |  |         {
 | 
					
						
							|  |  |  |             OpenOptions::new()
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         #[cfg(unix)]
 | 
					
						
							|  |  |  |         {
 | 
					
						
							|  |  |  |             use std::os::unix::fs::OpenOptionsExt;
 | 
					
						
							|  |  |  |             OpenOptions::new().mode(0o600)
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     .write(true)
 | 
					
						
							| 
									
										
										
										
											2019-11-21 11:02:04 -07:00
										 |  |  |     .truncate(true)
 | 
					
						
							| 
									
										
										
										
											2019-11-20 13:46:16 -07:00
										 |  |  |     .create(true)
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:26:21 -07:00
										 |  |  |     .open(outfile)?;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-10 17:01:03 -06:00
										 |  |  |     write_keypair(keypair, &mut f)
 | 
					
						
							| 
									
										
										
										
											2018-12-12 13:13:18 -08:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2019-04-18 14:37:20 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-12 18:37:29 -07:00
										 |  |  | pub fn keypair_from_seed(seed: &[u8]) -> Result<Keypair, Box<dyn error::Error>> {
 | 
					
						
							|  |  |  |     if seed.len() < ed25519_dalek::SECRET_KEY_LENGTH {
 | 
					
						
							|  |  |  |         return Err("Seed is too short".into());
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     let secret = ed25519_dalek::SecretKey::from_bytes(&seed[..ed25519_dalek::SECRET_KEY_LENGTH])
 | 
					
						
							|  |  |  |         .map_err(|e| e.to_string())?;
 | 
					
						
							|  |  |  |     let public = ed25519_dalek::PublicKey::from(&secret);
 | 
					
						
							| 
									
										
										
										
											2020-02-12 14:15:12 -07:00
										 |  |  |     let dalek_keypair = ed25519_dalek::Keypair { secret, public };
 | 
					
						
							|  |  |  |     Ok(Keypair(dalek_keypair))
 | 
					
						
							| 
									
										
										
										
											2019-09-12 18:37:29 -07:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-22 10:20:40 -05:00
										 |  |  | pub fn keypair_from_seed_phrase_and_passphrase(
 | 
					
						
							|  |  |  |     seed_phrase: &str,
 | 
					
						
							|  |  |  |     passphrase: &str,
 | 
					
						
							|  |  |  | ) -> Result<Keypair, Box<dyn error::Error>> {
 | 
					
						
							|  |  |  |     const PBKDF2_ROUNDS: usize = 2048;
 | 
					
						
							|  |  |  |     const PBKDF2_BYTES: usize = 64;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let salt = format!("mnemonic{}", passphrase);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let mut seed = vec![0u8; PBKDF2_BYTES];
 | 
					
						
							|  |  |  |     pbkdf2::pbkdf2::<Hmac<sha2::Sha512>>(
 | 
					
						
							|  |  |  |         seed_phrase.as_bytes(),
 | 
					
						
							|  |  |  |         salt.as_bytes(),
 | 
					
						
							|  |  |  |         PBKDF2_ROUNDS,
 | 
					
						
							|  |  |  |         &mut seed,
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  |     keypair_from_seed(&seed[..])
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-18 14:37:20 -06:00
										 |  |  | #[cfg(test)]
 | 
					
						
							|  |  |  | mod tests {
 | 
					
						
							|  |  |  |     use super::*;
 | 
					
						
							| 
									
										
										
										
											2019-11-22 10:20:40 -05:00
										 |  |  |     use bip39::{Language, Mnemonic, MnemonicType, Seed};
 | 
					
						
							| 
									
										
										
										
											2019-04-18 14:37:20 -06:00
										 |  |  |     use std::mem;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fn tmp_file_path(name: &str) -> String {
 | 
					
						
							|  |  |  |         use std::env;
 | 
					
						
							| 
									
										
										
										
											2019-07-17 14:27:58 -07:00
										 |  |  |         let out_dir = env::var("FARF_DIR").unwrap_or_else(|_| "farf".to_string());
 | 
					
						
							| 
									
										
										
										
											2019-04-18 14:37:20 -06:00
										 |  |  |         let keypair = Keypair::new();
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-15 17:35:43 +01:00
										 |  |  |         format!("{}/tmp/{}-{}", out_dir, name, keypair.pubkey())
 | 
					
						
							| 
									
										
										
										
											2019-04-18 14:37:20 -06:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[test]
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:26:21 -07:00
										 |  |  |     fn test_write_keypair_file() {
 | 
					
						
							| 
									
										
										
										
											2019-11-20 13:46:16 -07:00
										 |  |  |         let outfile = tmp_file_path("test_write_keypair_file.json");
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:26:21 -07:00
										 |  |  |         let serialized_keypair = write_keypair_file(&Keypair::new(), &outfile).unwrap();
 | 
					
						
							| 
									
										
										
										
											2019-04-18 14:37:20 -06:00
										 |  |  |         let keypair_vec: Vec<u8> = serde_json::from_str(&serialized_keypair).unwrap();
 | 
					
						
							|  |  |  |         assert!(Path::new(&outfile).exists());
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             keypair_vec,
 | 
					
						
							| 
									
										
										
										
											2020-02-12 14:15:12 -07:00
										 |  |  |             read_keypair_file(&outfile).unwrap().0.to_bytes().to_vec()
 | 
					
						
							| 
									
										
										
										
											2019-04-18 14:37:20 -06:00
										 |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2019-11-19 18:26:21 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         #[cfg(unix)]
 | 
					
						
							|  |  |  |         {
 | 
					
						
							|  |  |  |             use std::os::unix::fs::PermissionsExt;
 | 
					
						
							|  |  |  |             assert_eq!(
 | 
					
						
							|  |  |  |                 File::open(&outfile)
 | 
					
						
							|  |  |  |                     .expect("open")
 | 
					
						
							|  |  |  |                     .metadata()
 | 
					
						
							|  |  |  |                     .expect("metadata")
 | 
					
						
							|  |  |  |                     .permissions()
 | 
					
						
							|  |  |  |                     .mode()
 | 
					
						
							|  |  |  |                     & 0o777,
 | 
					
						
							|  |  |  |                 0o600
 | 
					
						
							|  |  |  |             );
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-18 14:37:20 -06:00
										 |  |  |         assert_eq!(
 | 
					
						
							| 
									
										
										
										
											2019-10-10 17:01:03 -06:00
										 |  |  |             read_keypair_file(&outfile).unwrap().pubkey().as_ref().len(),
 | 
					
						
							| 
									
										
										
										
											2019-04-18 14:37:20 -06:00
										 |  |  |             mem::size_of::<Pubkey>()
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |         fs::remove_file(&outfile).unwrap();
 | 
					
						
							|  |  |  |         assert!(!Path::new(&outfile).exists());
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2019-05-16 14:54:31 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-20 13:46:16 -07:00
										 |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_write_keypair_file_overwrite_ok() {
 | 
					
						
							|  |  |  |         let outfile = tmp_file_path("test_write_keypair_file_overwrite_ok.json");
 | 
					
						
							| 
									
										
										
										
											2019-11-21 11:02:04 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         write_keypair_file(&Keypair::new(), &outfile).unwrap();
 | 
					
						
							|  |  |  |         write_keypair_file(&Keypair::new(), &outfile).unwrap();
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_write_keypair_file_truncate() {
 | 
					
						
							|  |  |  |         let outfile = tmp_file_path("test_write_keypair_file_truncate.json");
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-20 13:46:16 -07:00
										 |  |  |         write_keypair_file(&Keypair::new(), &outfile).unwrap();
 | 
					
						
							| 
									
										
										
										
											2019-11-21 11:02:04 -07:00
										 |  |  |         read_keypair_file(&outfile).unwrap();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Ensure outfile is truncated
 | 
					
						
							|  |  |  |         {
 | 
					
						
							|  |  |  |             let mut f = File::create(&outfile).unwrap();
 | 
					
						
							|  |  |  |             f.write_all(String::from_utf8([b'a'; 2048].to_vec()).unwrap().as_bytes())
 | 
					
						
							|  |  |  |                 .unwrap();
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2019-11-20 13:46:16 -07:00
										 |  |  |         write_keypair_file(&Keypair::new(), &outfile).unwrap();
 | 
					
						
							| 
									
										
										
										
											2019-11-21 11:02:04 -07:00
										 |  |  |         read_keypair_file(&outfile).unwrap();
 | 
					
						
							| 
									
										
										
										
											2019-11-20 13:46:16 -07:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-12 18:37:29 -07:00
										 |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_keypair_from_seed() {
 | 
					
						
							|  |  |  |         let good_seed = vec![0; 32];
 | 
					
						
							|  |  |  |         assert!(keypair_from_seed(&good_seed).is_ok());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let too_short_seed = vec![0; 31];
 | 
					
						
							|  |  |  |         assert!(keypair_from_seed(&too_short_seed).is_err());
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-16 14:54:31 -07:00
										 |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_signature_fromstr() {
 | 
					
						
							|  |  |  |         let signature = Keypair::new().sign_message(&[0u8]);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let mut signature_base58_str = bs58::encode(signature).into_string();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         assert_eq!(signature_base58_str.parse::<Signature>(), Ok(signature));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         signature_base58_str.push_str(&bs58::encode(signature.0).into_string());
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             signature_base58_str.parse::<Signature>(),
 | 
					
						
							|  |  |  |             Err(ParseSignatureError::WrongSize)
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         signature_base58_str.truncate(signature_base58_str.len() / 2);
 | 
					
						
							|  |  |  |         assert_eq!(signature_base58_str.parse::<Signature>(), Ok(signature));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         signature_base58_str.truncate(signature_base58_str.len() / 2);
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             signature_base58_str.parse::<Signature>(),
 | 
					
						
							|  |  |  |             Err(ParseSignatureError::WrongSize)
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let mut signature_base58_str = bs58::encode(signature.0).into_string();
 | 
					
						
							|  |  |  |         assert_eq!(signature_base58_str.parse::<Signature>(), Ok(signature));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // throw some non-base58 stuff in there
 | 
					
						
							|  |  |  |         signature_base58_str.replace_range(..1, "I");
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             signature_base58_str.parse::<Signature>(),
 | 
					
						
							|  |  |  |             Err(ParseSignatureError::Invalid)
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2019-11-22 10:20:40 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_keypair_from_seed_phrase_and_passphrase() {
 | 
					
						
							|  |  |  |         let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English);
 | 
					
						
							|  |  |  |         let passphrase = "42";
 | 
					
						
							|  |  |  |         let seed = Seed::new(&mnemonic, passphrase);
 | 
					
						
							|  |  |  |         let expected_keypair = keypair_from_seed(seed.as_bytes()).unwrap();
 | 
					
						
							|  |  |  |         let keypair =
 | 
					
						
							|  |  |  |             keypair_from_seed_phrase_and_passphrase(mnemonic.phrase(), passphrase).unwrap();
 | 
					
						
							|  |  |  |         assert_eq!(keypair.pubkey(), expected_keypair.pubkey());
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-02-13 17:53:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_keypair() {
 | 
					
						
							|  |  |  |         let keypair = keypair_from_seed(&[0u8; 32]).unwrap();
 | 
					
						
							|  |  |  |         let pubkey = keypair.pubkey();
 | 
					
						
							|  |  |  |         let data = [1u8];
 | 
					
						
							|  |  |  |         let sig = keypair.sign_message(&data);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 14:28:55 -07:00
										 |  |  |         // Signer
 | 
					
						
							| 
									
										
										
										
											2020-02-13 17:53:09 -07:00
										 |  |  |         assert_eq!(keypair.try_pubkey().unwrap(), pubkey);
 | 
					
						
							|  |  |  |         assert_eq!(keypair.pubkey(), pubkey);
 | 
					
						
							|  |  |  |         assert_eq!(keypair.try_sign_message(&data).unwrap(), sig);
 | 
					
						
							|  |  |  |         assert_eq!(keypair.sign_message(&data), sig);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // PartialEq
 | 
					
						
							|  |  |  |         let keypair2 = keypair_from_seed(&[0u8; 32]).unwrap();
 | 
					
						
							|  |  |  |         assert_eq!(keypair, keypair2);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_presigner() {
 | 
					
						
							|  |  |  |         let keypair = keypair_from_seed(&[0u8; 32]).unwrap();
 | 
					
						
							|  |  |  |         let pubkey = keypair.pubkey();
 | 
					
						
							|  |  |  |         let data = [1u8];
 | 
					
						
							|  |  |  |         let sig = keypair.sign_message(&data);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 14:28:55 -07:00
										 |  |  |         // Signer
 | 
					
						
							| 
									
										
										
										
											2020-02-13 17:53:09 -07:00
										 |  |  |         let presigner = Presigner::new(&pubkey, &sig);
 | 
					
						
							|  |  |  |         assert_eq!(presigner.try_pubkey().unwrap(), pubkey);
 | 
					
						
							|  |  |  |         assert_eq!(presigner.pubkey(), pubkey);
 | 
					
						
							|  |  |  |         assert_eq!(presigner.try_sign_message(&data).unwrap(), sig);
 | 
					
						
							|  |  |  |         assert_eq!(presigner.sign_message(&data), sig);
 | 
					
						
							|  |  |  |         let bad_data = [2u8];
 | 
					
						
							|  |  |  |         assert!(presigner.try_sign_message(&bad_data).is_err());
 | 
					
						
							|  |  |  |         assert_eq!(presigner.sign_message(&bad_data), Signature::default());
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // PartialEq
 | 
					
						
							|  |  |  |         assert_eq!(presigner, keypair);
 | 
					
						
							|  |  |  |         assert_eq!(keypair, presigner);
 | 
					
						
							|  |  |  |         let presigner2 = Presigner::new(&pubkey, &sig);
 | 
					
						
							|  |  |  |         assert_eq!(presigner, presigner2);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-05-18 19:31:45 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     fn pubkeys(signers: &[&dyn Signer]) -> Vec<Pubkey> {
 | 
					
						
							| 
									
										
										
										
											2020-05-29 08:26:06 +01:00
										 |  |  |         signers.iter().map(|x| x.pubkey()).collect()
 | 
					
						
							| 
									
										
										
										
											2020-05-18 19:31:45 -06:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_unique_signers() {
 | 
					
						
							|  |  |  |         let alice = Keypair::new();
 | 
					
						
							|  |  |  |         let bob = Keypair::new();
 | 
					
						
							|  |  |  |         assert_eq!(
 | 
					
						
							|  |  |  |             pubkeys(&unique_signers(vec![&alice, &bob, &alice])),
 | 
					
						
							|  |  |  |             pubkeys(&[&alice, &bob])
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2020-07-30 18:11:16 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  |     #[test]
 | 
					
						
							|  |  |  |     fn test_off_curve_pubkey_verify_fails() {
 | 
					
						
							|  |  |  |         // Golden point off the ed25519 curve
 | 
					
						
							|  |  |  |         let off_curve_bytes = bs58::decode("9z5nJyQar1FUxVJxpBXzon6kHehbomeYiDaLi9WAMhCq")
 | 
					
						
							|  |  |  |             .into_vec()
 | 
					
						
							|  |  |  |             .unwrap();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Confirm golden's off-curvedness
 | 
					
						
							|  |  |  |         let mut off_curve_bits = [0u8; 32];
 | 
					
						
							|  |  |  |         off_curve_bits.copy_from_slice(&off_curve_bytes);
 | 
					
						
							|  |  |  |         let off_curve_point = curve25519_dalek::edwards::CompressedEdwardsY(off_curve_bits);
 | 
					
						
							|  |  |  |         assert_eq!(off_curve_point.decompress(), None);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let pubkey = Pubkey::new(&off_curve_bytes);
 | 
					
						
							|  |  |  |         let signature = Signature::default();
 | 
					
						
							|  |  |  |         // Unfortunately, ed25519-dalek doesn't surface the internal error types that we'd ideally
 | 
					
						
							|  |  |  |         // `source()` out of the `SignatureError` returned by `verify_strict()`.  So the best we
 | 
					
						
							|  |  |  |         // can do is `is_err()` here.
 | 
					
						
							|  |  |  |         assert!(signature.verify_verbose(pubkey.as_ref(), &[0u8]).is_err());
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2019-04-18 14:37:20 -06:00
										 |  |  | }
 |