Skip to content

Commit

Permalink
fix further issue with share indexing when stored as a vector of shares
Browse files Browse the repository at this point in the history
  • Loading branch information
Gary Mawdsley committed Nov 23, 2024
1 parent bc7443c commit 9f883f1
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 35 deletions.
10 changes: 6 additions & 4 deletions src/redis_data_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,14 +283,15 @@ impl DataStore for RedisDataStore {
async fn hset_shares(&self, key: &str, field: &str, shares: &[Vec<u8>]) -> Result<(), DataStoreError> {
let mut conn = self.pool.get().map_err(|_| DataStoreError::ConnectionError)?;

// Convert each share to base64 for storage
println!("Storing {} shares, first share length: {}", shares.len(), shares[0].len());
let encoded_shares: Vec<String> = shares.iter()
.map(|share| general_purpose::STANDARD.encode(share))
.collect();

let json = serde_json::to_string(&encoded_shares)
.map_err(|_| DataStoreError::OperationFailed)?;

println!("JSON length for storage: {}", json.len());

conn.hset(key, field, json)
.map_err(|_| DataStoreError::OperationFailed)?;

Expand All @@ -302,9 +303,10 @@ impl DataStore for RedisDataStore {

let result: Option<String> = conn.hget(key, field)
.map_err(|_| DataStoreError::OperationFailed)?;

match result {
Some(json) => {
println!("JSON length on retrieval: {}", json.len());
let encoded_shares: Vec<String> = serde_json::from_str(&json)
.map_err(|_| DataStoreError::OperationFailed)?;

Expand Down
94 changes: 63 additions & 31 deletions src/secret_sharing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ use rayon::prelude::*;use rayon::ThreadPool;
use anyhow::{Result, Error};
//use tokio; // For async runtime support

use base64::engine::general_purpose;
use base64::Engine;

// Custom deserialization function for BigInt
fn deserialize_bigint<'de, D>(deserializer: D) -> Result<BigInt, D::Error>
where
Expand Down Expand Up @@ -65,43 +68,72 @@ impl SecretSharingService {

pub async fn dis_assembly(&self, secret_data_value: &str) -> Result<Vec<Vec<u8>>, anyhow::Error> {
let secret = secret_data_value.as_bytes();
let chunks = secret.chunks(self.settings.chunk_size)
.map(|chunk| chunk.to_vec())
.collect::<Vec<_>>();
println!("Input content length: {}", secret.len());

// Convert bytes to BigInt for processing
let secret_bigint = BigInt::from_bytes_be(Sign::Plus, secret);

// Generate shares directly using the SSS implementation
let shares = self.sss.split(secret_bigint);

println!("\nRaw shares from SSS split:");
for (idx, share) in shares.iter() {
println!("Share {}: {}", idx, share.to_str_radix(10));
}

let shares: Vec<Vec<u8>> = self.pool.install(|| {
chunks.par_iter().map(|chunk| {
let secret_bigint = BigInt::from_bytes_be(Sign::Plus, chunk);
let shares = self.sss.split(secret_bigint);

shares.into_iter()
.map(|(_index, share)| share.to_bytes_be().1)
.collect::<Vec<Vec<u8>>>()
// Convert shares to byte vectors
let share_bytes: Vec<Vec<u8>> = shares.into_iter()
.map(|(idx, share)| {
let mut bytes = vec![idx as u8]; // Store index as first byte
bytes.extend(share.to_bytes_be().1);
bytes
})
.flatten()
.collect()
});

Ok(shares)
.collect();

println!("Share bytes generated:");
for share in share_bytes.iter() {
println!("Share {}: length={}", share[0], share.len());
}

Ok(share_bytes)
}

pub async fn re_assembly(&self, shares: &[Vec<u8>]) -> Result<String, anyhow::Error> {
// Group shares by chunk (share_amount shares per chunk)
let chunks = shares.chunks(self.settings.share_amount);
println!("Attempting reconstruction with {} shares", shares.len());

// Convert bytes back to (index, BigInt) pairs, using stored indices
let shares_for_recovery: Vec<(usize, BigInt)> = shares[..self.settings.threshold]
.iter()
.map(|share| {
let idx = share[0] as usize;
let bigint = BigInt::from_bytes_be(Sign::Plus, &share[1..]);
(idx, bigint)
})
.collect();

println!("\nShares prepared for recovery:");
for (idx, share) in shares_for_recovery.iter() {
println!("Share {}: {}", idx, share.to_str_radix(10));
}

println!("Processing {} shares for reconstruction", shares_for_recovery.len());

// Recover the secret using the SSS implementation
let recovered = self.sss.recover(&shares_for_recovery);
println!("Recovered BigInt: {}", recovered.to_str_radix(10));

// Convert recovered BigInt back to string
let (sign, result) = recovered.to_bytes_be();
println!("Bytes sign: {:?}", sign);
println!("Raw bytes: {:?}", result);

// Try to print as UTF-8 string before conversion
if let Ok(str_preview) = String::from_utf8(result.clone()) {
println!("Preview as UTF-8: {}", str_preview);
} else {
println!("Bytes are not valid UTF-8");
}

let reconstructed: Vec<Vec<u8>> = chunks.map(|chunk_shares| {
// Take any threshold number of shares for reconstruction
let shares: Vec<(usize, BigInt)> = chunk_shares.iter()
.take(self.settings.threshold) // Take only threshold number needed for reconstruction
.enumerate()
.map(|(i, share)| (i as usize, BigInt::from_bytes_be(Sign::Plus, share)))
.collect();

let reconstructed = self.sss.recover(&shares);
reconstructed.to_bytes_be().1
}).collect();

let result = reconstructed.concat();
String::from_utf8(result).map_err(|e| anyhow::anyhow!(e))
}

Expand Down

0 comments on commit 9f883f1

Please sign in to comment.