snipsco / rust-paillier

A pure-Rust implementation of the Paillier encryption scheme
Other
82 stars 12 forks source link

Possible to use single key for scalar and vector encryption simultaneously? #25

Closed polyfractal closed 7 years ago

polyfractal commented 7 years ago

I'm still reading up on how Paillier actually works, so this may be a silly question. Is it possible for a single set of keys to encrypt both a scalar and a vector at the same time? I attempted to do this, but the output was unstable. The vector was occasionally the correct result, but often just garbage values. Interestingly, the scalar was correct all the time.

The test is pretty simple. The secret is a vector from 0-100. In 10 iterations, 0,1,2,3...is added to each position in the vector. The amount added is also tallied onto a counter.

At the end, the vector should be [45, 46, 47, ...]

use paillier::*;

//keys
let (ek, dk) = Paillier::keypair().keys();

// cypher setup
let code = integral::Code::new(100, 16);
let eek = ek.with_code(&code);
let secret: Vec<u64> = (0..100).collect();
let mut cypher = Paillier::encrypt(&eek, &secret);

// counter setup
let counter_code = integral::Code::new(1, 16);
let eek_counter = ek.with_code(&counter_code);
let mut counter = Paillier::encrypt(&eek_counter, &0);

// plaintext for debug
let mut plain_counter = 0;
let mut plain_secret = secret.clone();

for i in 0..10 {
    let cypher_add = Paillier::encrypt(&eek, &vec![i; 100]);
    cypher = Paillier::add(&ek, &cypher_add, &cypher);
    plain_secret = plain_secret.iter().map(|x| { x + i }).collect();

    let counter_add = Paillier::encrypt(&eek_counter, &i);
    counter = Paillier::add(&ek, &counter_add, &counter);
    plain_counter += i;
}

let ddk = dk.with_code(&code);
let ddk_counter = dk.with_code(&counter_code);

let m: Vec<u64> = Paillier::decrypt(&ddk, &cypher);
println!("decrypted final is {:?} \n vs \nplain_counter: {:?}", m, plain_secret);

let n: u64 = Paillier::decrypt(&ddk_counter, &counter);
println!("decrypted counter: {:?} vs plain_counter: {:?}", n, plain_counter);

But the output is often crazy :)

    Finished release [optimized] target(s) in 0.0 secs
     Running `target/release/secret`

decrypted: [45377, 8106, 17995, 45938, 40529, 30752, 37842, 168, 3340, 4956, 63741, 48476, 4086, 19123, 25182, 47280, 26116, 5209, 17635, 10457, 9627, 46923, 32496, 11251, 18786, 22148, 53225, 22526, 18588, 55750, 61422, 53029, 50392, 44863, 39196, 19355, 31777, 38392, 35275, 38529, 2203, 22073, 61439, 64133, 14073, 22993, 1762, 13263, 7124, 40780, 29244, 17309, 47257, 9286, 30413, 8524, 11818, 53362, 50966, 34949, 15072, 16017, 560, 3417, 10933, 61291, 8198, 47468, 55814, 44483, 50380, 46619, 62870, 59105, 42416, 62889, 9342, 35276, 64856, 41950, 15754, 45110, 51763, 16264, 18391, 23242, 26481, 32601, 20174, 10040, 54617, 28150, 31440, 17476, 46381, 29981, 32015, 34109, 43601, 63525] 
 vs 
plain_secret: [45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144]

decrypted counter:45 vs plain_counter: 45

This is running with features = ["inclramp", "defaultramp", "keygen"]

kali commented 7 years ago

I was able to reduce the test-case a bit. It fails once every 5 tries or so...

extern crate paillier;

use paillier::*;

fn main() {
    let (ek, dk) = Paillier::keypair().keys();

    let code = integral::Code::new(100, 16);
    let eek = ek.with_code(&code);
    let secret: Vec<u64> = (0..100).collect();
    let cypher = Paillier::encrypt(&eek, &secret);

    let ddk = dk.with_code(&code);

    let m: Vec<u64> = Paillier::decrypt(&ddk, &cypher);
    assert_eq!(m, secret);
}
kali commented 7 years ago

Making progress here, the bug is presumably in the CRT variant of the decryption code. Switching to standard decryption algo fixed it.

kali commented 7 years ago

@polyfractal Feel tree to try out the fix-crt branch, as we will only be able to merge and release early next week.

polyfractal commented 7 years ago

Oh, awesome, thanks! I just assumed it was the mixing of different code types, rather than just a bug in the decryption.

This is a super cool library btw, been fun playing around with it :)

mortendahl commented 7 years ago

Hi @polyfractal, thanks for reporting the issue! New version now merged and pushed to crates.io.