1use std::{
28 collections::{BTreeMap, HashSet},
29 fmt::Debug,
30};
31
32#[derive(Debug, Clone)]
35pub struct ShamirSS;
36
37impl ShamirSS {
39
40 pub fn split(n: i32, k: i32, secret: Vec<u8>) -> Result<BTreeMap<i32, Vec<u8>>, String> {
60 if !(k > 1) {
61 return Err("Not k > 1".to_string());
62 }
63 if !(n >= k) {
64 return Err("Not n >= k".to_string());
65 }
66 if !(n <= 255) {
67 return Err("Not n <= 255".to_string());
68 }
69
70 let seclen = secret.len();
71 let mut values: Vec<Vec<u8>> = vec![vec![0u8; seclen]; n as usize];
72 let degree = k - 1;
73 for i in 0..=secret.len() - 1 {
74 let p = GFC256::generate(degree, secret[i]);
75 for x in 1..=n {
76 let index = x - 1;
77 let element = GFC256::eval(p.clone(), x as u8);
78 values[index as usize][i] = element;
79 }
80 }
81 let mut parts: BTreeMap<i32, Vec<u8>> = BTreeMap::new();
82 for i in 0..=n - 1 {
83 let mut tmp = vec![0u8; secret.len()];
84
85 for ii in 0..=secret.len() - 1 {
86 tmp[ii] = values[i as usize][ii as usize];
87 }
88 parts.insert(i + 1, tmp);
89 }
90
91 Ok(parts)
92 }
93
94 pub fn join(parts: BTreeMap<i32, Vec<u8>>) -> Result<Vec<u8>, String> {
112 let p = parts.clone();
113
114 if !(parts.len() > 0) {
115 return Err("No parts provided".to_string());
116 }
117 let mut h = HashSet::new();
118 for value in p.values() {
119 let l = value.clone().len();
120 if l != 0 {
121 h.insert(l);
122 }
123 }
124 if h.len() != 1 {
125 return Err("Varying lengths of part values".to_string());
126 }
127 let len = h.iter().next().unwrap();
128 let partslen = parts.len();
129 let mut secret = vec![0u8; len.clone()];
130
131 for i in 0..=secret.len() - 1 {
132 let mut points = vec![vec![0u8; 2]; partslen as usize];
133 let mut j = 0;
134
135 let mut iter = parts.iter();
136
137 while let Some(item) = iter.next() {
138 points[j][0] = *item.0 as u8;
140 points[j][1] = item.1[i];
141
142 j = j + 1;
143 }
144
145 secret[i] = GFC256::interpolate(points);
146 }
147
148 Ok(secret.clone())
149 }
150}
151
152struct GFC256;
154
155impl GFC256 {
157 fn add(a: u8, b: u8) -> u8 {
158 a ^ b
159 }
160 fn sub(a: u8, b: u8) -> u8 {
161 Self::add(a, b)
162 }
163 fn mul(a: u8, b: u8) -> u8 {
164 if a == 0 || b == 0 {
165 return 0;
166 }
167
168 let exp = LOG[a as usize] as i32 + LOG[b as usize] as i32;
169
170 EXP[exp as usize]
171 }
172 fn div(a: u8, b: u8) -> u8 {
173 Self::mul(a, EXP[255 - LOG[b as usize] as usize])
174 }
175
176 fn eval(p: Vec<u8>, x: u8) -> u8 {
178 let mut result: u8 = 0u8;
179
180 for i in (0..=p.len() - 1).rev() {
182 let val = p[i];
183 result = Self::add(Self::mul(result, x), val);
184 }
185
186 result
187 }
188 fn degree(p: Vec<u8>) -> i32 {
189 let to = p.len() - 1;
190
191 for i in (1..=to).rev() {
192 if p[i] != 0 {
193 return i as i32;
194 }
195 }
196 return 0;
197 }
198 fn generate(degree: i32, x: u8) -> Vec<u8> {
199 let d: i32 = degree + 1;
200 let mut p: Vec<u8>;
201
202 loop {
203 p = (0..d).map(|_| rand::random::<u8>()).collect();
204 let dg = Self::degree(p.clone());
205 if dg == degree {
206 break;
207 }
208 }
209 p[0] = x;
210
211 p
212 }
213
214 fn interpolate(points: Vec<Vec<u8>>) -> u8 {
216 let x: u8 = 0;
217 let mut y: u8 = 0;
218 let len = points.len() - 1;
219 for i in 0..=len {
220 let ax: u8 = points[i][0];
221 let ay: u8 = points[i][1];
222 let mut li: u8 = 1;
223 for j in 0..=len {
224 let bx = points[j][0];
225 if i != j {
226 li = Self::mul(li, Self::div(Self::sub(x, bx), Self::sub(ax, bx)));
227 }
228 }
229 let mul = Self::mul(li, ay);
230 y = Self::add(y, mul);
231 }
232 y
233 }
234}
235
236static LOG: [u8; 256] = [
237 0xff, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
238 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
239 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
240 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
241 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
242 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
243 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
244 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
245 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
246 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
247 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
248 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
249 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
250 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
251 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
252 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07,
253];
254
255static EXP: [u8; 510] = [
256 0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff, 0x1a, 0x2e, 0x72, 0x96, 0xa1, 0xf8, 0x13, 0x35,
257 0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4, 0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa,
258 0xe5, 0x34, 0x5c, 0xe4, 0x37, 0x59, 0xeb, 0x26, 0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31,
259 0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc, 0x4f, 0xd1, 0x68, 0xb8, 0xd3, 0x6e, 0xb2, 0xcd,
260 0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7, 0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88,
261 0x83, 0x9e, 0xb9, 0xd0, 0x6b, 0xbd, 0xdc, 0x7f, 0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a,
262 0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0, 0x0b, 0x1d, 0x27, 0x69, 0xbb, 0xd6, 0x61, 0xa3,
263 0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec, 0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0,
264 0xfb, 0x16, 0x3a, 0x4e, 0xd2, 0x6d, 0xb7, 0xc2, 0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41,
265 0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0, 0x5b, 0xed, 0x2c, 0x74, 0x9c, 0xbf, 0xda, 0x75,
266 0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e, 0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80,
267 0x9b, 0xb6, 0xc1, 0x58, 0xe8, 0x23, 0x65, 0xaf, 0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54,
268 0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09, 0x1b, 0x2d, 0x77, 0x99, 0xb0, 0xcb, 0x46, 0xca,
269 0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91, 0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e,
270 0x12, 0x36, 0x5a, 0xee, 0x29, 0x7b, 0x8d, 0x8c, 0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17,
271 0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd, 0x1c, 0x24, 0x6c, 0xb4, 0xc7, 0x52, 0xf6, 0x01,
272 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff, 0x1a, 0x2e, 0x72, 0x96, 0xa1, 0xf8, 0x13, 0x35, 0x5f,
273 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4, 0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa, 0xe5,
274 0x34, 0x5c, 0xe4, 0x37, 0x59, 0xeb, 0x26, 0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31, 0x53,
275 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc, 0x4f, 0xd1, 0x68, 0xb8, 0xd3, 0x6e, 0xb2, 0xcd, 0x4c,
276 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7, 0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88, 0x83,
277 0x9e, 0xb9, 0xd0, 0x6b, 0xbd, 0xdc, 0x7f, 0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a, 0xb5,
278 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0, 0x0b, 0x1d, 0x27, 0x69, 0xbb, 0xd6, 0x61, 0xa3, 0xfe,
279 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec, 0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0, 0xfb,
280 0x16, 0x3a, 0x4e, 0xd2, 0x6d, 0xb7, 0xc2, 0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41, 0xc3,
281 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0, 0x5b, 0xed, 0x2c, 0x74, 0x9c, 0xbf, 0xda, 0x75, 0x9f,
282 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e, 0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80, 0x9b,
283 0xb6, 0xc1, 0x58, 0xe8, 0x23, 0x65, 0xaf, 0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54, 0xfc,
284 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09, 0x1b, 0x2d, 0x77, 0x99, 0xb0, 0xcb, 0x46, 0xca, 0x45,
285 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91, 0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e, 0x12,
286 0x36, 0x5a, 0xee, 0x29, 0x7b, 0x8d, 0x8c, 0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17, 0x39,
287 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd, 0x1c, 0x24, 0x6c, 0xb4, 0xc7, 0x52, 0xf6,
288];
289
290#[cfg(test)]
291mod tests {
292 use super::*;
293
294 #[test]
295 fn it_works() {
296 let secret = b"Hello Shamir Shared Secret!!!!!";
297 let numparts = 5;
298 let miniumparts = 3;
299
300
301
302 let keys = ShamirSS::split(numparts, miniumparts, secret.to_vec());
303 assert!(keys.is_ok());
304 let keys = keys.unwrap();
305 let mut parts:BTreeMap<i32,Vec<u8>>=BTreeMap::new();
306 for (key, value) in &keys {
307 if *key <= miniumparts {
309 parts.insert(*key, value.clone());
310 }
311 }
312 let nshared = ShamirSS::join(parts);
313 assert!(nshared.is_ok());
314 let shared = nshared.unwrap();
315 assert_eq!(shared, secret.to_vec());
316
317 }
318}