# CKKS RNS encoding

**URL:** <https://openfhe.discourse.group/t/ckks-rns-encoding/975>\
**Category:** Library Questions\
**Created:** [December 18, 2023, 3:18pm UTC](https://openfhe.discourse.group/t/ckks-rns-encoding/975 "2023-12-18T15:18:40Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![mmazz](https://avatars.discourse-cdn.com/v4/letter/m/50afbb/32.png) [@mmazz](https://openfhe.discourse.group/u/mmazz)\
**Post date:** [December 18, 2023, 3:18pm UTC](https://openfhe.discourse.group/t/ckks-rns-encoding/975/1 "2023-12-18T15:18:40Z")

</div>

Hello!

I having some trouble to understand how the encoding is in RNS representation and then how get encrypted.  
I get that the encoding is in DCRT.  
However when I want to get details of the theory, books like [On Architecting Fully Homomorphic Encryption-based Computing Systems](https://link.springer.com/book/10.1007/978-3-031-31754-5) or papers like [A Full RNS Variant of  
Approximate Homomorphic Encryption](https://eprint.iacr.org/2018/931.pdf), (if I understand correctly) it shows that they first encode the data and then in the encryption, they transforms it into an RNS representation.

For example in the paper appears that de encryption (page 11)

> Enc\_{pk}(m): For m ∈ R, sample v ← χ\_{enc} and e\_0, e\_1 ← χ\_{err}.  
> Output the ciphertext ct = (ct(j))\_ {0≤j≤L} ∈ \prod^L\_{j=0} R^2\_{q\_j} where ct^{(j)} ← v · pk^{(j)} + (m + e\_0, e\_1) (mod q\_j ) for 0 ≤ j ≤ L.

And if I’m correct, that m is not in RNS…

How can I see/learn how it is done in OpenFHE?

---

<div class="post-metadata">

**Author:** ![Caesar](https://yyz1.discourse-cdn.com/flex031/user_avatar/openfhe.discourse.group/caesar/32/63_2.png) [@Caesar](https://openfhe.discourse.group/u/Caesar)\
**Post date:** [December 19, 2023, 8:02pm UTC](https://openfhe.discourse.group/t/ckks-rns-encoding/975/2 "2023-12-19T20:02:23Z")

</div>

It does not matter what representation is m in. That equation describes polynomial modular arithmetic which can be done in several ways. But to do it efficiently in CPU, RNS and DCRT representations are the currently best-known approaches to use.

I suggest you review a reference on RNS arithmetic for integers and polynomials. This is mandatory to understand RNS and DCRT arithmetic in OpenFHE. After you understand the theory, you can study the DCRT [unittests](https://github.com/openfheorg/openfhe-development/blob/main/src/core/unittest/UnitTestDCRTElements.cpp#L285) in OpenFHE.

---

<div class="post-metadata">

**Author:** ![mmazz](https://avatars.discourse-cdn.com/v4/letter/m/50afbb/32.png) [@mmazz](https://openfhe.discourse.group/u/mmazz)\
**Post date:** [December 21, 2023, 3:26pm UTC](https://openfhe.discourse.group/t/ckks-rns-encoding/975/3 "2023-12-21T15:26:16Z")

</div>

I think I get it. However in my reasoning, I get that the RNS encryption are limb independent (something that I ask in other post), but when I test it in OpenFHE I get that are not independent. So I don’t know were I’m getting wrong.

Can you confirm my toy example?

Suppose that I have Q=105=q\_0\*q\_1\*q\_2 =7\*5\*3, and m=47+23X=(47, 23)  
So the RNS representation using \<7,5,3\> of each coefficient will be 47 = (5, 2, 2) and 23 = (2, 3, 2).  
And this will be represented as 3 polynomials, m\_0 = (5, 2), m\_1 = (2, 3) and m\_2 = (2, 2).

So when I want to encrypt this in a supper naive way (to only one polynomial and not two like CKKS), say adding to m the polynomial e=0+1X and the public key pk = 89 + 67X that in RNS is: pk\_0=(5, 4), pk\_1 = (4, 2) and pk\_2=(2, 1)

So doing c\_i = pk\_i + m + e \text{ mod } q\_i we have:  
\begin{align} c\_0&= pk\_0 + m + e \text{ mod } q\_0 = (5, 4) + (47, 23) + (0, 1) \text{ mod } 7 = (52, 28) \text{ mod } 7 = (3, 0)\\ c\_1& =pk\_1 + m + e \text{ mod } q\_1 = (4, 2) + (47, 23) + (0, 1) \text{ mod } 5 = (51, 26) \text{ mod } 5 = (1, 1) \\ c\_2& =pk\_2 + m + e \text{ mod } q\_2 = (2, 1) + (47, 23) + (0, 1) \text{ mod } 3 = (49, 25) \text{ mod } 3 = (1, 1) \end{align}

That is equivalent do this:  
\begin{align} c\_0&= pk\_0 + m\_0 + e \text{ mod } q\_0 = (5, 4) + (5, 2) + (0, 1) \text{ mod } 7 = (10, 7) \text{ mod } 7 =(3, 0)\\ c\_1& =pk\_1 + m\_1 + e \text{ mod } q\_1 = (4, 2) + (2, 3) + (0, 1) \text{ mod } 5 = (6, 6) \text{ mod } 5 = (1, 1)\\ c\_2& =pk\_2 + m\_2 + e \text{ mod } q\_2 = (2, 1) + (2, 2) + (0, 1) \text{ mod } 3 = (4, 4) \text{ mod } 3 = (1, 1) \end{align}

That is the same. So in a sense, the calculation of each limb of the encryption c\_i are only affected by the respective limb of the encoding m\_i, right?

---

<div class="post-metadata">

**Author:** ![ypolyakov](https://yyz1.discourse-cdn.com/flex031/user_avatar/openfhe.discourse.group/ypolyakov/32/47_2.png) [@ypolyakov](https://openfhe.discourse.group/u/ypolyakov)\
**Post date:** [December 22, 2023, 10:06pm UTC](https://openfhe.discourse.group/t/ckks-rns-encoding/975/4 "2023-12-22T22:06:34Z")

</div>

Yes, this is correct.
