Cryptographic Parameters

Parameters and message precision

shortint comes with sets of parameters that permit the use of the library functionalities securely and efficiently. Each parameter set is associated to the message and carry precisions. Thus, each key pair is entangled to precision.

The user is allowed to choose which set of parameters to use when creating the pair of keys.

The difference between the parameter sets is the total amount of space dedicated to the plaintext and how it is split between the message buffer and the carry buffer. The syntax chosen for the name of a parameter is: PARAM_MESSAGE_{number of message bits}_CARRY_{number of carry bits}. For example, the set of parameters for a message buffer of 5 bits and a carry buffer of 2 bits is PARAM_MESSAGE_5_CARRY_2.

The PARAM_MESSAGE_2_CARRY_2 parameter set is the default shortint parameter set that you can also use through the tfhe::shortint::prelude::DEFAULT_PARAMETERS constant.

use tfhe::shortint::prelude::*;

fn main() {
    // We generate a set of client/server keys, using the default parameters:
   let (client_key, server_key) = gen_keys(PARAM_MESSAGE_2_CARRY_2);

    let msg1 = 3;
    let msg2 = 2;

    // We use the client key to encrypt two messages:
    let ct_1 = client_key.encrypt(msg1);
    let ct_2 = client_key.encrypt(msg2);
}

Impact of parameters on the operations

As shown here, the choice of the parameter set impacts the operations available and their efficiency.

Generic bi-variate functions.

The computations of bi-variate functions is based on a trick: concatenating two ciphertexts into one. Where the carry buffer is not at least as large as the message one, this trick no longer works. Many bi-variate operations, such as comparisons, then cannot be correctly computed. The only exception concerns multiplication.

Multiplication.

In the case of multiplication, two algorithms are implemented: the first one relies on the bi-variate function trick, where the other one is based on the quarter square method. To correctly compute a multiplication, the only requirement is to have at least one bit of carry (i.e., using parameter sets PARAM_MESSAGE_X_CARRY_Y with Y>=1). This method is slower than using the other one. Using the smart version of the multiplication automatically chooses which algorithm is used depending on the chosen parameters.

User-defined parameter sets

It is possible to define new parameter sets. To do so, it is sufficient to use the function unsecure_parameters() or to manually fill the Parameter structure fields.

For instance:

use tfhe::shortint::prelude::*;

fn main() {
    let param = unsafe {
        Parameters::new(
            LweDimension(656),
            GlweDimension(2),
            PolynomialSize(512),
            StandardDev(0.000034119201269311964),
            StandardDev(0.00000004053919869756513),
            DecompositionBaseLog(8),
            DecompositionLevelCount(2),
            DecompositionBaseLog(3),
            DecompositionLevelCount(4),
            StandardDev(0.00000000037411618952047216),
            DecompositionBaseLog(15),
            DecompositionLevelCount(1),
            DecompositionLevelCount(0),
            DecompositionBaseLog(0),
            MessageModulus(4),
            CarryModulus(1),
            CiphertextModulus::new_native(),
        )
    };
}

Last updated