I am trying to get a sense of how big FHE ciphertext is under a range of different conditions. I have edited some of the examples to print the CiphertextImpl type and I see (for example in the PKE tree) I get and output of the form:
Cyphertext #1: enc=PACKED_ENCODING noiseScaleDeg=<integer>
metadata: [ ]
Element 0: 0: EVAL: [ <vector of big unsigned integers> ] modulus: <big unsigned integer>
1: EVAL: [ <vector of big unsigned integers> ] modulus: <big unsigned integer>
2: EVAL: [ <vector of big unsigned integers> ] modulus: <big unsigned integer>
Element 1: 0: EVAL: [ <vector of big unsigned integers> ] modulus: <big unsigned integer>
1: EVAL: [ <vector of big unsigned integers> ] modulus: <big unsigned integer>
2: EVAL: [ <vector of big unsigned integers> ] modulus: <big unsigned integer>
I am a bit confused as to what the two Elements (Element 0 and Element 1) are. And I am also confused as to why there are 3 EVAL vectors per Element (0, 1 and 2). Can someone explain what I am looking at here and if all these arrays are needed to represent the Ciphertext?
Ultimately what I am trying to obtain is the size (in Bytes) of a given ciphertext object. Is there a member function or method to determine that?
Apologies in advance if this question has been answerted elsewhere in the forum.
I’ll answer the ultimate question. Let me know if you still want to know what the data structure of ciphertext is.
The best approach is to serialize the ciphertext to the hard disk and measure the file size to get the ciphertext size in bytes.
Here is an example of how to serialize a ciphertext to a file.
Alternatively, if you know the crypto parameters (ring dimension N and ciphertext coefficient modulus Q), then the ciphertext size can be calculated via the following formula:
size(bits) = 2 \cdot N \cdot \log_2{Q}.
One thing to note is that some internal FHE operations expand the ciphertext internally. Similarly, some operations shrink it as you compute on it. The formula above captures the ciphertext size at the input level (level 0).
Thanks so much for this useful information. I took at look at the -serial example and that makes sense. I would still like to understand the structure of the ciphertext object so I can understand why there are multiple vectors (in my case above 6) and not just one vector.
Sure. I’ll assume you are working with an RLWE-based scheme such as BFV, BGV, or CKKS.
An RLWE ciphertext consists of two elements (Element 0 and Element 1) - basically polynomials. Each of these two polynomials is represented by a k \times N matrix - via the Chinese Remainder Theorem (CRT) or DoubleCRT (DCRT). N is known as the ring dimension and any of those polynomials will have a degree of \lt N, whereas k \approx \lceil \log_2{}Q / average(\log_2{}modulus_i) \rceil is the number of levels in the ciphertext. The small moduli modulus_i are prime numbers that fit in the underlying machine word size, either 64- or 128-bit integers.
The label EVAL above designates that the polynomials are represented in the evaluation form. The other potential format is COEFF which designates coefficient representation.
Each of the elements above is called a DCRTPoly. For more info on DCRTPoly, please refer to this thread.