Program Listing for File binfhe-base-scheme.h

↰ Return to documentation for file (binfhe/include/binfhe-base-scheme.h)

//==================================================================================
// BSD 2-Clause License
//
// Copyright (c) 2014-2026, NJIT, Duality Technologies Inc. and other contributors
//
// All rights reserved.
//
// Author TPOC: contact@openfhe.org
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==================================================================================

#ifndef SRC_BINFHE_INCLUDE_BINFHE_BASE_SCHEME_H_
#define SRC_BINFHE_INCLUDE_BINFHE_BASE_SCHEME_H_

#include <cstdint>
#include <cstdlib>
#include <map>
#include <memory>
#include <string>
#include <vector>

#include "binfhe-base-params.h"
#include "lwe-pke.h"
#include "rgsw-acc-cggi.h"
#include "rgsw-acc-dm.h"
#include "rgsw-acc-lmkcdey.h"
#include "rgsw-acc.h"
#include "rgsw-acckey.h"
#include "rgsw-acckey32.h"
#include "rlwe-ciphertext.h"

namespace lbcrypto {

struct RingGSWBTKey {
    RingGSWACCKey BSkey;
    LWESwitchingKey KSkey;
    LWEPublicKey Pkey;
#if NATIVEINT != 32
    RingGSWACCKey32 BSkey32;
    LWESwitchingKey32 KSkey32;
#endif

    bool HasRefreshKey() const {
#if NATIVEINT != 32
        return (BSkey != nullptr) || (BSkey32 != nullptr);
#else
        return BSkey != nullptr;
#endif
    }

    // Each key is written in whichever width the context holds it at, and the null members say
    // which that was, so the archive needs no separate discriminator.
    template <class Archive>
    void save(Archive& ar, std::uint32_t const version) const {
        ar(::cereal::make_nvp("bs", BSkey));
        ar(::cereal::make_nvp("ks", KSkey));
        ar(::cereal::make_nvp("pk", Pkey));
#if NATIVEINT != 32
        ar(::cereal::make_nvp("bs32", BSkey32));
        ar(::cereal::make_nvp("ks32", KSkey32));
#endif
    }

    template <class Archive>
    void load(Archive& ar, std::uint32_t const version) {
        if (version > SerializedVersion()) {
            OPENFHE_THROW("serialized object version " + std::to_string(version) +
                          " is from a later version of the library");
        }
        ar(::cereal::make_nvp("bs", BSkey));
        ar(::cereal::make_nvp("ks", KSkey));
        ar(::cereal::make_nvp("pk", Pkey));
#if NATIVEINT != 32
        ar(::cereal::make_nvp("bs32", BSkey32));
        ar(::cereal::make_nvp("ks32", KSkey32));
#endif
    }

    std::string SerializedObjectName() const {
        return "RingGSWBTKey";
    }

    static uint32_t SerializedVersion() {
        return 1;
    }
};

class BinFHEScheme {
  public:
    BinFHEScheme() = default;

    explicit BinFHEScheme(BINFHE_METHOD method) {
        if (method == AP)
            ACCscheme = std::make_shared<RingGSWAccumulatorDM>();
        else if (method == GINX)
            ACCscheme = std::make_shared<RingGSWAccumulatorCGGI>();
        else if (method == LMKCDEY)
            ACCscheme = std::make_shared<RingGSWAccumulatorLMKCDEY>();
        else
            OPENFHE_THROW("method is invalid");
    }

    RingGSWBTKey KeyGen(const std::shared_ptr<BinFHECryptoParams>& params, ConstLWEPrivateKey& LWEsk,
                        KEYGEN_MODE keygenMode, bool internal32) const;

    LWECiphertext EvalBinGate(const std::shared_ptr<BinFHECryptoParams>& params, BINGATE gate, const RingGSWBTKey& EK,
                              ConstLWECiphertext& ct1, ConstLWECiphertext& ct2, bool extended = false) const;

    LWECiphertext EvalBinGate(const std::shared_ptr<BinFHECryptoParams>& params, BINGATE gate, const RingGSWBTKey& EK,
                              const std::vector<LWECiphertext>& ctvector, bool extended = false) const;

    LWECiphertext EvalNOT(const std::shared_ptr<BinFHECryptoParams>& params, ConstLWECiphertext& ct) const;

    LWECiphertext Bootstrap(const std::shared_ptr<BinFHECryptoParams>& params, const RingGSWBTKey& EK,
                            ConstLWECiphertext& ct, bool extended = false) const;

    LWECiphertext EvalFunc(const std::shared_ptr<BinFHECryptoParams>& params, const RingGSWBTKey& EK,
                           ConstLWECiphertext& ct, const std::vector<NativeInteger>& LUT, NativeInteger beta) const;

    LWECiphertext EvalFloor(const std::shared_ptr<BinFHECryptoParams>& params, const RingGSWBTKey& EK,
                            ConstLWECiphertext& ct, NativeInteger beta, uint32_t roundbits = 0) const;

    LWECiphertext EvalSign(const std::shared_ptr<BinFHECryptoParams>& params,
                           const std::map<uint32_t, RingGSWBTKey>& EKs, ConstLWECiphertext& ct, NativeInteger beta,
                           bool schemeSwitch = false) const;

    std::vector<LWECiphertext> EvalDecomp(const std::shared_ptr<BinFHECryptoParams>& params,
                                          const std::map<uint32_t, RingGSWBTKey>& EKs, ConstLWECiphertext& ct,
                                          NativeInteger beta) const;

  private:
    RLWECiphertext BootstrapGateCore(const std::shared_ptr<BinFHECryptoParams>& params, BINGATE gate,
                                     const RingGSWBTKey& EK, ConstLWECiphertext& ct) const;

    // Arbitrary function evaluation purposes

    template <typename Func>
    RLWECiphertext BootstrapFuncCore(const std::shared_ptr<BinFHECryptoParams>& params, const RingGSWBTKey& EK,
                                     ConstLWECiphertext& ct, const Func f, NativeInteger fmod) const;

    template <typename Func>
    LWECiphertext BootstrapFunc(const std::shared_ptr<BinFHECryptoParams>& params, const RingGSWBTKey& EK,
                                ConstLWECiphertext& ct, const Func f, NativeInteger fmod) const;

    // dispatch to the key representation EK actually holds
    LWECiphertext SwitchCTtoqn(const std::shared_ptr<LWECryptoParams>& params, const RingGSWBTKey& EK,
                               ConstLWECiphertext& ct) const;

    LWECiphertext KeySwitch(const std::shared_ptr<LWECryptoParams>& params, const RingGSWBTKey& EK,
                            ConstLWECiphertext& ct) const;

  protected:
    std::shared_ptr<LWEEncryptionScheme> LWEscheme{std::make_shared<LWEEncryptionScheme>()};
    std::shared_ptr<RingGSWAccumulator> ACCscheme{nullptr};

    static uint32_t checkInputFunction(const std::vector<NativeInteger>& lut, NativeInteger mod) {
        size_t mid{lut.size() / 2};
        if (lut[0] == (mod - lut[mid])) {
            for (size_t i = 1; i < mid; ++i)
                if (lut[i] != (mod - lut[mid + i]))
                    return 2;
            return 0;
        }
        if (lut[0] == lut[mid]) {
            for (size_t i = 1; i < mid; ++i)
                if (lut[i] != lut[mid + i])
                    return 2;
            return 1;
        }
        return 2;
    }
};

}  // namespace lbcrypto

#endif  // SRC_BINFHE_INCLUDE_BINFHE_BASE_SCHEME_H_