1use serde::{Deserialize, Serialize};
20use tokio::io::{AsyncReadExt, AsyncWriteExt};
21use tokio::net::UnixStream;
22
23use crate::error::Error;
24
25pub struct SignerClient {
27 path: String,
28}
29
30#[derive(Debug, Serialize)]
32enum SignerRequest {
33 Sign {
34 key_id: String,
35 operation: String,
36 data: String,
37 },
38}
39
40#[derive(Debug, Deserialize)]
42#[serde(untagged)]
43enum SignerResponse {
44 Ok { signature: String },
45 Err { error: String },
46}
47
48impl SignerClient {
49 pub async fn connect(path: &str) -> Result<Self, Error> {
54 let stream = UnixStream::connect(path)
56 .await
57 .map_err(|e| Error::Signer(format!("cannot connect to {path}: {e}")))?;
58 drop(stream);
59
60 Ok(Self {
61 path: path.to_string(),
62 })
63 }
64
65 pub fn new(path: &str) -> Self {
69 Self {
70 path: path.to_string(),
71 }
72 }
73
74 pub async fn sign(&self, key_id: &str, operation: &str, data: &[u8]) -> Result<String, Error> {
86 let request = SignerRequest::Sign {
87 key_id: key_id.to_string(),
88 operation: operation.to_string(),
89 data: crate::crypto::base64url_encode(data),
90 };
91
92 let request_json =
93 serde_json::to_vec(&request).map_err(|e| Error::Signer(format!("serialize: {e}")))?;
94
95 let mut stream = UnixStream::connect(&self.path)
96 .await
97 .map_err(|e| Error::Signer(format!("connect: {e}")))?;
98
99 let len = request_json.len() as u32;
101 stream
102 .write_all(&len.to_be_bytes())
103 .await
104 .map_err(|e| Error::Signer(format!("write length: {e}")))?;
105 stream
106 .write_all(&request_json)
107 .await
108 .map_err(|e| Error::Signer(format!("write body: {e}")))?;
109 stream
110 .flush()
111 .await
112 .map_err(|e| Error::Signer(format!("flush: {e}")))?;
113
114 let mut len_buf = [0u8; 4];
116 stream
117 .read_exact(&mut len_buf)
118 .await
119 .map_err(|e| Error::Signer(format!("read length: {e}")))?;
120 let resp_len = u32::from_be_bytes(len_buf) as usize;
121
122 if resp_len > 1024 * 1024 {
123 return Err(Error::Signer(format!(
124 "response too large: {resp_len} bytes"
125 )));
126 }
127
128 let mut resp_buf = vec![0u8; resp_len];
129 stream
130 .read_exact(&mut resp_buf)
131 .await
132 .map_err(|e| Error::Signer(format!("read body: {e}")))?;
133
134 let response: SignerResponse = serde_json::from_slice(&resp_buf)
135 .map_err(|e| Error::Signer(format!("deserialize response: {e}")))?;
136
137 match response {
138 SignerResponse::Ok { signature } => Ok(signature),
139 SignerResponse::Err { error } => Err(Error::Signer(format!("signer error: {error}"))),
140 }
141 }
142}