1use crate::{Block, BlockKey, BlockStorage, RKPair, ReadCapability};
6use blake2::{
7 digest::consts::U32, digest::FixedOutput, digest::KeyInit, digest::Update, Blake2bMac,
8};
9use futures_lite::io::{AsyncRead, AsyncReadExt};
10
11impl<const BS: usize> Block<BS> {
12 fn encrypt(&mut self, convergence_secret: &[u8; 32]) -> RKPair {
13 let key = self.derive_key(convergence_secret);
14 self.chacha20(&key);
15 let reference = self.reference();
16 (reference, key)
17 }
18
19 fn derive_key(&self, convergence_secret: &[u8; 32]) -> BlockKey {
20 let mut hasher = Blake2bMac::<U32>::new_from_slice(convergence_secret).unwrap();
21 Update::update(&mut hasher, &**self);
22 BlockKey(hasher.finalize_fixed().into())
23 }
24}
25
26pub struct Encoder<'a, S: BlockStorage<BS>, const BS: usize> {
27 pub convergence_secret: [u8; 32],
28 pub block_storage: &'a S,
29}
30
31#[derive(thiserror::Error, Clone, Copy, Debug)]
33pub enum BlockSize {
34 #[error("1kB")]
35 _1K,
36 #[error("32kB")]
37 _32K,
38}
39
40pub async fn encode<S: BlockStorage<1024> + BlockStorage<32768>, R: AsyncRead + Unpin>(
48 content: &mut R,
49 convergence_secret: &[u8; 32],
50 block_size: BlockSize,
51 block_storage: &S,
52) -> std::io::Result<ReadCapability> {
53 match block_size {
54 BlockSize::_1K => {
55 encode_const::<_, _, 1024>(content, convergence_secret, block_storage).await
56 }
57 BlockSize::_32K => {
58 encode_const::<_, _, 32768>(content, convergence_secret, block_storage).await
59 }
60 }
61}
62
63pub async fn encode_const<S: BlockStorage<BS>, R: AsyncRead + Unpin, const BS: usize>(
64 content: &mut R,
65 convergence_secret: &[u8; 32],
66 block_storage: &S,
67) -> std::io::Result<ReadCapability> {
68 let mut encoder = Encoder::<S, BS> {
69 convergence_secret: convergence_secret.clone(),
70 block_storage,
71 };
72 encoder.encode(content).await
73}
74
75impl<'a, S: BlockStorage<BS>, const BS: usize> Encoder<'a, S, BS> {
76 pub async fn encode<R: AsyncRead + Unpin>(
77 &mut self,
78 content: &mut R,
79 ) -> std::io::Result<ReadCapability> {
80 let mut level = 0;
81 let mut rk_pairs = self.split_content(content).await?;
82
83 while rk_pairs.len() > 1 {
84 let new_rk_pairs = self.collect_rk_pairs(rk_pairs).await?;
85 rk_pairs = new_rk_pairs;
86 level += 1;
87 }
88
89 let root = rk_pairs.remove(0);
90 Ok(ReadCapability::from_rk_pair(root, level, BS))
91 }
92
93 async fn split_content<R: AsyncRead + Unpin>(
94 &mut self,
95 content: &mut R,
96 ) -> std::io::Result<Vec<RKPair>> {
97 let mut rk_pairs = vec![];
98 let mut buf = Block([0u8; BS]);
99 let mut pos;
100 loop {
101 pos = 0;
102 while pos < BS {
103 match content.read(&mut buf[pos..]).await? {
104 0 => break,
105 n => {
106 pos += n;
107 }
108 };
109 }
110 if pos != BS {
111 buf[pos..].fill(0);
112 buf[pos] = 0x80;
113 }
114
115 let rk_pair = buf.encrypt(&self.convergence_secret);
116 self.block_storage.store(&buf).await?;
117 rk_pairs.push(rk_pair);
118 if pos != BS {
119 break;
120 };
121 }
122
123 Ok(rk_pairs)
124 }
125
126 async fn collect_rk_pairs(
127 &mut self,
128 input_rk_pairs: Vec<RKPair>,
129 ) -> std::io::Result<Vec<RKPair>> {
130 let arity = BS / 64;
131
132 let mut output_rk_pairs = vec![];
133
134 for rk_pairs_for_node in input_rk_pairs.chunks(arity) {
135 let mut node = Block([0u8; BS]);
136 for (x, pair) in rk_pairs_for_node.iter().enumerate() {
137 node[64 * x..64 * x + 32].copy_from_slice(&pair.0 .0);
138 node[64 * x + 32..64 * x + 64].copy_from_slice(&pair.1 .0);
139 }
140
141 let rk_pair = node.encrypt(&self.convergence_secret);
142
143 self.block_storage.store(&node).await?;
144 output_rk_pairs.push(rk_pair);
145 }
146
147 Ok(output_rk_pairs)
148 }
149}