Extract a LWE ciphertext from a RLWE ciphertext

Hello,
I am trying to extract a LWE ciphertext from a RLWE ciphertext yet at the decryption of the LWE ciphertext I obtain random values. I use concrete core. Here is the code :

use concrete_core::prelude::{GlweCiphertextCount, GlweDimension, PolynomialSize, Variance, LweCiphertext64,*};
use concrete_core::specification::engines::{
    LweCiphertextDiscardingExtractionEngine, LweCiphertextDiscardingExtractionError,
};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {


// DISCLAIMER: the parameters used here are only for test purpose, and are not secure.
    let glwe_dimension = GlweDimension(2);
    let polynomial_size = PolynomialSize(4);
    let lwe_dimension = LweDimension(8);

//obtaining my input from a txt file and shifting by 20 bits
let input = get_input_from_txt("input.txt"); 
    let input = shift_input(input);

    let noise = Variance(2_f64.powf(-75.));

    // Unix seeder must be given a secret input.
// Here we just give it 0, which is totally unsafe.
    const UNSAFE_SECRET: u128 = 0;
    let mut engine = DefaultEngine::new(Box::new(UnixSeeder::new(UNSAFE_SECRET)))?;
    let key: GlweSecretKey32 = engine.generate_new_glwe_secret_key(glwe_dimension, polynomial_size)?;
    let plaintext = engine.create_plaintext_vector_from(&input)?;
    let ciphertext = engine.encrypt_glwe_ciphertext(&key, &plaintext, noise)?;

    let lwe_key : LweSecretKey32 = engine.generate_new_lwe_secret_key(lwe_dimension)?;
    let mut lwe_ciphertext = engine.zero_encrypt_lwe_ciphertext(&lwe_key,noise)?;

    engine.discard_extract_lwe_ciphertext( &mut lwe_ciphertext, &ciphertext,MonomialIndex(2));
    let decrypted_plaintext2 = engine.decrypt_lwe_ciphertext(&lwe_key, &lwe_ciphertext)?;
    let output: u32 = engine.retrieve_plaintext(&decrypted_plaintext2)?;

    println!("{}",output>>20);
Ok(())
}

I would like to know if I am using the good function (discard_extract_lwe_ciphertext) and in this case what shall I correct. Else I would like to know if there is a function to extract a LWE ciphertext from a RLWE ciphertext.

Thank you for your answer

Hello @Victor !

I took your code and tried to change it to make it work, I think your issue is that you are using an LWE secret key that is not related to the original GLWE secret key, here is a rust code I wrote (adapted from yours) which outputs 2 with my hardcoded input, the main change I did was cloning the GLWE secret key and storing it as an LWE secret key :slightly_smiling_face:

use concrete_core::prelude::*;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    // DISCLAIMER: the parameters used here are only for test purpose, and are not secure.
    let glwe_dimension = GlweDimension(2);
    let polynomial_size = PolynomialSize(4);

    // Hard coding values for example purposes
    let input = [0u32 << 20, 1 << 20, 2 << 20, 3 << 20];

    let noise = Variance(2_f64.powf(-75.));

    // Unix seeder must be given a secret input.
    // Here we just give it 0, which is totally unsafe.
    const UNSAFE_SECRET: u128 = 0;
    let mut engine = DefaultEngine::new(Box::new(UnixSeeder::new(UNSAFE_SECRET)))?;
    let key: GlweSecretKey32 =
        engine.generate_new_glwe_secret_key(glwe_dimension, polynomial_size)?;
    let plaintext = engine.create_plaintext_vector_from(&input)?;
    let ciphertext = engine.encrypt_glwe_ciphertext(&key, &plaintext, noise)?;

    let lwe_key: LweSecretKey32 =
        engine.transform_glwe_secret_key_to_lwe_secret_key(key.clone())?;
    let mut lwe_ciphertext = engine.zero_encrypt_lwe_ciphertext(&lwe_key, noise)?;

    engine.discard_extract_lwe_ciphertext(&mut lwe_ciphertext, &ciphertext, MonomialIndex(2))?;
    let decrypted_plaintext2 = engine.decrypt_lwe_ciphertext(&lwe_key, &lwe_ciphertext)?;
    let output: u32 = engine.retrieve_plaintext(&decrypted_plaintext2)?;

    println!("{}", output >> 20);
    Ok(())
}

Let me know if you have further issues!

1 Like

That works perfectly, thank you a lot.

What you explained is not clear in the examples you can find here.
https://github.com/zama-ai/concrete-core/blob/f29e44b41e87d044f3781549379ac45994ec439f/concrete-core/src/backends/default/implementation/engines/default_engine/lwe_ciphertext_discarding_extraction.rs

Indeed, thanks a lot! I’ll open a PR on our end to enhance those doc strings