Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: zeroize #14

Merged
merged 2 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM rust:1.75 as base
RUN cargo install cargo-chef --version ^0.1

FROM base AS planner
WORKDIR /app
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

FROM base as builder
WORKDIR /app
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json
COPY . .
RUN cargo build

ENV WS_URL="ws://127.0.0.1:9944"
CMD ["/bin/murmur"]
30 changes: 19 additions & 11 deletions core/src/murmur.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ use rand_chacha::ChaCha20Rng;
use ark_std::rand::SeedableRng;
use ark_std::rand::{CryptoRng, Rng};

#[cfg(feature = "client")]
use zeroize::Zeroize;

#[cfg(feature = "client")]
use ark_serialize::CanonicalSerialize;

Expand Down Expand Up @@ -78,12 +81,13 @@ impl MurmurStore {
/// * `round_public_key`: The IDN beacon's public key
///
pub fn new<E: EngineBLS, I: IdentityBuilder<BlockNumber>>(
seed: Vec<u8>,
mut seed: Vec<u8>,
block_schedule: Vec<BlockNumber>,
ephemeral_msk: [u8; 32],
mut ephemeral_msk: [u8; 32],
round_public_key: DoublePublicKey<E>,
) -> Result<Self, Error> {
let totp = build_generator(&seed.clone())?;
let totp = build_generator(seed.clone())?;
seed.zeroize();
let mut metadata = BTreeMap::new();

let store = MemStore::default();
Expand Down Expand Up @@ -114,6 +118,7 @@ impl MurmurStore {
metadata.insert(*i, ct_bytes);
}

ephemeral_msk.zeroize();
let root = mmr.get_root().map_err(|_| Error::InconsistentStore)?;

Ok(MurmurStore { metadata, root })
Expand All @@ -127,12 +132,13 @@ impl MurmurStore {
///
pub fn execute(
&self,
seed: Vec<u8>,
mut seed: Vec<u8>,
when: BlockNumber,
call_data: Vec<u8>,
) -> Result<(MerkleProof<Leaf, MergeLeaves>, Vec<u8>, Ciphertext, u64), Error> {
if let Some(ciphertext) = self.metadata.get(&when) {
let commitment = MurmurStore::commit(seed.clone(), when, &call_data.clone())?;
seed.zeroize();
let idx = get_key_index(&self.metadata, &when)
.expect("The key must exist within the metadata.");
let pos = leaf_index_to_pos(idx as u64);
Expand All @@ -152,8 +158,9 @@ impl MurmurStore {
/// * `when`: The block number when the commitment is verifiable
/// * `data`: The data to commit to
///
fn commit(seed: Vec<u8>, when: BlockNumber, data: &[u8]) -> Result<Vec<u8>, Error> {
let botp = build_generator(&seed)?;
fn commit(mut seed: Vec<u8>, when: BlockNumber, data: &[u8]) -> Result<Vec<u8>, Error> {
let botp = build_generator(seed.clone())?;
seed.zeroize();
let otp_code = botp.generate(when);

let mut hasher = sha3::Sha3_256::default();
Expand Down Expand Up @@ -198,9 +205,10 @@ pub fn timelock_encrypt<E: EngineBLS, R: CryptoRng + Rng + Sized>(

/// Build a block-otp generator from the seed
#[cfg(feature = "client")]
fn build_generator(seed: &[u8]) -> Result<BOTPGenerator, Error> {
fn build_generator(mut seed: Vec<u8>) -> Result<BOTPGenerator, Error> {
let mut hasher = sha3::Sha3_256::default();
hasher.update(seed);
hasher.update(&seed);
seed.zeroize();
let hash = hasher.finalize();
BOTPGenerator::new(hash.to_vec())
.map_err(|_| Error::InvalidSeed)
Expand Down Expand Up @@ -318,7 +326,7 @@ mod tests {

// in practice, the otp code would be timelock decrypted
// but for testing purposes, we will just calculate the expected one now
let botp = build_generator(&seed.clone()).unwrap();
let botp = build_generator(seed.clone()).unwrap();
let otp_code = botp.generate(when);

assert!(verify(
Expand Down Expand Up @@ -396,7 +404,7 @@ mod tests {

// in practice, the otp code would be timelock decrypted
// but for testing purposes, we will just calculate the expected one now
let botp = build_generator(&seed.clone()).unwrap();
let botp = build_generator(seed.clone()).unwrap();
let otp_code = botp.generate(when);

let bad_aux = vec![2, 3, 13, 3];
Expand Down Expand Up @@ -456,7 +464,7 @@ mod tests {

// in practice, the otp code would be timelock decrypted
// but for testing purposes, we will just calculate the expected one now
let botp = build_generator(&seed.clone()).unwrap();
let botp = build_generator(seed.clone()).unwrap();
let otp_code = botp.generate(when);
assert!(!verify(
root,
Expand Down
2 changes: 2 additions & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ ark-ff = "0.4.0"
ark-serialize = "0.4.0"
w3f-bls = "0.1.3"
murmur-core = { path = "../core/", features = ["client"] }
zeroize = "1.8.1"


[dev-dependencies]
murmur-test-utils = { path = "../test-utils/" }
12 changes: 3 additions & 9 deletions lib/src/bin/murmur/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ struct WalletExecuteDetails {
seed: String,
#[arg(long, short)]
to: String,
#[arg(short, long)]
amount: String
#[arg(short, long, value_parser = clap::value_parser!(u128))]
amount: u128
}

#[derive(Error, Debug)]
Expand Down Expand Up @@ -133,16 +133,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let from_ss58_sized: [u8;32] = bytes.try_into()
.map_err(|_| CLIError::InvalidRecipient)?;
let to = subxt::utils::AccountId32::from(from_ss58_sized);
let v: u128 = args.amount
.split_whitespace()
.map(|r| r.replace('_', "")
.parse()
.unwrap()
).collect::<Vec<_>>()[0];

let balance_transfer_call = Balances(etf::balances::Call::transfer_allow_death {
dest: subxt::utils::MultiAddress::<_, u32>::from(to),
value: v,
value: args.amount,
});

let store: MurmurStore = load_mmr_store(MMR_STORE_FILEPATH)?;
Expand Down
11 changes: 7 additions & 4 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use subxt::{
config::SubstrateConfig,
ext::codec::Encode,
};

use zeroize::Zeroize;
use w3f_bls::{DoublePublicKey, SerializableToBytes, TinyBLS377};

// Generate an interface that we can use from the node's metadata.
Expand Down Expand Up @@ -62,8 +62,8 @@ impl IdentityBuilder<BlockNumber> for BasicIdBuilder {
///
pub fn create(
name: Vec<u8>,
seed: Vec<u8>,
ephem_msk: [u8; 32],
mut seed: Vec<u8>,
mut ephem_msk: [u8; 32],
block_schedule: Vec<BlockNumber>,
round_pubkey_bytes: Vec<u8>,
) -> Result<(subxt::tx::Payload<Create>, MurmurStore), Error> {
Expand All @@ -75,6 +75,8 @@ pub fn create(
ephem_msk,
round_pubkey,
)?;
ephem_msk.zeroize();
seed.zeroize();
let root = mmr_store.root.clone();

let call = etf::tx()
Expand All @@ -101,12 +103,13 @@ pub fn create(
///
pub fn prepare_execute(
name: Vec<u8>,
seed: Vec<u8>,
mut seed: Vec<u8>,
when: BlockNumber,
store: MurmurStore,
call: RuntimeCall,
) -> Result<subxt::tx::Payload<Proxy>, Error> {
let (proof, commitment, ciphertext, pos) = store.execute(seed.clone(), when, call.encode())?;
seed.zeroize();
let size = proof.mmr_size();
let proof_items: Vec<Vec<u8>> = proof
.proof_items()
Expand Down