cloud_util/
crypto.rs

1//
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14use crate::common::{ADDR_BYTES_LEN, HASH_BYTES_LEN};
15use cita_cloud_proto::blockchain::BlockHeader;
16use cita_cloud_proto::client::{CryptoClientTrait, InterceptedSvc};
17use cita_cloud_proto::crypto::crypto_service_client::CryptoServiceClient;
18use cita_cloud_proto::crypto::{HashDataRequest, RecoverSignatureRequest, SignMessageRequest};
19use cita_cloud_proto::retry::RetryClient;
20use cita_cloud_proto::status_code::StatusCodeEnum;
21use prost::Message;
22
23pub async fn hash_data(
24    client: RetryClient<CryptoServiceClient<InterceptedSvc>>,
25    data: &[u8],
26) -> Result<Vec<u8>, StatusCodeEnum> {
27    let data = data.to_vec();
28    match client.hash_data(HashDataRequest { data }).await {
29        Ok(hash_respond) => {
30            let status_code = StatusCodeEnum::from(
31                hash_respond
32                    .status
33                    .ok_or(StatusCodeEnum::NoneStatusCode)?
34                    .code,
35            );
36
37            if status_code != StatusCodeEnum::Success {
38                Err(status_code)
39            } else {
40                Ok(hash_respond
41                    .hash
42                    .ok_or(StatusCodeEnum::NoneHashResult)?
43                    .hash)
44            }
45        }
46        Err(status) => {
47            warn!("hash_data error: {}", status.to_string());
48            Err(StatusCodeEnum::CryptoServerNotReady)
49        }
50    }
51}
52
53pub async fn get_block_hash(
54    client: RetryClient<CryptoServiceClient<InterceptedSvc>>,
55    header: Option<&BlockHeader>,
56) -> Result<Vec<u8>, StatusCodeEnum> {
57    match header {
58        Some(header) => {
59            let mut block_header_bytes = Vec::with_capacity(header.encoded_len());
60            header.encode(&mut block_header_bytes).map_err(|_| {
61                warn!("get_block_hash: encode block header failed");
62                StatusCodeEnum::EncodeError
63            })?;
64            let block_hash = hash_data(client, &block_header_bytes).await?;
65            Ok(block_hash)
66        }
67        None => Err(StatusCodeEnum::NoneBlockHeader),
68    }
69}
70
71pub async fn pk2address(
72    client: RetryClient<CryptoServiceClient<InterceptedSvc>>,
73    pk: &[u8],
74) -> Result<Vec<u8>, StatusCodeEnum> {
75    Ok(hash_data(client, pk).await?[HASH_BYTES_LEN - ADDR_BYTES_LEN..].to_vec())
76}
77
78pub async fn sign_message(
79    client: RetryClient<CryptoServiceClient<InterceptedSvc>>,
80    msg: &[u8],
81) -> Result<Vec<u8>, StatusCodeEnum> {
82    let smr = client
83        .sign_message(SignMessageRequest { msg: msg.to_vec() })
84        .await
85        .map_err(|e| {
86            warn!("sign_message failed: {}", e.to_string());
87            StatusCodeEnum::CryptoServerNotReady
88        })?;
89
90    let status = StatusCodeEnum::from(smr.status.ok_or(StatusCodeEnum::NoneStatusCode)?);
91    if status != StatusCodeEnum::Success {
92        Err(status)
93    } else {
94        Ok(smr.signature)
95    }
96}
97
98pub async fn recover_signature(
99    client: RetryClient<CryptoServiceClient<InterceptedSvc>>,
100    signature: &[u8],
101    msg: &[u8],
102) -> Result<Vec<u8>, StatusCodeEnum> {
103    let rsr = client
104        .recover_signature(RecoverSignatureRequest {
105            msg: msg.to_vec(),
106            signature: signature.to_vec(),
107        })
108        .await
109        .map_err(|e| {
110            warn!("recover_signature failed: {}", e.to_string());
111            StatusCodeEnum::CryptoServerNotReady
112        })?;
113
114    let status = StatusCodeEnum::from(rsr.status.ok_or(StatusCodeEnum::NoneStatusCode)?);
115    if status != StatusCodeEnum::Success {
116        Err(status)
117    } else {
118        Ok(rsr.address)
119    }
120}