Skip to content

Commit

Permalink
Take ArrayView as argument instead of Array
Browse files Browse the repository at this point in the history
  • Loading branch information
TrAyZeN authored and kingofpayne committed Apr 12, 2024
1 parent e5f3e4c commit 0fa6c25
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 136 deletions.
17 changes: 7 additions & 10 deletions benches/cpa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ fn cpa_sequential(leakages: &Array2<f64>, plaintexts: &Array2<u8>) -> Cpa {

for i in 0..leakages.shape()[0] {
cpa.update(
leakages.row(i).map(|&x| x as usize),
plaintexts.row(i).map(|&y| y as usize),
leakages.row(i).map(|&x| x as usize).view(),
plaintexts.row(i).map(|&y| y as usize).view(),
);
}

Expand All @@ -40,10 +40,7 @@ fn cpa_normal_sequential(leakages: &Array2<f64>, plaintexts: &Array2<u8>) -> cpa
leakages.axis_chunks_iter(Axis(0), chunk_size),
plaintexts.axis_chunks_iter(Axis(0), chunk_size),
) {
cpa.update(
leakages_chunk.map(|&x| x as f32),
plaintexts_chunk.to_owned(),
);
cpa.update(leakages_chunk.map(|&x| x as f32).view(), plaintexts_chunk);
}

