sos_core/encoding/v1/
crypto.rs

1use crate::{
2    crypto::{
3        AeadPack, Cipher, KeyDerivation, Nonce, AES_GCM_256, ARGON_2_ID,
4        BALLOON_HASH, X25519, X_CHACHA20_POLY1305,
5    },
6    encoding::encoding_error,
7};
8
9use async_trait::async_trait;
10use binary_stream::futures::{
11    BinaryReader, BinaryWriter, Decodable, Encodable,
12};
13use std::io::{Error, ErrorKind, Result};
14use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite};
15
16#[async_trait]
17impl Encodable for AeadPack {
18    async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
19        &self,
20        writer: &mut BinaryWriter<W>,
21    ) -> Result<()> {
22        match &self.nonce {
23            Nonce::Nonce12(ref bytes) => {
24                writer.write_u8(12).await?;
25                writer.write_bytes(bytes).await?;
26            }
27            Nonce::Nonce24(ref bytes) => {
28                writer.write_u8(24).await?;
29                writer.write_bytes(bytes).await?;
30            }
31        }
32        writer.write_u32(self.ciphertext.len() as u32).await?;
33        writer.write_bytes(&self.ciphertext).await?;
34        Ok(())
35    }
36}
37
38#[async_trait]
39impl Decodable for AeadPack {
40    async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
41        &mut self,
42        reader: &mut BinaryReader<R>,
43    ) -> Result<()> {
44        let nonce_size = reader.read_u8().await?;
45        let nonce_buffer = reader.read_bytes(nonce_size as usize).await?;
46        match nonce_size {
47            12 => {
48                self.nonce = Nonce::Nonce12(
49                    nonce_buffer
50                        .as_slice()
51                        .try_into()
52                        .map_err(encoding_error)?,
53                );
54            }
55            24 => {
56                self.nonce = Nonce::Nonce24(
57                    nonce_buffer
58                        .as_slice()
59                        .try_into()
60                        .map_err(encoding_error)?,
61                );
62            }
63            _ => {
64                return Err(Error::new(
65                    ErrorKind::Other,
66                    format!("unknown nonce size {}", nonce_size),
67                ));
68            }
69        }
70        let len = reader.read_u32().await?;
71        self.ciphertext = reader.read_bytes(len as usize).await?;
72        Ok(())
73    }
74}
75
76#[async_trait]
77impl Encodable for Cipher {
78    async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
79        &self,
80        writer: &mut BinaryWriter<W>,
81    ) -> Result<()> {
82        let id: u8 = self.into();
83        writer.write_u8(id).await?;
84        Ok(())
85    }
86}
87
88#[async_trait]
89impl Decodable for Cipher {
90    async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
91        &mut self,
92        reader: &mut BinaryReader<R>,
93    ) -> Result<()> {
94        let id = reader.read_u8().await?;
95        *self = match id {
96            X_CHACHA20_POLY1305 => Cipher::XChaCha20Poly1305,
97            AES_GCM_256 => Cipher::AesGcm256,
98            X25519 => Cipher::X25519,
99            _ => {
100                return Err(Error::new(
101                    ErrorKind::Other,
102                    format!("unknown cipher {}", id),
103                ));
104            }
105        };
106        Ok(())
107    }
108}
109
110#[async_trait]
111impl Encodable for KeyDerivation {
112    async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
113        &self,
114        writer: &mut BinaryWriter<W>,
115    ) -> Result<()> {
116        let id: u8 = self.into();
117        writer.write_u8(id).await?;
118        Ok(())
119    }
120}
121
122#[async_trait]
123impl Decodable for KeyDerivation {
124    async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
125        &mut self,
126        reader: &mut BinaryReader<R>,
127    ) -> Result<()> {
128        let id = reader.read_u8().await?;
129        *self = match id {
130            ARGON_2_ID => KeyDerivation::Argon2Id,
131            BALLOON_HASH => KeyDerivation::BalloonHash,
132            _ => {
133                return Err(Error::new(
134                    ErrorKind::Other,
135                    format!("unknown key derivation function {}", id),
136                ));
137            }
138        };
139        Ok(())
140    }
141}