cyfs_lib/crypto/
requestor.rs

1use super::output_request::*;
2use super::processor::*;
3use super::request::*;
4use crate::non::NONObjectInfo;
5use crate::*;
6use cyfs_base::*;
7
8use http_types::{Method, Request, Response, Url};
9use std::sync::Arc;
10
11#[derive(Clone)]
12pub struct CryptoRequestor {
13    dec_id: Option<SharedObjectStackDecID>,
14    requestor: HttpRequestorRef,
15    service_url: Url,
16}
17
18impl CryptoRequestor {
19    pub fn new(dec_id: Option<SharedObjectStackDecID>, requestor: HttpRequestorRef) -> Self {
20        let addr = requestor.remote_addr();
21
22        let url = format!("http://{}/crypto/", addr);
23        let url = Url::parse(&url).unwrap();
24
25        Self {
26            dec_id,
27            requestor,
28            service_url: url,
29        }
30    }
31
32    pub fn into_processor(self) -> CryptoOutputProcessorRef {
33        Arc::new(Box::new(self))
34    }
35
36    pub fn clone_processor(&self) -> CryptoOutputProcessorRef {
37        self.clone().into_processor()
38    }
39
40    fn encode_common_headers(&self, com_req: &CryptoOutputRequestCommon, http_req: &mut Request) {
41        if let Some(dec_id) = &com_req.dec_id {
42            http_req.insert_header(cyfs_base::CYFS_DEC_ID, dec_id.to_string());
43        } else if let Some(dec_id) = &self.dec_id {
44            if let Some(dec_id) = dec_id.get() {
45                http_req.insert_header(cyfs_base::CYFS_DEC_ID, dec_id.to_string());
46            }
47        }
48
49        RequestorHelper::encode_opt_header_with_encoding(
50            http_req,
51            cyfs_base::CYFS_REQ_PATH,
52            com_req.req_path.as_deref(),
53        );
54
55        if let Some(target) = &com_req.target {
56            http_req.insert_header(cyfs_base::CYFS_TARGET, target.to_string());
57        }
58
59        http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string());
60    }
61
62    fn encode_verify_object_request(&self, req: &CryptoVerifyObjectOutputRequest) -> Request {
63        let url = self.service_url.join("verify").unwrap();
64
65        let mut http_req = Request::new(Method::Post, url);
66        self.encode_common_headers(&req.common, &mut http_req);
67
68        http_req.insert_header(cyfs_base::CYFS_OBJECT_ID, req.object.object_id.to_string());
69        http_req.insert_header(cyfs_base::CYFS_SIGN_TYPE, req.sign_type.to_string());
70
71        let verify_type = req.sign_object.as_str();
72        match &req.sign_object {
73            VerifyObjectType::Owner | VerifyObjectType::Own => {}
74            VerifyObjectType::Object(sign_object) => {
75                http_req.insert_header(
76                    cyfs_base::CYFS_SIGN_OBJ_ID,
77                    sign_object.object_id.to_string(),
78                );
79                if let Some(obj) = &sign_object.object_raw {
80                    http_req.insert_header(cyfs_base::CYFS_SIGN_OBJ, hex::encode(obj));
81                }
82            }
83            VerifyObjectType::Sign(signs) => {
84                http_req.insert_header(cyfs_base::CYFS_VERIFY_SIGNS, signs.encode_string());
85            }
86        }
87
88        http_req.insert_header(cyfs_base::CYFS_VERIFY_TYPE, verify_type);
89
90        http_req
91    }
92
93    async fn decode_verify_object_response(
94        object_id: &ObjectId,
95        mut resp: Response,
96    ) -> BuckyResult<CryptoVerifyObjectOutputResponse> {
97        let body = resp.body_string().await.map_err(|e| {
98            let msg = format!(
99                "read verify object response from crypto failed, read body string error! obj={}, {}",
100                object_id, e
101            );
102            error!("{}", msg);
103
104            BuckyError::new(BuckyErrorCode::IoError, msg)
105        })?;
106
107        info!("verify resp body: {}", body);
108
109        let resp = CryptoVerifyObjectResponse::decode_string(&body)?;
110
111        info!("verify object response: obj={}, resp={:?}", object_id, resp);
112
113        Ok(resp)
114    }
115
116    // 校验一个对象是否有指定object的签名
117    pub async fn verify_object(
118        &self,
119        req: CryptoVerifyObjectRequest,
120    ) -> BuckyResult<CryptoVerifyObjectResponse> {
121        let mut http_req = self.encode_verify_object_request(&req);
122        http_req.set_body(req.object.object_raw);
123
124        let mut resp = self.requestor.request(http_req).await?;
125
126        if resp.status().is_success() {
127            let resp = Self::decode_verify_object_response(&req.object.object_id, resp).await?;
128            Ok(resp)
129        } else {
130            let e = RequestorHelper::error_from_resp(&mut resp).await;
131            Err(e)
132        }
133    }
134
135    fn encode_sign_object_request(&self, req: &CryptoSignObjectRequest) -> Request {
136        let url = self.service_url.join("sign").unwrap();
137
138        let mut http_req = Request::new(Method::Post, url);
139        self.encode_common_headers(&req.common, &mut http_req);
140        http_req.insert_header(cyfs_base::CYFS_OBJECT_ID, req.object.object_id.to_string());
141        http_req.insert_header(cyfs_base::CYFS_CRYPTO_FLAGS, req.flags.to_string());
142
143        http_req
144    }
145
146    async fn decode_sign_object_response(
147        object_id: &ObjectId,
148        mut resp: Response,
149    ) -> BuckyResult<CryptoSignObjectOutputResponse> {
150        let sign_result: SignObjectResult =
151            RequestorHelper::decode_header(&resp, cyfs_base::CYFS_SIGN_RET)?;
152
153        info!(
154            "sign object from crypto success: obj={}, ret={}",
155            object_id,
156            sign_result.to_string()
157        );
158
159        let ret = match sign_result {
160            SignObjectResult::Signed => {
161                let buf = resp.body_bytes().await.map_err(|e| {
162                    let msg = format!(
163                        "get object from sign object resp failed, read body bytes error! obj={} {}",
164                        object_id, e
165                    );
166                    error!("{}", msg);
167
168                    BuckyError::from(msg)
169                })?;
170
171                let object = NONObjectInfo::new_from_object_raw(buf)?;
172
173                CryptoSignObjectResponse {
174                    result: sign_result,
175                    object: Some(object),
176                }
177            }
178            SignObjectResult::Pending => CryptoSignObjectResponse {
179                result: sign_result,
180                object: None,
181            },
182        };
183
184        Ok(ret)
185    }
186
187    pub async fn sign_object(
188        &self,
189        req: CryptoSignObjectRequest,
190    ) -> BuckyResult<CryptoSignObjectResponse> {
191        let mut http_req = self.encode_sign_object_request(&req);
192        http_req.set_body(req.object.object_raw);
193
194        let mut resp = self.requestor.request(http_req).await?;
195
196        if resp.status().is_success() {
197            let resp = Self::decode_sign_object_response(&req.object.object_id, resp).await?;
198            Ok(resp)
199        } else {
200            let e = RequestorHelper::error_from_resp(&mut resp).await;
201            Err(e)
202        }
203    }
204
205    // encrypt
206    fn encode_encrypt_data_request(&self, req: &CryptoEncryptDataOutputRequest) -> Request {
207        let url = self.service_url.join("encrypt").unwrap();
208
209        let mut http_req = Request::new(Method::Post, url);
210        self.encode_common_headers(&req.common, &mut http_req);
211        http_req.insert_header(cyfs_base::CYFS_ENCRYPT_TYPE, req.encrypt_type.to_string());
212        http_req.insert_header(cyfs_base::CYFS_CRYPTO_FLAGS, req.flags.to_string());
213
214        http_req
215    }
216
217    async fn decode_encrypt_data_response(
218        mut resp: Response,
219    ) -> BuckyResult<CryptoEncryptDataOutputResponse> {
220        let aes_key: Option<AesKey> =
221            RequestorHelper::decode_optional_header(&resp, cyfs_base::CYFS_AES_KEY)?;
222
223        let result = resp.body_bytes().await.map_err(|e| {
224            let msg = format!(
225                "get encrypt data from resp failed, read body bytes error! {}",
226                e
227            );
228            error!("{}", msg);
229
230            BuckyError::from(msg)
231        })?;
232
233        let resp = CryptoEncryptDataOutputResponse { aes_key, result };
234
235        Ok(resp)
236    }
237
238    pub async fn encrypt_data(
239        &self,
240        req: CryptoEncryptDataOutputRequest,
241    ) -> BuckyResult<CryptoEncryptDataOutputResponse> {
242        let mut http_req = self.encode_encrypt_data_request(&req);
243        let data_len = match &req.data {
244            Some(data) => data.len(),
245            None => 0,
246        };
247
248        if let Some(data) = req.data {
249            http_req.set_body(data);
250        }
251
252        let mut resp = self.requestor.request(http_req).await?;
253
254        if resp.status().is_success() {
255            let resp = Self::decode_encrypt_data_response(resp).await?;
256
257            info!(
258                "encrypt data success: data={}, type={}, ret={}",
259                data_len,
260                req.encrypt_type.to_string(),
261                resp.result.len(),
262            );
263
264            Ok(resp)
265        } else {
266            let e = RequestorHelper::error_from_resp(&mut resp).await;
267            error!(
268                "encrypt data failed: data={}, type={}, {}",
269                data_len,
270                req.encrypt_type.to_string(),
271                e,
272            );
273            Err(e)
274        }
275    }
276
277    // decrypt
278    fn encode_decrypt_data_request(&self, req: &CryptoDecryptDataOutputRequest) -> Request {
279        let url = self.service_url.join("decrypt").unwrap();
280
281        let mut http_req = Request::new(Method::Post, url);
282        self.encode_common_headers(&req.common, &mut http_req);
283        http_req.insert_header(cyfs_base::CYFS_DECRYPT_TYPE, req.decrypt_type.to_string());
284        http_req.insert_header(cyfs_base::CYFS_CRYPTO_FLAGS, req.flags.to_string());
285
286        http_req
287    }
288
289    async fn decode_decrypt_data_response(
290        mut resp: Response,
291    ) -> BuckyResult<CryptoDecryptDataOutputResponse> {
292        let result: DecryptDataResult =
293            RequestorHelper::decode_header(&resp, cyfs_base::CYFS_DECRYPT_RET)?;
294
295        let data = resp.body_bytes().await.map_err(|e| {
296            let msg = format!(
297                "get decrypt data from resp failed, read body bytes error! {}",
298                e
299            );
300            error!("{}", msg);
301
302            BuckyError::from(msg)
303        })?;
304
305        let resp = CryptoDecryptDataOutputResponse { result, data };
306
307        Ok(resp)
308    }
309
310    pub async fn decrypt_data(
311        &self,
312        req: CryptoDecryptDataOutputRequest,
313    ) -> BuckyResult<CryptoDecryptDataOutputResponse> {
314        let mut http_req = self.encode_decrypt_data_request(&req);
315        let data_len = req.data.len();
316        http_req.set_body(req.data);
317
318        let mut resp = self.requestor.request(http_req).await?;
319
320        if resp.status().is_success() {
321            let resp = Self::decode_decrypt_data_response(resp).await?;
322
323            info!(
324                "decrypt data crypto success: data={}, type={}, {}",
325                data_len,
326                req.decrypt_type.to_string(),
327                resp,
328            );
329
330            Ok(resp)
331        } else {
332            let e = RequestorHelper::error_from_resp(&mut resp).await;
333            error!(
334                "decrypt data crypto failed: data={}, type={}, {}",
335                data_len,
336                req.decrypt_type.to_string(),
337                e,
338            );
339
340            Err(e)
341        }
342    }
343}
344
345#[async_trait::async_trait]
346impl CryptoOutputProcessor for CryptoRequestor {
347    async fn verify_object(
348        &self,
349        req: CryptoVerifyObjectOutputRequest,
350    ) -> BuckyResult<CryptoVerifyObjectOutputResponse> {
351        Self::verify_object(&self, req).await
352    }
353
354    async fn sign_object(
355        &self,
356        req: CryptoSignObjectOutputRequest,
357    ) -> BuckyResult<CryptoSignObjectOutputResponse> {
358        Self::sign_object(&self, req).await
359    }
360
361    async fn encrypt_data(
362        &self,
363        req: CryptoEncryptDataOutputRequest,
364    ) -> BuckyResult<CryptoEncryptDataOutputResponse> {
365        Self::encrypt_data(&self, req).await
366    }
367
368    async fn decrypt_data(
369        &self,
370        req: CryptoDecryptDataOutputRequest,
371    ) -> BuckyResult<CryptoDecryptDataOutputResponse> {
372        Self::decrypt_data(&self, req).await
373    }
374}