nostr_android_signer/
client.rs

1//! Android signer client
2
3use std::borrow::Cow;
4use std::os::unix::net::UnixStream as StdUnixStream;
5use std::sync::Arc;
6
7use hyper_util::rt::TokioIo;
8use nostr::prelude::*;
9use nostr_android_signer_proto::android_signer_client::AndroidSignerClient;
10use nostr_android_signer_proto::{
11    GetPublicKeyReply, GetPublicKeyRequest, IsExternalSignerInstalledReply,
12    IsExternalSignerInstalledRequest, Nip04DecryptReply, Nip04DecryptRequest, Nip04EncryptReply,
13    Nip04EncryptRequest, Nip44DecryptReply, Nip44DecryptRequest, Nip44EncryptReply,
14    Nip44EncryptRequest, SignEventReply, SignEventRequest,
15};
16use tokio::net::UnixStream as TokioUnixStream;
17use tokio::sync::{Mutex, OnceCell};
18use tonic::transport::{Channel, Endpoint, Uri};
19use tonic::{Request, Response};
20use tower::service_fn;
21use uds::{UnixSocketAddr, UnixStreamExt};
22
23use crate::error::Error;
24
25/// Android signer client.
26#[derive(Debug, Clone)]
27pub struct AndroidSigner {
28    /// UNIX socket address
29    socket_addr: UnixSocketAddr,
30    /// Timeout for requests
31    client: OnceCell<Arc<Mutex<AndroidSignerClient<Channel>>>>,
32    /// Current user public key
33    public_key: OnceCell<PublicKey>,
34}
35
36impl AndroidSigner {
37    /// Construct a new Android signer.
38    #[inline]
39    pub fn new(unique_name: &str) -> Result<Self, Error> {
40        let name: String = format!("nip55_proxy_{unique_name}");
41
42        Ok(Self {
43            socket_addr: UnixSocketAddr::from_abstract(name.as_bytes())?,
44            client: OnceCell::new(),
45            public_key: OnceCell::new(),
46        })
47    }
48
49    async fn client(&self) -> Result<&Arc<Mutex<AndroidSignerClient<Channel>>>, Error> {
50        self.client
51            .get_or_try_init(|| async {
52                let socket_addr: UnixSocketAddr = self.socket_addr;
53
54                // We will ignore this uri because uds do not use it
55                let channel: Channel = Endpoint::try_from("unix://fake_uri")?
56                    .connect_with_connector(service_fn(move |_: Uri| async move {
57                        let stream: TokioUnixStream = connect(&socket_addr)?;
58
59                        Ok::<_, Error>(TokioIo::new(stream))
60                    }))
61                    .await?;
62
63                // Construct client
64                let client: AndroidSignerClient<Channel> = AndroidSignerClient::new(channel);
65
66                Ok(Arc::new(Mutex::new(client)))
67            })
68            .await
69    }
70
71    /// Check if an external signer is installed.
72    pub async fn is_external_signer_installed(&self) -> Result<bool, Error> {
73        // Get the client
74        let client = self.client().await?;
75
76        // Acquire the lock
77        let mut client = client.lock().await;
78
79        // Make the request
80        let req: Request<IsExternalSignerInstalledRequest> =
81            Request::new(IsExternalSignerInstalledRequest {});
82        let res: Response<IsExternalSignerInstalledReply> =
83            client.is_external_signer_installed(req).await?;
84
85        // Unwrap the response
86        let inner: IsExternalSignerInstalledReply = res.into_inner();
87        Ok(inner.installed)
88    }
89
90    async fn _get_public_key(&self) -> Result<&PublicKey, Error> {
91        self.public_key
92            .get_or_try_init(|| async {
93                // Get the client
94                let client = self.client().await?;
95
96                // Acquire the lock
97                let mut client = client.lock().await;
98
99                // Make the request
100                let req: Request<GetPublicKeyRequest> = Request::new(GetPublicKeyRequest {});
101                let res: Response<GetPublicKeyReply> = client.get_public_key(req).await?;
102
103                // Unwrap the response
104                let inner: GetPublicKeyReply = res.into_inner();
105                Ok(PublicKey::parse(&inner.public_key)?)
106            })
107            .await
108    }
109
110    async fn _sign_event(&self, unsigned: UnsignedEvent) -> Result<Event, Error> {
111        // Get the client
112        let client = self.client().await?;
113
114        // Acquire the lock
115        let mut client = client.lock().await;
116
117        // Make the request
118        let req: Request<SignEventRequest> = Request::new(SignEventRequest {
119            unsigned_event: unsigned.as_json(),
120            current_user_public_key: unsigned.pubkey.to_hex(),
121        });
122        let res: Response<SignEventReply> = client.sign_event(req).await?;
123
124        // Unwrap the response
125        let inner: SignEventReply = res.into_inner();
126        let event: Event = Event::from_json(&inner.event)?;
127
128        // Verify
129        event.verify()?;
130
131        Ok(event)
132    }
133
134    async fn _nip04_encrypt(
135        &self,
136        current_user_public_key: &PublicKey,
137        public_key: &PublicKey,
138        plaintext: &str,
139    ) -> Result<String, Error> {
140        // Get the client
141        let client = self.client().await?;
142
143        // Acquire the lock
144        let mut client = client.lock().await;
145
146        // Make the request
147        let req: Request<Nip04EncryptRequest> = Request::new(Nip04EncryptRequest {
148            current_user_public_key: current_user_public_key.to_hex(),
149            other_public_key: public_key.to_hex(),
150            plaintext: plaintext.to_string(),
151        });
152        let res: Response<Nip04EncryptReply> = client.nip04_encrypt(req).await?;
153
154        // Unwrap the response
155        let inner: Nip04EncryptReply = res.into_inner();
156        Ok(inner.ciphertext)
157    }
158
159    async fn _nip04_decrypt(
160        &self,
161        current_user_public_key: &PublicKey,
162        public_key: &PublicKey,
163        ciphertext: &str,
164    ) -> Result<String, Error> {
165        // Get the client
166        let client = self.client().await?;
167
168        // Acquire the lock
169        let mut client = client.lock().await;
170
171        // Make the request
172        let req: Request<Nip04DecryptRequest> = Request::new(Nip04DecryptRequest {
173            current_user_public_key: current_user_public_key.to_hex(),
174            other_public_key: public_key.to_hex(),
175            ciphertext: ciphertext.to_string(),
176        });
177        let res: Response<Nip04DecryptReply> = client.nip04_decrypt(req).await?;
178
179        // Unwrap the response
180        let inner: Nip04DecryptReply = res.into_inner();
181        Ok(inner.plaintext)
182    }
183
184    async fn _nip44_encrypt(
185        &self,
186        current_user_public_key: &PublicKey,
187        public_key: &PublicKey,
188        plaintext: &str,
189    ) -> Result<String, Error> {
190        // Get the client
191        let client = self.client().await?;
192
193        // Acquire the lock
194        let mut client = client.lock().await;
195
196        // Make the request
197        let req: Request<Nip44EncryptRequest> = Request::new(Nip44EncryptRequest {
198            current_user_public_key: current_user_public_key.to_hex(),
199            other_public_key: public_key.to_hex(),
200            plaintext: plaintext.to_string(),
201        });
202        let res: Response<Nip44EncryptReply> = client.nip44_encrypt(req).await?;
203
204        // Unwrap the response
205        let inner: Nip44EncryptReply = res.into_inner();
206        Ok(inner.ciphertext)
207    }
208
209    async fn _nip44_decrypt(
210        &self,
211        current_user_public_key: &PublicKey,
212        public_key: &PublicKey,
213        ciphertext: &str,
214    ) -> Result<String, Error> {
215        // Get the client
216        let client = self.client().await?;
217
218        // Acquire the lock
219        let mut client = client.lock().await;
220
221        // Make the request
222        let req: Request<Nip44DecryptRequest> = Request::new(Nip44DecryptRequest {
223            current_user_public_key: current_user_public_key.to_hex(),
224            other_public_key: public_key.to_hex(),
225            ciphertext: ciphertext.to_string(),
226        });
227        let res: Response<Nip44DecryptReply> = client.nip44_decrypt(req).await?;
228
229        // Unwrap the response
230        let inner: Nip44DecryptReply = res.into_inner();
231        Ok(inner.plaintext)
232    }
233}
234
235impl NostrSigner for AndroidSigner {
236    fn backend(&self) -> SignerBackend {
237        SignerBackend::Custom(Cow::Borrowed("android signer"))
238    }
239
240    fn get_public_key(&self) -> BoxedFuture<Result<PublicKey, SignerError>> {
241        Box::pin(async move {
242            self._get_public_key()
243                .await
244                .copied()
245                .map_err(SignerError::backend)
246        })
247    }
248
249    fn sign_event(&self, unsigned: UnsignedEvent) -> BoxedFuture<Result<Event, SignerError>> {
250        Box::pin(async move {
251            self._sign_event(unsigned)
252                .await
253                .map_err(SignerError::backend)
254        })
255    }
256
257    fn nip04_encrypt<'a>(
258        &'a self,
259        public_key: &'a PublicKey,
260        content: &'a str,
261    ) -> BoxedFuture<'a, Result<String, SignerError>> {
262        Box::pin(async move {
263            let current_user_public_key =
264                self._get_public_key().await.map_err(SignerError::backend)?;
265            self._nip04_encrypt(current_user_public_key, public_key, content)
266                .await
267                .map_err(SignerError::backend)
268        })
269    }
270
271    fn nip04_decrypt<'a>(
272        &'a self,
273        public_key: &'a PublicKey,
274        encrypted_content: &'a str,
275    ) -> BoxedFuture<'a, Result<String, SignerError>> {
276        Box::pin(async move {
277            let current_user_public_key =
278                self._get_public_key().await.map_err(SignerError::backend)?;
279            self._nip04_decrypt(current_user_public_key, public_key, encrypted_content)
280                .await
281                .map_err(SignerError::backend)
282        })
283    }
284
285    fn nip44_encrypt<'a>(
286        &'a self,
287        public_key: &'a PublicKey,
288        content: &'a str,
289    ) -> BoxedFuture<'a, Result<String, SignerError>> {
290        Box::pin(async move {
291            let current_user_public_key =
292                self._get_public_key().await.map_err(SignerError::backend)?;
293            self._nip44_encrypt(current_user_public_key, public_key, content)
294                .await
295                .map_err(SignerError::backend)
296        })
297    }
298
299    fn nip44_decrypt<'a>(
300        &'a self,
301        public_key: &'a PublicKey,
302        payload: &'a str,
303    ) -> BoxedFuture<'a, Result<String, SignerError>> {
304        Box::pin(async move {
305            let current_user_public_key =
306                self._get_public_key().await.map_err(SignerError::backend)?;
307            self._nip44_decrypt(current_user_public_key, public_key, payload)
308                .await
309                .map_err(SignerError::backend)
310        })
311    }
312}
313
314fn connect(socket_addr: &UnixSocketAddr) -> Result<TokioUnixStream, Error> {
315    // Connect to the abstract socket
316    let std_stream: StdUnixStream = StdUnixStream::connect_to_unix_addr(socket_addr)?;
317
318    // Moves the socket into nonblocking mode
319    std_stream.set_nonblocking(true)?;
320
321    // Convert to Tokio's async UnixStream
322    Ok(TokioUnixStream::from_std(std_stream)?)
323}