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 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 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 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}