# Can FHE be used for comparing 2 ciphertexts?

**URL:** <https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045>\
**Category:** FHE Questions\
**Created:** [January 26, 2024, 8:25pm UTC](https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045 "2024-01-26T20:25:32Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pavanranganath](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Pavanranganath](https://openfhe.discourse.group/u/Pavanranganath)\
**Post date:** [January 26, 2024, 8:25pm UTC](https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045/1 "2024-01-26T20:25:32Z")

</div>

Hi! I’m curious about using homomorphic encryption to compare two encrypted values, even if they were encrypted by different people. I’m new to these concepts, so any insights would be really helpful!

---

<div class="post-metadata">

**Author:** ![mchenu](https://avatars.discourse-cdn.com/v4/letter/m/ba9def/32.png) [@mchenu](https://openfhe.discourse.group/u/mchenu)\
**Post date:** [January 29, 2024, 12:55pm UTC](https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045/2 "2024-01-29T12:55:15Z")

</div>

Hi @Pavanranganath, as @Caesar kindly pointed out to me in a related question (see [Ciphertexts equality testing in CKKS](https://openfhe.discourse.group/t/ciphertexts-equality-testing-in-ckks/1033/1))

> [@Ciphertexts equality testing in CKKS](https://openfhe.discourse.group/t/ciphertexts-equality-testing-in-ckks/1033/2):
>
> Most existing FHE schemes, including CKKS, are semantically secure cryptoschemes, that is: given access to the ciphertexts only, negligible information about the plaintext can be deduced, such as message length.
> 
> In other words, a cryptoscheme is deemed semantically secure if it satisfies the following: “for any two messages of equal length, the ciphertexts produced by the encryption algorithm are indistinguishable by any efficient adversary”.
> 
> Also, note that CKKS encryption is probabilistic, that is, encrypting the same message twice does not generate the same ciphertext with a fairly large probability.
> 
> To compare encrypted messages, you will need to evaluate a comparison circuit homomorphically, and by definition, the result will also be encrypted. Thus, adversaries who do not own the secret key should not be able to learn the result of the comparison.

However if the ciphertexts are encrypted with the same public key, there are some comparison functions available. The result will be encrypted though.

I hope this helps.

---

<div class="post-metadata">

**Author:** ![Pavanranganath](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Pavanranganath](https://openfhe.discourse.group/u/Pavanranganath)\
**Post date:** [April 16, 2024, 11:31am UTC](https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045/3 "2024-04-16T11:31:39Z")

</div>

I’m attempting to convert ciphertext encrypted under the same public key from CKKS to TFHE, conduct comparisons using circuits, and then return the highest ciphertext back in CKKS format. However, I’m encountering an issue with performing gate operations between the output of EvalSign and EvalCKKStoFHEW because their moduli are different. Can someone please provide insight into this problem and help me resolve it?

```auto
def compareStmt(input1, input2):
    # Step 1: Setup CryptoContext for CKKS
    scTech = FIXEDAUTO
    multDepth = 17
    if scTech == FLEXIBLEAUTOEXT:
        multDepth += 1

    firstModSize = 60
    scaleModSize = 50
    ringDim = 8192
    sl = HEStd_NotSet
    slBin = TOY
    logQ_ccLWE = 23
    slots = 16 # sparsely-packed
    batchSize = slots

    parameters = CCParamsCKKSRNS()
    parameters.SetMultiplicativeDepth(multDepth)
    parameters.SetFirstModSize(firstModSize)
    parameters.SetScalingModSize(scaleModSize)
    parameters.SetScalingTechnique(scTech)
    parameters.SetSecurityLevel(sl)
    parameters.SetRingDim(ringDim)
    parameters.SetBatchSize(batchSize)

    cc = GenCryptoContext(parameters)

    # Enable the features that you wish to use
    cc.Enable(PKE)
    cc.Enable(KEYSWITCH)
    cc.Enable(LEVELEDSHE)
    cc.Enable(ADVANCEDSHE)
    cc.Enable(SCHEMESWITCH)

    print(
        f"CKKS scheme is using ring dimension {cc.GetRingDimension()},\n number of slots {slots}, and suports a multiplicative depth of {multDepth}\n"
    )

    # Generate encryption keys.
    keys = cc.KeyGen()

    # Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
    arbFunc = False
    FHEWparams = cc.EvalSchemeSwitchingSetup(
        sl, slBin, arbFunc, logQ_ccLWE, False, slots
    )

    ccLWE = FHEWparams[0]
    privateKeyFHEW = FHEWparams[1]

    cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW)

    # Generate bootstrapping key for EvalFloor
    ccLWE.BTKeyGen(privateKeyFHEW)

    print(
        f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n"
    )

    # Set the scaling factor to be able to decrypt; the LWE mod switch is performed on the ciphertext at the last level
    modulus_CKKS_from = cc.GetModulusCKKS()
    pLWE1 = ccLWE.GetMaxPlaintextSpace()
    modulus_LWE = 1 << logQ_ccLWE
    beta = ccLWE.GetBeta()
    pLWE = int(modulus_LWE / (2 * beta)) # Large precision

    scFactor = cc.GetScalingFactorReal(0)
    if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
        scFactor = cc.GetScalingFactorReal(1)
    scaleCF = int(modulus_CKKS_from) / (scFactor * pLWE)

    cc.EvalCKKStoFHEWPrecompute(scaleCF)

    # Step 3: Encoding and encryption of inputs
    x1 = [input1]
    x2 = [input2]
    encodedLength1 = len(x1)
    encodedLength2 = len(x2)

    # Encoding as plaintexts
    ptxt1 = cc.MakeCKKSPackedPlaintext(x1, 1, 0) # , None)
    ptxt2 = cc.MakeCKKSPackedPlaintext(x2, 1, 0) # , None)

    # Encrypt the encoded vectors
    c1 = cc.Encrypt(keys.publicKey, ptxt1)
    c2 = cc.Encrypt(keys.publicKey, ptxt2)

    # Step 4: Scheme switching from CKKS to FHEW
    cTemp1 = cc.EvalCKKStoFHEW(c1, encodedLength1)
    cTemp2 = cc.EvalCKKStoFHEW(c2, encodedLength2)
    # Step 5: Evaluate the floor function
    bits = 2
    print(
        f"\n---Decrypting switched ciphertext 1 with large precision (plaintext modulus {pLWE}) ---\n"
    )
    ptxt1.SetLength(encodedLength1)
    print(f"Input x2: {ptxt1.GetRealPackedValue()}")
    decryptLWECipherText(ccLWE, privateKeyFHEW, pLWE1, pLWE, cTemp1)

    print(
        f"\n---Decrypting switched ciphertext 2 with large precision (plaintext modulus {pLWE}) ---\n"
    )
    ptxt2.SetLength(encodedLength2)
    print(f"Input x2: {ptxt2.GetRealPackedValue()}")
    decryptLWECipherText(ccLWE, privateKeyFHEW, pLWE1, pLWE, cTemp2)

    comparator_result = comparator(cc, ccLWE, c1, c2)
    LWESign = comparator_result.get("LWESign")
    LWECiphertexts = comparator_result.get("LWECiphertexts")

    print(
        f"\n---Decrypting switched comparator_result with large precision (plaintext modulus {pLWE}) ---\n"
    )
    # ptxt2.SetLength(encodedLength2)
    # print(f"Output comparator_result: {ptxt2.GetRealPackedValue()}")
    decryptLWECipherText(ccLWE, privateKeyFHEW, pLWE1, pLWE, LWECiphertexts)

    fheSignNot = [ccLWE.EvalNOT(LWESign[i]) for i in range(len(LWESign))]
    print("EvalSign: ", "")
    for i in range(len(LWESign)):
        LWESignplainLWE = ccLWE.Decrypt(privateKeyFHEW, LWESign[i], 2)
        print(LWESignplainLWE, end=" ")
    print()
    print("EvalNOT: ", "")
    for i in range(len(fheSignNot)):
        plainLWE = ccLWE.Decrypt(privateKeyFHEW, fheSignNot[i], 2)
        print(plainLWE, end=" ")
    print()
    e_a1_result = [
        ccLWE.EvalBinGate(AND, cTemp1[i], LWESign[i]) for i in range(len(cTemp1))
    ]
    e_b1_result = [
        ccLWE.EvalBinGate(AND, fheSignNot[i], cTemp2[i]) for i in range(len(cTemp2))
    ]
    larger_num_circuit_result = [
        ccLWE.EvalBinGate(XOR, e_a1_result[i], e_b1_result[i])
        for i in range(len(e_b1_result))
    ]

    e_a2_result = [
        ccLWE.EvalBinGate(AND, cTemp1[i], fheSignNot[i]) for i in range(len(cTemp1))
    ]
    e_b2_result = [
        ccLWE.EvalBinGate(AND, LWESign[i], cTemp2[i]) for i in range(len(cTemp2))
    ]
    smaller_num_circuit_result = [
        ccLWE.EvalBinGate(XOR, e_a2_result[i], e_b2_result[i])
        for i in range(len(e_b2_result))
    ]
    print(
        f"\nFHEW decryption larger_num_circuit_result p = {pLWE}/(1 << bits) = {pLWE // (1 << bits)}: ",
        end="",
    )
    decryptLWECipherText(ccLWE, privateKeyFHEW, pLWE1, pLWE, larger_num_circuit_result)

    print(
        f"\nFHEW decryption smaller_num_circuit_result p = {pLWE}/(1 << bits) = {pLWE // (1 << bits)}: ",
        end="",
    )
    decryptLWECipherText(ccLWE, privateKeyFHEW, pLWE1, pLWE, smaller_num_circuit_result)

    # Step 6: Scheme switching from FHEW to CKKS
    cTemp2_cc = cc.EvalFHEWtoCKKS(
        larger_num_circuit_result,
        slots,
        slots,
    )

    plaintextDec2 = cc.Decrypt(keys.secretKey, cTemp2_cc)
    plaintextDec2.SetLength(slots)
    print(
        f"larger_num_circuit_result decryption modulus_LWE mod {pLWE // (1 << bits)}: {plaintextDec2}"
    )

    cTemp1_cc = cc.EvalFHEWtoCKKS(
        smaller_num_circuit_result,
        slots,
        slots,
    )

    plaintextDec2 = cc.Decrypt(keys.secretKey, cTemp1_cc)
    plaintextDec2.SetLength(slots)
    print(
        f"smaller_num_circuit_result decryption modulus_LWE mod {pLWE // (1 << bits)}: {plaintextDec2}"
    )

def decryptLWECipherText(ccLWE, privateKeyFHEW, pLWE1, pLWE, LWECiphertexts):
    print("FHEW Decryption")
    for j in range(len(LWECiphertexts)):
        # Decompose the large ciphertext into small ciphertexts that fit in q
        decomp = ccLWE.EvalDecomp(LWECiphertexts[j])

    # Decryption
    p = ccLWE.GetMaxPlaintextSpace()
    for i in range(len(decomp)):
        ct = decomp[i]
        if i == len(decomp) - 1:
            p = int(pLWE / (pLWE1 ** floor(log(pLWE) / log(pLWE1))))
            # The last digit should be up to P / p^floor(log_p(P))
        resultDecomp = ccLWE.Decrypt(privateKeyFHEW, ct, p)
        print(f"( {resultDecomp} * {pLWE1} ^ {i} )")
        if i != len(decomp) - 1:
            print("+", end=" ")
    print("\n")

def comparator(cc, ccLWE, ct1, ct2):
    # Compute the difference between the two ciphertexts
    cDiff = cc.EvalSub(ct1, ct2)

    # Convert the difference to the FHEW scheme
    LWECiphertexts = cc.EvalCKKStoFHEW(cDiff, 1)

    # Compute the sign of each element in LWECiphertexts
    LWESign = [None] * len(LWECiphertexts)
    for i in range(len(LWECiphertexts)):
        LWESign[i] = ccLWE.EvalSign(LWECiphertexts[i], True)

    # Return the signs and the ciphertexts
    return {"LWESign": LWESign, "LWECiphertexts": LWECiphertexts}

```

 ![Screenshot 2024-04-16 at 4.54.00 PM](https://canada1.discourse-cdn.com/flex031/uploads/openfhe/original/1X/bbd3c81f290e7d05943ec6e06aa501bbf1524cbf.png)

---

<div class="post-metadata">

**Author:** ![andreea.alexandru](https://yyz1.discourse-cdn.com/flex031/user_avatar/openfhe.discourse.group/andreea.alexandru/32/378_2.png) [@andreea.alexandru](https://openfhe.discourse.group/u/andreea.alexandru)\
**Post date:** [April 16, 2024, 2:29pm UTC](https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045/4 "2024-04-16T14:29:24Z")

</div>

Can you isolate the exception from “However, I’m encountering an issue with performing gate operations between the output of EvalSign and EvalCKKStoFHEW because their moduli are different”? Where exactly is it thrown? Can you provide a smaller example (a simpler circuit where you just convert a CKKS ciphertext into a FHEW ciphertext then apply a binary gate) which reproduces the error that can be copied and run as is?

On a different note, do you have a particular need to use Boolean circuits for this? If I understand correctly what you need to output, i.e., a ciphertext consisting of the largest elements between the two inputs, and a ciphertext consisting of the smallest elements between the two inputs, then you can do it only in CKKS after computing EvalCompareSchemeSwitching. Let sign = EvalCompareSchemeSwitching(input1,input2). Then larger = (1-sign) \* input1 + sign \* input2, and smaller = (1-sign) \* input2 + sign \* input 1.

---

<div class="post-metadata">

**Author:** ![Pavanranganath](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Pavanranganath](https://openfhe.discourse.group/u/Pavanranganath)\
**Post date:** [April 16, 2024, 4:39pm UTC](https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045/5 "2024-04-16T16:39:02Z")

</div>

I am getting Error

> ModAddEq called on NativeVectorT’s with different parameters when ` ccLWE.EvalBinGate(AND, cTemp1[i], LWESign[i]) for i in range(len(cTemp1))` gets executed

I have tried to make it simple code as possible :

```auto
from lib.openfhe import *
from math import log2, floor, log

def compareStmt():
    # Step 1: Setup CryptoContext for CKKS
    scTech = FIXEDAUTO
    multDepth = 17
    if scTech == FLEXIBLEAUTOEXT:
        multDepth += 1

    firstModSize = 60
    scaleModSize = 50
    ringDim = 8192
    sl = HEStd_NotSet
    slBin = TOY
    logQ_ccLWE = 23
    slots = 16 # sparsely-packed
    batchSize = slots

    parameters = CCParamsCKKSRNS()
    parameters.SetMultiplicativeDepth(multDepth)
    parameters.SetFirstModSize(firstModSize)
    parameters.SetScalingModSize(scaleModSize)
    parameters.SetScalingTechnique(scTech)
    parameters.SetSecurityLevel(sl)
    parameters.SetRingDim(ringDim)
    parameters.SetBatchSize(batchSize)

    cc = GenCryptoContext(parameters)

    # Enable the features that you wish to use
    cc.Enable(PKE)
    cc.Enable(KEYSWITCH)
    cc.Enable(LEVELEDSHE)
    cc.Enable(ADVANCEDSHE)
    cc.Enable(SCHEMESWITCH)

    print(
        f"CKKS scheme is using ring dimension {cc.GetRingDimension()},\n number of slots {slots}, and suports a multiplicative depth of {multDepth}\n"
    )

    # Generate encryption keys.
    keys = cc.KeyGen()

    # Step 2: Prepare the FHEW cryptocontext and keys for FHEW and scheme switching
    arbFunc = False
    FHEWparams = cc.EvalSchemeSwitchingSetup(
        sl, slBin, arbFunc, logQ_ccLWE, False, slots
    )

    ccLWE = FHEWparams[0]
    privateKeyFHEW = FHEWparams[1]

    cc.EvalSchemeSwitchingKeyGen(keys, privateKeyFHEW, 1)

    # Generate bootstrapping key for EvalFloor
    ccLWE.BTKeyGen(privateKeyFHEW)

    print(
        f"FHEW scheme is using lattice parameter {ccLWE.Getn()},\n logQ {logQ_ccLWE},\n and modulus q {ccLWE.Getq()}\n"
    )

    # Set the scaling factor to be able to decrypt; the LWE mod switch is performed on the ciphertext at the last level
    modulus_CKKS_from = cc.GetModulusCKKS()
    modulus_LWE = 1 << logQ_ccLWE
    beta = ccLWE.GetBeta()
    pLWE = int(modulus_LWE / (2 * beta)) # Large precision

    scFactor = cc.GetScalingFactorReal(0)
    if cc.GetScalingTechnique() == FLEXIBLEAUTOEXT:
        scFactor = cc.GetScalingFactorReal(1)
    scaleCF = int(modulus_CKKS_from) / (scFactor * pLWE)

    cc.EvalCKKStoFHEWPrecompute(scaleCF)

    # Step 3: Encoding and encryption of inputs
    x1 = [100]
    x2 = [8]
    encodedLength1 = len(x1)

    # Encoding as plaintexts
    ptxt1 = cc.MakeCKKSPackedPlaintext(x1, 1, 0) # , None)
    ptxt2 = cc.MakeCKKSPackedPlaintext(x2, 1, 0) # , None)

    # Encrypt the encoded vectors
    c1 = cc.Encrypt(keys.publicKey, ptxt1)
    c2 = cc.Encrypt(keys.publicKey, ptxt2)

    # Step 4: Scheme switching from CKKS to FHEW
    cTemp1 = cc.EvalCKKStoFHEW(c1, encodedLength1)

    # Compute the difference between the two ciphertexts
    cDiff = cc.EvalSub(c1, c2)

    # Convert the difference to the FHEW scheme
    LWECiphertexts = cc.EvalCKKStoFHEW(cDiff, 1)

    # Compute the sign of each element in LWECiphertexts
    LWESign = [None] * len(LWECiphertexts)
    for i in range(len(LWECiphertexts)):
        LWESign[i] = ccLWE.EvalSign(LWECiphertexts[i], False)

    e_a1_result = [
        ccLWE.EvalBinGate(AND, cTemp1[i], LWESign[i]) for i in range(len(cTemp1))
    ]
    # Error: ModAddEq called on NativeVectorT's with different parameters.
if __name__ == " __main__":
    compareStmt()

```

---

<div class="post-metadata">

**Author:** ![andreea.alexandru](https://yyz1.discourse-cdn.com/flex031/user_avatar/openfhe.discourse.group/andreea.alexandru/32/378_2.png) [@andreea.alexandru](https://openfhe.discourse.group/u/andreea.alexandru)\
**Post date:** [April 16, 2024, 5:29pm UTC](https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045/6 "2024-04-16T17:29:19Z")

</div>

Ok, I see the issue. EvalCKKStoFHEW returns LWE ciphertexts with a large modulus, in order to support large-precision operations, such as EvalSign. However, the EvalSign returns an LWE ciphertext with a smaller modulus. If you want to perform further operations between the output of EvalCKKStoFHEW (LWECiphertexts) and the output of EvalSign (LWESign), you need to do modulus switching for the LWECiphertexts from their larger modulus to the smaller modulus of LWESign. You can take a look [here](https://github.com/openfheorg/openfhe-development/blob/main/src/pke/lib/scheme/ckksrns/ckksrns-schemeswitching.cpp#L1422) for inspiration on how to do this.

---

<div class="post-metadata">

**Author:** ![Pavanranganath](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Pavanranganath](https://openfhe.discourse.group/u/Pavanranganath)\
**Post date:** [April 16, 2024, 6:31pm UTC](https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045/7 "2024-04-16T18:31:30Z")

</div>

Appreciate your response. In my setup, the modulus for `EvalSign` is 4096, while for `LWECiphertexts` it’s 8388608. I examined the C++ code you referenced, but since I’m working in Python, some of the methods used there aren’t accessible in current Python wrapper. It seems like achieving this in Python might be challenging. If you have any alternative approaches in mind, I’m all ears. Let me know if you have any suggestions.

---

<div class="post-metadata">

**Author:** ![Pavanranganath](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Pavanranganath](https://openfhe.discourse.group/u/Pavanranganath)\
**Post date:** [April 17, 2024, 6:36pm UTC](https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045/8 "2024-04-17T18:36:37Z")

</div>

As per your suggestion i added this code in core library so i can change the modulus from higher to lower

```auto
std::vector<std::shared_ptr<LWECiphertextImpl>> SWITCHCKKSRNS::EvalFHEWChangeModulus(
    std::vector<lbcrypto::LWECiphertext> LWEciphertexts, uint32_t fromModulus, uint32_t toModulus,uint32_t numCtxts) {
        NativeInteger native_fromModulus(fromModulus);
        NativeInteger native_toModulus(toModulus);
        uint32_t n = m_ccLWE.GetParams()->GetLWEParams()->Getn(); // lattice parameter for additive LWE
#pragma omp parallel for
    for (uint32_t i = 0; i < numCtxts; i++) {
        auto original_a = LWEciphertexts[i]->GetA();
        auto original_b = LWEciphertexts[i]->GetB();
        // multiply by Q_LWE/Q' and round to Q_LWE
        NativeVector a_round(n, toModulus);
        for (uint32_t j = 0; j < n; ++j) {
            a_round[j] = RoundqQAlter(original_a[j], native_toModulus, native_fromModulus);
        }
        NativeInteger b_round = RoundqQAlter(original_b, native_toModulus, native_fromModulus);
        LWEciphertexts[i] = std::make_shared<LWECiphertextImpl>(std::move(a_round), std::move(b_round));
    }

    return LWEciphertexts;
}

```

i added this in python wrapper

```auto
.def("EvalFHEWChangeModulus", &CryptoContextImpl<DCRTPoly>::EvalFHEWChangeModulus,
             cc_EvalCKKStoFHEW_docs,
             py::arg("LWEciphertexts"),
             py::arg("fromModulus"),
             py::arg("toModulus"),
             py::arg("numCtxts") = 0)

```

I was able to execute

```auto
    cTemp1_new = cc.EvalFHEWChangeModulus(cTemp1,cTemp1[0].GetModulus(),LWESign[0].GetModulus(),len(cTemp1))

e_a1_result = [
        ccLWE.EvalBinGate(AND, cTemp1_new[i], LWESign[i]) for i in range(len(cTemp1))
    ]

```

I am not getting any errors

But i am getting incorrect outputs.

can someone please help me with this

---

<div class="post-metadata">

**Author:** ![Pavanranganath](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Pavanranganath](https://openfhe.discourse.group/u/Pavanranganath)\
**Post date:** [April 18, 2024, 3:54pm UTC](https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045/9 "2024-04-18T15:54:51Z")

</div>

> [@andreea.alexandru](#):
>
> a ciphertext consisting of the largest elements between the two inputs, and a ciphertext consisting of the smallest elements between the two inputs, then you can do it only in CKKS after computing EvalCompareSchemeSwitching. Let sign = EvalCompareSchemeSwitching(input1,input2). Then larger = (1-sign) \* input1 + sign \* input2, and smaller = (1-sign) \* input2 + sign \* input 1.

```auto
    x1=[input1]
    x2=[input2]
    encodedLengthx1 = len(x1)
    ptxt1 = cc.MakeCKKSPackedPlaintext(x1, 1, 0, None, slots)
    ptxt2 = cc.MakeCKKSPackedPlaintext(x2, 1, 0, None, slots)

    c1 = cc.Encrypt(keys.publicKey, ptxt1)
    c2 = cc.Encrypt(keys.publicKey, ptxt2)
    cResult = cc.EvalCompareSchemeSwitching(c1, c2, slots, 0, scaleSignFHEW)

    one_minus_cResult = cc.EvalSub(1, cResult)
    # larger = (1-sign) * input1 + sign * input2
    larger = cc.EvalAdd(cc.EvalMult(one_minus_cResult, c1), cc.EvalMult(cResult, c2))
    # smaller = (1-sign) * input2 + sign * input 1.
    smaller = cc.EvalAdd(cc.EvalMult(one_minus_cResult, c2), cc.EvalMult(cResult, c1))

    largerPlaintext = cc.Decrypt(keys.secretKey, larger)
    largerPlaintext.SetLength(encodedLengthx1)
    print(f"Decrypted larger result: {largerPlaintext}\n")

    smallerPlaintext = cc.Decrypt(keys.secretKey, smaller)
    smallerPlaintext.SetLength(encodedLengthx1)
    print(f"Decrypted smaller result: {smallerPlaintext}\n")

```

i tried your way of calculating  
when i pass

> input1 = 40 input2 = 8 , largerPlaintext = 40 and smallerPlaintext = 8

> input1 = 8 input2 = 40 , largerPlaintext = 8 and smallerPlaintext = 40

can you see help me with this

---

<div class="post-metadata">

**Author:** ![andreea.alexandru](https://yyz1.discourse-cdn.com/flex031/user_avatar/openfhe.discourse.group/andreea.alexandru/32/378_2.png) [@andreea.alexandru](https://openfhe.discourse.group/u/andreea.alexandru)\
**Post date:** [April 18, 2024, 4:15pm UTC](https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045/10 "2024-04-18T16:15:49Z")

</div>

First question: please read more on the FHEW/TFHE scheme to understand the message scaling and more on the [scheme switching functionality](https://github.com/openfheorg/openfhe-development/blob/main/src/pke/examples/SCHEME_SWITCHING_CAPABILITY.md) to understand how the message is scaled there. An LWE valid encryption will have the message scaled by q/p. The scheme switching is designed to switch from a larger value in CKKS to its corresponding value in LWE, with a large p and a large q to support this large precision. The implemented function EvalSign returns a message scaled with a small p’=2 and q’. The Boolean gates are also currently implemented for small p’ and q’. This value of p’ cannot support the large input you want to perform AND with. You can only obtain correctness if the two LWE ciphertexts you want to operate with have the same scaling and the output is supported in the given plaintext size.

That’s why you should focus on the CKKS-based solution.  
Second question: Based on the code, you don’t seem to be running with the latest version. I ran it with the latest version and I get the correct result regardless of the order, so I could not reproduce your issue.

---

<div class="post-metadata">

**Author:** ![Pavanranganath](https://avatars.discourse-cdn.com/v4/letter/p/ec9cab/32.png) [@Pavanranganath](https://openfhe.discourse.group/u/Pavanranganath)\
**Post date:** [April 18, 2024, 6:08pm UTC](https://openfhe.discourse.group/t/can-fhe-be-used-for-comparing-2-ciphertexts/1045/11 "2024-04-18T18:08:16Z")

</div>

> [@andreea.alexandru](#):
>
> Second question: Based on the code, you don’t seem to be running with the latest version. I ran it with the latest version and I get the correct result regardless of the order, so I could not reproduce your issue.

Thank you soo much for responding  
As you said i had older version, i updated to the latest version and made some changes in the code as per new version and changed the code

> ```
> cResult = cc.EvalCompareSchemeSwitching(c1, c2, slots,slots,pLWE2)
> 
> ```

now i am getting proper results

Thank you
