Chris Pollett > Students >
Molina

    ( Print View)

    [Bio]

    [Blog]

    [CS 297 Proposal]

    [Deliverable 1]

    [Deliverable 2]

    [Deliverable 3]

    [Deliverable 4]

    [McEliece System]

    [Regev System]

    [RSA System]

    [CS 297 Report-PDF]

    [CS 298 Proposal]

    [CS298 Slides-PDF]

    [CS298 Report-PDF]



// main.rs
use rand_distr::{Normal, Distribution};
use rand::{thread_rng, Rng};
use std::process;
use rand::prelude::SliceRandom;

fn main() {
    let mut n = 5;
    let mut B = alpha(n as f64);
    let mut p = 7;
    let mut m = 5;
    let mut private_key = private_key(m, n, p);
    let mut public_key = public_key(m, n, p, B, &private_key);
    let mut message = vec![1 as u64,0,0,1,1,0,1];
    let mut encrypted = encrypt_vector(&message, m, n, &public_key, p);
    let mut decrypted = decrypt_vector(&encrypted, &private_key, p);
    println!("decrypted = {:?}", decrypted);
}

fn encrypt_vector(message:&Vec<u64>, m:u64, n:u64, public_key:&Vec<(Vec<u64>, u64)>, p:u64) -> Vec<(Vec<u64>, u64)> {
    let mut encrypted_bits = Vec::new();
    for bit in message {
        let mut encrypted_bit = encrypt_bit(*bit, m, n, public_key, p);
        encrypted_bits.push(encrypted_bit);
    }
    encrypted_bits
}
fn decrypt_vector(encrypted_bits:&Vec<(Vec<u64>, u64)>, private_key:&Vec<u64>, p:u64) -> Vec<u64> {
    let mut decrypted_bits = Vec::new();
    for bit in encrypted_bits {
        let mut decrypted_bit = decrypt_bit(bit, private_key, p);
        decrypted_bits.push(decrypted_bit);
    }
    decrypted_bits
}

fn decrypt_bit(encrypted_bit:&(Vec<u64>, u64), private_key:&Vec<u64>, p:u64) -> u64 {
    let mut a = encrypted_bit.0.clone();
    let mut b = encrypted_bit.1.clone();
    let mut inner_product = inner_product(&a, &private_key, p);
    let mut point = b as i64 - inner_product as i64;
    //println!("point = {}", point);
    let mut q = (p as f64 / 2 as f64).floor();
    //println!("q = {}", q);
    let mut distance_to_0 = (point as i64 - 0 as i64).abs();
    let mut distance_to_q = (point.rem_euclid(p as i64) as i64 - q as i64).abs();
    //println!("distance to 0 = {}", distance_to_0);
    //println!("distance to q = {}", distance_to_q);
    if distance_to_0 < distance_to_q {
        return 0;
    } else {
        return 1;
    }
}

fn encrypt_bit(bit:u64, m:u64, n:u64, public_key:&Vec<(Vec<u64>, u64)>, p:u64) -> (Vec<u64>, u64) {
    let mut subset = choose_subset(m); 
    let mut x = vec![0; n as usize];
    let mut y = 0 as u64;
    for index in subset {
        let mut a = public_key[index as usize].0.clone();
        let mut b = public_key[index as usize].1.clone();
        x = add_vector(&x, &a, p);
        y += b;
        
    }
    if bit == 0 {
        y = y.rem_euclid(p);
        return (x,y);
    } else {
        y += (p as f64 / 2 as f64).floor() as u64;
        y = y.rem_euclid(p);
        return (x, y);
    }
}

fn add_vector(a:&Vec<u64>, b:&Vec<u64>, p:u64) -> Vec<u64> {
    let mut sum = Vec::new();
    for i in 0..a.len() {
        sum.push((a[i] + b[i]).rem_euclid(p));
    }
    sum
}

fn choose_subset(m:u64) -> Vec<u64> {
    let mut set = Vec::new();
    let mut num = rand::thread_rng().gen_range(0..2_u64.pow(m as u32)) as u64;
    for i in 0..m {
        if num%2==1 {
            set.push(i);
        }
        num = num >> 1;
    }
    set
}

fn private_key(m:u64, n:u64, p:u64) -> Vec<u64> {
    let mut private_key = draw_vector_from_Znp(n,p);
    private_key
}

fn public_key(m:u64, n:u64, p:u64, B:f64, private_key:&Vec<u64>) -> Vec<(Vec<u64>, u64)> {
    let mut s = private_key.clone();
    let mut public_key = Vec::new();
    for i in 0..m {
        let mut a = draw_vector_from_Znp(n, p);
        let mut b = inner_product(&a, &s, p) + draw_element_from_X(p, B);
        public_key.push((a,b));
    }
    public_key
} 

fn inner_product(a:&Vec<u64>, b:&Vec<u64>, p:u64) -> u64 {
    let mut sum = 0;
    if a.len() != b.len() {
        println!("Error in inner product - lengths were different");
        process::exit(1);
    }
    for i in 0..a.len() {
        sum += a[i] * b[i];
    }
    return (sum).rem_euclid(p);
}

fn draw_vector_from_Znp(n:u64, p:u64) -> Vec<u64> {
    let mut vec = Vec::new();
    for i in 0..n {
        vec.push(rand::thread_rng().gen_range(0..p));
    }
    vec
}

fn draw_element_from_X(p:u64, B:f64) -> u64 {
    let mut mean = 0.0;
    let mut std_dev = B/(2 as f64*std::f64::consts::PI).sqrt(); // mean 0, standard deviation B/sqrt(2pi)
    let normal = Normal::new(mean, std_dev).unwrap(); // create normal distribution 
    let mut v = normal.sample(&mut rand::thread_rng()); // sample from normal distribution
    let mut w = (v).rem_euclid(1.0); // reduce result modulo 1
    let mut x = w * p as f64; // multiply by p
    let mut y = (x.round()).rem_euclid(p as f64); // round to nearest integer modulo p
    return y as u64;
}

// return B E R+
fn alpha(n:f64) -> f64 {
    return 1 as f64/(n.sqrt() * n.log2() * n.log2());
}