1use crate::revoke::RevokeError::IncorrectSignature;
18use fluence_keypair::key_pair::KeyPair;
19use fluence_keypair::public_key::PublicKey;
20use fluence_keypair::signature::Signature;
21use serde::{Deserialize, Serialize};
22use sha2::Digest;
23use std::time::Duration;
24use thiserror::Error as ThisError;
25
26#[derive(ThisError, Debug)]
27pub enum RevokeError {
28 #[error("Signature is incorrect: {0}")]
29 IncorrectSignature(
30 #[from]
31 #[source]
32 fluence_keypair::error::VerificationError,
33 ),
34}
35
36#[derive(Clone, Debug, Serialize, Deserialize)]
39pub struct Revocation {
40 pub pk: PublicKey,
42 pub revoked_at: Duration,
44 pub revoked_by: PublicKey,
46 pub signature: Signature,
48}
49
50impl Revocation {
51 pub fn new(
52 revoked_by: PublicKey,
53 pk: PublicKey,
54 revoked_at: Duration,
55 signature: Signature,
56 ) -> Self {
57 Self {
58 pk,
59 revoked_at,
60 revoked_by,
61 signature,
62 }
63 }
64
65 pub fn create(revoker: &KeyPair, to_revoke: PublicKey, revoked_at: Duration) -> Self {
67 let msg = Revocation::signature_bytes(&to_revoke, revoked_at);
68 let signature = revoker.sign(&msg).unwrap();
69
70 Revocation::new(revoker.public(), to_revoke, revoked_at, signature)
71 }
72
73 pub fn signature_bytes(pk: &PublicKey, revoked_at: Duration) -> Vec<u8> {
74 let mut metadata = Vec::new();
75 let pk_bytes = &pk.encode();
76 metadata.push(pk_bytes.len() as u8);
77 metadata.extend(pk_bytes);
78 metadata.extend_from_slice(&revoked_at.as_secs().to_le_bytes());
79
80 sha2::Sha256::digest(&metadata).to_vec()
81 }
82
83 pub fn verify(revoke: &Revocation) -> Result<(), RevokeError> {
85 let msg = Revocation::signature_bytes(&revoke.pk, revoke.revoked_at);
86
87 revoke
88 .revoked_by
89 .verify(msg.as_slice(), &revoke.signature)
90 .map_err(IncorrectSignature)
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_gen_revoke_and_validate_ed25519() {
100 let revoker = KeyPair::generate_ed25519();
101 let to_revoke = KeyPair::generate_ed25519();
102
103 let duration = Duration::new(100, 0);
104
105 let revoke = Revocation::create(&revoker, to_revoke.public(), duration);
106
107 assert_eq!(Revocation::verify(&revoke).is_ok(), true);
108 }
109
110 #[test]
111 fn test_validate_corrupted_revoke_ed25519() {
112 let revoker = KeyPair::generate_ed25519();
113 let to_revoke = KeyPair::generate_ed25519();
114
115 let duration = Duration::new(100, 0);
116
117 let revoke = Revocation::create(&revoker, to_revoke.public(), duration);
118
119 let duration2 = Duration::new(95, 0);
120 let corrupted_revoke = Revocation::new(
121 revoker.public(),
122 to_revoke.public(),
123 duration2,
124 revoke.signature,
125 );
126
127 assert_eq!(Revocation::verify(&corrupted_revoke).is_ok(), false);
128 }
129}