dup_crypto/keys/
text_signable.rs1use super::*;
19
20pub trait TextSignable: Debug + Clone {
22 fn as_signable_text(&self) -> String;
24 fn issuer_pubkey(&self) -> PubKeyEnum;
26 fn signature(&self) -> Option<Sig>;
28 fn set_signature(&mut self, _signature: Sig);
30 fn sign(&mut self, signator: &SignatorEnum) -> Result<String, SignError> {
32 if self.signature().is_some() {
33 return Err(SignError::AlreadySign);
34 }
35 match self.issuer_pubkey() {
36 PubKeyEnum::Ed25519(_) => match signator {
37 SignatorEnum::Ed25519(ed25519_signator) => {
38 let text = self.as_signable_text();
39 let sig = ed25519_signator.sign(&text.as_bytes());
40 self.set_signature(Sig::Ed25519(sig));
41 let str_sig = sig.to_base64();
42 Ok(format!("{}{}", text, str_sig))
43 }
44 _ => Err(SignError::WrongAlgo),
45 },
46 }
47 }
48 fn verify(&self) -> Result<(), SigError> {
50 if let Some(signature) = self.signature() {
51 match self.issuer_pubkey() {
52 PubKeyEnum::Ed25519(pubkey) => match signature {
53 Sig::Ed25519(sig) => pubkey.verify(&self.as_signable_text().as_bytes(), &sig),
54 _ => Err(SigError::NotSameAlgo),
55 },
56 }
57 } else {
58 Err(SigError::NotSig)
59 }
60 }
61}
62
63#[cfg(test)]
64mod tests {
65
66 use super::*;
67
68 #[derive(Debug, Clone)]
69 struct TextSignableTestImpl {
70 issuer: PubKeyEnum,
71 text: String,
72 sig: Option<Sig>,
73 }
74
75 impl TextSignable for TextSignableTestImpl {
76 fn as_signable_text(&self) -> String {
77 format!("{}:{}", self.issuer, self.text)
78 }
79 fn issuer_pubkey(&self) -> PubKeyEnum {
80 self.issuer
81 }
82 fn signature(&self) -> Option<Sig> {
83 self.sig
84 }
85 fn set_signature(&mut self, new_signature: Sig) {
86 self.sig = Some(new_signature);
87 }
88 }
89
90 #[test]
91 fn test_text_signable() {
92 let key_pair = super::super::tests::valid_key_pair_1();
93
94 let signator = key_pair.generate_signator();
95
96 let mut text_signable = TextSignableTestImpl {
97 issuer: key_pair.public_key(),
98 text: "toto".to_owned(),
99 sig: None,
100 };
101
102 assert_eq!(Err(SigError::NotSig), text_signable.verify());
103 assert_eq!(
104 Err(SignError::WrongAlgo),
105 text_signable.sign(&SignatorEnum::Schnorr())
106 );
107 text_signable.issuer = key_pair.public_key();
108 assert_eq!(
109 Ok("VYgskcKKh525MzFRzpCiT5KXCQrnFLTnzMLffbvm9uw:toto+IC1fFkkYo5ox2loc1IMLCtrir1i6oyljfshNXIyXVcz6sJMFqn+6o8Zip4XdTzoBEORkbcnEnqQEr4TgaHpCw==".to_owned()),
110 text_signable.sign(&signator)
111 );
112 assert_eq!(Err(SignError::AlreadySign), text_signable.sign(&signator));
113 assert_eq!(Ok(()), text_signable.verify());
114 text_signable.sig.replace(Sig::Schnorr());
115 assert_eq!(Err(SigError::NotSameAlgo), text_signable.verify());
116 }
117}