cpa.finalize();
Expand Down Expand Up @@ -78,8 +75,8 @@ fn bench_cpa(c: &mut Criterion) {
|b, (leakages, plaintexts)| {
b.iter(|| {
cpa::cpa(
&leakages.map(|&x| x as usize),
&plaintexts.map(|&x| x as usize),
leakages.map(|&x| x as usize).view(),
plaintexts.map(|&x| x as usize).view(),
256,
0,
leakage_model,
Expand All @@ -102,8 +99,8 @@ fn bench_cpa(c: &mut Criterion) {
|b, (leakages, plaintexts)| {
b.iter(|| {
cpa_normal::cpa(
&leakages.map(|&x| x as f32),
plaintexts,
leakages.map(|&x| x as f32).view(),
plaintexts.view(),
256,
leakage_model_normal,
500,
Expand Down
4 changes: 2 additions & 2 deletions benches/snr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ fn snr_sequential(leakages: &Array2<i64>, plaintexts: &Array2<u8>) -> Array1<f64
let mut snr = Snr::new(leakages.shape()[1], 256);

for i in 0..leakages.shape()[0] {
snr.process(&leakages.row(i), plaintexts.row(i)[0] as usize);
snr.process(leakages.row(i), plaintexts.row(i)[0] as usize);
}

snr.snr()
}

fn snr_parallel(leakages: &Array2<i64>, plaintexts: &Array2<u8>) -> Array1<f64> {
compute_snr(leakages, 256, |i| plaintexts.row(i)[0].into(), 500)
compute_snr(leakages.view(), 256, |i| plaintexts.row(i)[0].into(), 500)
}

fn bench_snr(c: &mut Criterion) {
Expand Down
28 changes: 13 additions & 15 deletions examples/cpa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn cpa() -> Result<()> {
let start_sample = 0;
let end_sample = 5000;
let size = end_sample - start_sample; // Number of samples
let patch = 500;
let batch = 500;
let guess_range = 256; // 2**(key length)
let folder = String::from("../../data/cw");
let dir_l = format!("{folder}/leakages.npy");
Expand All @@ -30,23 +30,22 @@ fn cpa() -> Result<()> {
let plaintext = read_array2_from_npy_file::<FormatMetadata>(&dir_p)?;
let len_traces = leakages.shape()[0];

let mut cpa_parallel = ((0..len_traces).step_by(patch))
let mut cpa_parallel = ((0..len_traces).step_by(batch))
.progress_with(progress_bar(len_traces))
.par_bridge()
.map(|row_number| {
let mut cpa = Cpa::new(size, patch, guess_range, leakage_model);
let range_rows = row_number..row_number + patch;
let mut cpa = Cpa::new(size, batch, guess_range, leakage_model);
let range_rows = row_number..row_number + batch;
let range_samples = start_sample..end_sample;
let sample_traces = leakages
.slice(s![range_rows.clone(), range_samples])
.map(|l| *l as f32);
let sample_metadata: ArrayBase<OwnedRepr<usize>, Dim<[usize; 2]>> =
plaintext.slice(s![range_rows, ..]).map(|p| *p as usize);
cpa.update(sample_traces, sample_metadata);
let sample_metadata = plaintext.slice(s![range_rows, ..]).map(|p| *p as usize);
cpa.update(sample_traces.view(), sample_metadata.view());
cpa
})
.reduce(
|| Cpa::new(size, patch, guess_range, leakage_model),
|| Cpa::new(size, batch, guess_range, leakage_model),
|x, y| x + y,
);

Expand All @@ -63,13 +62,13 @@ fn success() -> Result<()> {
let start_sample = 0;
let end_sample = 5000;
let size = end_sample - start_sample; // Number of samples
let patch = 500;
let batch = 500;
let guess_range = 256; // 2**(key length)
let folder = String::from("../data/log_584012"); // "../../../intenship/scripts/log_584012"
let nfiles = 13; // Number of files in the directory. TBD: Automating this value
let rank_traces = 1000;

let mut cpa = Cpa::new(size, patch, guess_range, leakage_model);
let mut cpa = Cpa::new(size, batch, guess_range, leakage_model);

cpa.success_traces(rank_traces);
for i in (0..nfiles).progress() {
Expand All @@ -78,16 +77,15 @@ fn success() -> Result<()> {
let leakages = read_array2_from_npy_file::<FormatTraces>(&dir_l)?;
let plaintext = read_array2_from_npy_file::<FormatMetadata>(&dir_p)?;
let len_leakages = leakages.shape()[0];
for row in (0..len_leakages).step_by(patch) {
for row in (0..len_leakages).step_by(batch) {
let range_samples = start_sample..end_sample;
let range_rows: std::ops::Range<usize> = row..row + patch;
let range_rows: std::ops::Range<usize> = row..row + batch;
let range_metadat = 0..plaintext.shape()[1];
let sample_traces = leakages
.slice(s![range_rows.clone(), range_samples])
.map(|l| *l as f32);
let sample_metadata: Array2<FormatMetadata> =
plaintext.slice(s![range_rows, range_metadat]).to_owned();
cpa.update_success(sample_traces, sample_metadata);
let sample_metadata = plaintext.slice(s![range_rows, range_metadat]);
cpa.update_success(sample_traces.view(), sample_metadata);
}
}

Expand Down
10 changes: 5 additions & 5 deletions examples/cpa_partioned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn cpa() -> Result<()> {
let folder = String::from("../../data"); // Directory of leakages and metadata
let nfiles = 5; // Number of files in the directory. TBD: Automating this value

/* Parallel operation using multi-threading on patches */
/* Parallel operation using multi-threading on batches */
let mut cpa = (0..nfiles)
.progress_with(progress_bar(nfiles))
.map(|n| {
Expand All @@ -33,13 +33,13 @@ fn cpa() -> Result<()> {
(leakages, plaintext)
})
.par_bridge()
.map(|patch| {
.map(|batch| {
let mut c = Cpa::new(size, guess_range, target_byte, leakage_model);
let len_leakage = patch.0.shape()[0];
let len_leakage = batch.0.shape()[0];
for i in 0..len_leakage {
c.update(
patch.0.row(i).map(|x| *x as usize),
patch.1.row(i).map(|y| *y as usize),
batch.0.row(i).map(|x| *x as usize).view(),
batch.1.row(i).map(|y| *y as usize).view(),
);
}
c
Expand Down
36 changes: 18 additions & 18 deletions examples/dpa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ pub fn leakage_model(value: Array1<FormatMetadata>, guess: usize) -> usize {
}

fn dpa() -> Result<()> {
let start_sample: usize = 0;
let end_sample: usize = 2000;
let size: usize = end_sample - start_sample; // Number of samples
let start_sample = 0;
let end_sample = 2000;
let size = end_sample - start_sample; // Number of samples
let guess_range = 256; // 2**(key length)
let folder = String::from("../../data/cw");
let dir_l = format!("{folder}/leakages.npy");
Expand All @@ -32,8 +32,8 @@ fn dpa() -> Result<()> {
.row(i)
.slice(s![start_sample..end_sample])
.map(|t| *t as f32);
let tmp_metadata = plaintext.row(i).to_owned();
dpa.update(tmp_trace, tmp_metadata);
let tmp_metadata = plaintext.row(i);
dpa.update(tmp_trace.view(), tmp_metadata.to_owned());
}
dpa.finalize();
println!("Guessed key = {:02x}", dpa.pass_guess());
Expand All @@ -44,9 +44,9 @@ fn dpa() -> Result<()> {

#[allow(dead_code)]
fn dpa_success() -> Result<()> {
let start_sample: usize = 0;
let end_sample: usize = 2000;
let size: usize = end_sample - start_sample; // Number of samples
let start_sample = 0;
let end_sample = 2000;
let size = end_sample - start_sample; // Number of samples
let guess_range = 256; // 2**(key length)
let folder = String::from("../../data/cw");
let dir_l = format!("{folder}/leakages.npy");
Expand All @@ -64,7 +64,7 @@ fn dpa_success() -> Result<()> {
.slice(s![start_sample..end_sample])
.map(|t| *t as f32);
let tmp_metadata = plaintext.row(i).to_owned();
dpa.update_success(tmp_trace, tmp_metadata);
dpa.update_success(tmp_trace.view(), tmp_metadata);
}

println!("Guessed key = {:02x}", dpa.pass_guess());
Expand All @@ -75,30 +75,30 @@ fn dpa_success() -> Result<()> {

#[allow(dead_code)]
fn dpa_parallel() -> Result<()> {
let start_sample: usize = 0;
let end_sample: usize = 2000;
let size: usize = end_sample - start_sample; // Number of samples
let start_sample = 0;
let end_sample = 2000;
let size = end_sample - start_sample; // Number of samples
let guess_range = 256; // 2**(key length)
let folder = String::from("../../data/cw");
let dir_l = format!("{folder}/leakages.npy");
let dir_p = format!("{folder}/plaintexts.npy");
let leakages: Array2<FormatTraces> = read_array2_from_npy_file::<FormatTraces>(&dir_l)?;
let plaintext: Array2<FormatMetadata> = read_array2_from_npy_file::<FormatMetadata>(&dir_p)?;
let len_traces = 20000; //leakages.shape()[0];
let patch: usize = 2500;
let batch = 2500;
let mut dpa = (0..len_traces)
.step_by(patch)
.step_by(batch)
.par_bridge()
.map(|range_rows: usize| {
let tmp_leakages = leakages
.slice(s![range_rows..range_rows + patch, start_sample..end_sample])
.slice(s![range_rows..range_rows + batch, start_sample..end_sample])
.map(|l| *l as f32);
let tmp_metadata = plaintext
.slice(s![range_rows..range_rows + patch, ..])
.slice(s![range_rows..range_rows + batch, ..])
.to_owned();
let mut dpa_inner = Dpa::new(size, guess_range, leakage_model);
for i in 0..patch {
let trace = tmp_leakages.row(i).to_owned();
for i in 0..batch {
let trace = tmp_leakages.row(i);
let metadata = tmp_metadata.row(i).to_owned();
dpa_inner.update(trace, metadata);
}
Expand Down
4 changes: 2 additions & 2 deletions examples/rank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ fn rank() -> Result<()> {
|| Cpa::new(size, guess_range, target_byte, leakage_model),
|mut r: Cpa, n| {
r.update(
l_sample.row(n).map(|l: &FormatTraces| *l as usize),
p_sample.row(n).map(|p: &FormatMetadata| *p as usize),
l_sample.row(n).map(|l| *l as usize).view(),
p_sample.row(n).map(|p| *p as usize).view(),
);
r
},
Expand Down
2 changes: 1 addition & 1 deletion examples/snr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn main() -> Result<()> {
for trace in batch {
// `process` takes an `ArrayView1` argument, which makes possible to pass a
// trace slice: `traces.leakage.slice(s![100..])` for instance.
snr.process(&trace.leakage.view(), trace.value as usize)
snr.process(trace.leakage.view(), trace.value as usize)
}
snr
},
Expand Down
38 changes: 22 additions & 16 deletions src/cpa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use std::{iter::zip, ops::Add};
/// - Panic if `leakages.shape()[0] != plaintexts.shape()[0]`
/// - Panic if `chunk_size` is 0.
pub fn cpa(
leakages: &Array2<usize>,
plaintexts: &Array2<usize>,
leakages: ArrayView2<usize>,
plaintexts: ArrayView2<usize>,
guess_range: usize,
target_byte: usize,
leakage_func: fn(usize, usize) -> usize,
Expand All @@ -30,10 +30,7 @@ pub fn cpa(
let mut cpa = Cpa::new(leakages.shape()[1], guess_range, target_byte, leakage_func);

for i in 0..leakages_chunk.shape()[0] {
cpa.update(
leakages_chunk.row(i).to_owned(),
plaintexts_chunk.row(i).to_owned(),
);
cpa.update(leakages_chunk.row(i), plaintexts_chunk.row(i));
}

cpa
Expand Down Expand Up @@ -91,21 +88,31 @@ impl Cpa {
}
}

pub fn update(&mut self, trace: Array1<usize>, plaintext: Array1<usize>) {
pub fn update(&mut self, trace: ArrayView1<usize>, plaintext: ArrayView1<usize>) {
/* This function updates the main arrays of the CPA, as shown in Alg. 4
in the paper.*/
self.len_leakages += 1;
self.gen_values(plaintext.clone(), self.guess_range, self.target_byte);
self.go(trace, plaintext.clone(), self.guess_range);
self.gen_values(plaintext, self.guess_range, self.target_byte);
self.go(trace, plaintext, self.guess_range);
}

pub fn gen_values(&mut self, metadata: Array1<usize>, guess_range: usize, target_key: usize) {
pub fn gen_values(
&mut self,
metadata: ArrayView1<usize>,
guess_range: usize,
target_key: usize,
) {
for guess in 0..guess_range {
self.values[guess] = (self.leakage_func)(metadata[target_key], guess);
}
}

pub fn go(&mut self, trace: Array1<usize>, metadata: Array1<usize>, guess_range: usize) {
pub fn go(
&mut self,
trace: ArrayView1<usize>,
metadata: ArrayView1<usize>,
guess_range: usize,
) {
for i in 0..self.len_samples {
self.sum_leakages[i] += trace[i];
self.sig_leakages[i] += trace[i] * trace[i];
Expand All @@ -126,8 +133,7 @@ impl Cpa {
overall traces */

let shape_p = self.guess_range;
let mut p: ndarray::ArrayBase<ndarray::OwnedRepr<usize>, ndarray::Dim<[usize; 2]>> =
Array2::zeros((shape_p, shape_p));
let mut p = Array2::zeros((shape_p, shape_p));
for i in 0..self.guess_range {
for x in 0..self.guess_range {
p[[x, i]] = (self.leakage_func)(x, i);
Expand All @@ -136,7 +142,7 @@ impl Cpa {
for i in 0..self.guess_range {
let _sigkeys = self.sig_keys[i] as f32 / self.len_leakages as f32;
let _sumkeys = self.sum_keys[i] as f32 / self.len_leakages as f32;
let lower1: f32 = _sigkeys - (_sumkeys * _sumkeys);
let lower1 = _sigkeys - (_sumkeys * _sumkeys);

/* Parallel operation using multi-threading */
let tmp: Vec<f32> = (0..self.len_samples)
Expand Down Expand Up @@ -187,8 +193,8 @@ impl Cpa {
self.rank_slice.slice(s![.., 1..])
}

pub fn pass_corr_array(&self) -> Array2<f32> {
self.corr.clone()
pub fn pass_corr_array(&self) -> ArrayView2<f32> {
self.corr.view()
}

pub fn pass_guess(&self) -> usize {
Expand Down

0 comments on commit 0fa6c25

Please sign in to comment.