fi_verifiable_data/
proof.rs1use chrono::Utc;
2use fi_digital_signatures::{
3 algorithms::Algorithm, signer::get_signing_key, verifier::get_verifying_key,
4};
5use serde::{Deserialize, Serialize};
6#[cfg(feature = "wasm")]
7use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
8
9use crate::{document::VerificationDocument, error::FiError};
10
11pub trait Proof {
12 fn sign(&mut self, doc: &mut VerificationDocument, content: String) -> Result<(), FiError>;
13 fn verify(&self, doc: &mut VerificationDocument, content: String) -> Result<bool, FiError>;
14}
15
16#[derive(Serialize, Deserialize, Clone)]
17pub struct FiProof {
18 #[serde(rename = "type")]
19 _type: String,
20 created: String,
21 algorithm: String,
22 #[serde(rename = "proofPurpose")]
23 proof_purpose: String,
24 jws: Option<String>,
25}
26
27impl Proof for FiProof {
28 fn sign(&mut self, doc: &mut VerificationDocument, content: String) -> Result<(), FiError> {
29 let key_bytes = match doc.get_private_key_mut() {
30 None => {
31 return Err(FiError::new(
32 "No private key was found in the VerificationDocument",
33 ))
34 }
35 Some(val) => val,
36 };
37
38 let alg = match Algorithm::from_str(self.algorithm.as_str()) {
39 Some(val) => val,
40 None => return Err(FiError::new("Algorithm cannot be identified.")),
41 };
42
43 let signing_key = match get_signing_key(alg, key_bytes.as_mut_slice()) {
44 Ok(val) => val,
45 Err(error) => {
46 eprintln!("{}", error);
47 return Err(FiError::new("Failed to get signing key"));
48 }
49 };
50
51 match signing_key.sign(content, alg) {
52 Ok(val) => {
53 self.jws = Some(val);
54 Ok(())
55 }
56 Err(error) => {
57 eprintln!("{}", error);
58 return Err(FiError::new("Failed to sign content"));
59 }
60 }
61 }
62
63 fn verify(&self, doc: &mut VerificationDocument, content: String) -> Result<bool, FiError> {
64 let key_bytes = match doc.get_public_key_mut() {
65 None => {
66 return Err(FiError::new(
67 "No publuc key was found in the VerificationDocument",
68 ))
69 }
70 Some(val) => val,
71 };
72
73 let alg = match Algorithm::from_str(self.algorithm.as_str()) {
74 None => return Err(FiError::new("Provided algorithm is no supported")),
75 Some(val) => val,
76 };
77
78 let verifying_key = match get_verifying_key(alg, key_bytes.as_mut_slice()) {
79 Ok(val) => val,
80 Err(error) => {
81 eprintln!("{}", error);
82 return Err(FiError::new("Failed to get signing key"));
83 }
84 };
85
86 match self.jws.clone() {
87 Some(val) => match verifying_key.verify(content, val, alg) {
88 Ok(val) => Ok(val),
89 Err(error) => {
90 eprintln!("{}", error);
91 return Err(FiError::new("Failed to verify content"));
92 }
93 },
94 None => {
95 return Err(FiError::new("Failed to verify content"));
96 }
97 }
98 }
99}
100
101impl FiProof {
102 pub fn new(alg: Algorithm, purpose: String) -> Self {
103 let datetime = Utc::now().to_rfc3339();
104 return FiProof {
105 _type: String::from("FiProof"),
106 algorithm: String::from(alg.to_str()),
107 proof_purpose: purpose,
108 created: datetime.to_string(),
109 jws: None,
110 };
111 }
112}
113
114#[cfg(feature = "wasm")]
115#[wasm_bindgen]
116pub enum ProofType {
117 FiProof,
118}
119
120#[cfg(feature = "wasm")]
121impl ProofType {
122 pub fn sign(
123 &self,
124 alg: Algorithm,
125 purpose: String,
126 doc: &mut VerificationDocument,
127 content: String,
128 ) -> Result<JsValue, FiError> {
129 match self {
130 ProofType::FiProof => {
131 let mut proof = FiProof::new(alg, purpose);
132 _ = proof.sign(doc, content);
133
134 match serde_wasm_bindgen::to_value(&proof) {
135 Ok(val) => return Ok(val),
136 Err(err) => return Err(FiError::new(err.to_string().as_str())),
137 }
138 }
139 }
140 }
141
142 pub fn verify(
143 &self,
144 doc: &mut VerificationDocument,
145 content: String,
146 proof: JsValue,
147 ) -> Result<bool, FiError> {
148 match self {
149 ProofType::FiProof => {
150 let fi_proof: FiProof = match serde_wasm_bindgen::from_value(proof) {
151 Err(error) => return Err(FiError::new(error.to_string().as_str())),
152 Ok(val) => val,
153 };
154
155 fi_proof.verify(doc, content)
156 }
157 }
158 }
159}