栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

SEAL开源库源码05

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SEAL开源库源码05

SEAL开源库源码05

文章目录
  • SEAL开源库源码05
  • seal/dynarray.h
    • 一些声明
    • DynArray 类,位于 namespace seal 中
      • 类说明
      • 声明友元类
      • 定义别名
      • 构造函数,不分配空间
      • 给定 size 的构造函数,调用 resize 函数
      • 给定 capacity 和 size 的构造函数,调用 reserve(预留) 和 resize 函数
      • 包装指针的构造函数
      • 构造函数, initialized with data from a given buffer.
      • 拷贝构造和移动构造
      • 析构函数
      • begin 函数,返回指向第一个元素的指针
      • begin函数 和 cbegin 函数,返回指向第一个元素的常量指针
      • end 函数,返回指向最后一个元素的指针,跟 begin 类似
      • gsl span
      • at 函数,两个版本
      • [ ] 运算符,跟 at 函数差不多
      • empty 函数,判断是否为空
      • max_size 函数,返回数组可能的最大size
      • size 函数,返回此时数组的大小
      • capacity 函数
      • pool 函数
      • release 函数,把内存还给 memory pool
      • clear 函数
      • reserve 函数
      • shrink_to_fit 函数
      • resize 函数
      • 赋值运算符
      • save_size 函数
      • save 和 load 函数
      • save_members 和 load_members 函数,私有
      • 私有成员
  • seal/randomgen.h
    • 定义两个常量和一个别名
    • prng_type 枚举类型,用于确定使用哪种伪随机数生成器
    • random_bytes 函数
    • random_uint64 函数
    • UniformRandomGeneratorInfo 类
      • 声明友元类
      • 构造函数
      • 赋值运算符
      • 比较运算符
      • clear 函数,清除数据
      • 析构函数,调用 clear 函数
      • make_prng 函数,生成一个伪随机数生成器
      • has_valid_prng_type 函数
      • type 函数
      • seed 函数
      • save_size 函数
      • save 和 load 函数
      • 成员变量
    • UniformRandomGenerator 类
      • 类说明
      • 构造函数
      • seed 函数,返回种子的副本
      • generate 函数,生成一组伪随机数
      • generate 函数,生成一个32-bit伪随机数
      • refresh 函数,重新生成一组伪随机数,调用 refill_buffer 函数
      • info 函数,返回信息的副本
      • 析构函数
      • 成员变量
    • UniformRandomGeneratorFactory 类
      • 类说明
      • 构造函数
      • create 函数,创建新的伪随机数生成器
      • 析构函数
      • static DefaultFactory 函数,返回默认的 random number generator factory
      • use_random_seed 函数,判断是否使用随机的种子
      • create_impl 函数,protected
      • private 成员
    • Blake2xbPRNG 类
    • Blake2xbPRNGFactory 类
    • Shake256PRNG 类
    • Shake256PRNGFactory 类
  • seal/randomgen.cpp
      • random_bytes 实现
      • UniformRandomGeneratorInfo::save_members 实现
      • UniformRandomGeneratorInfo::load_members 实现
      • UniformRandomGeneratorInfo::make_prng() 实现
      • UniformRandomGenerator::generate 实现
      • UniformRandomGeneratorFactory::DefaultFactory() -> shared_ptr< UniformRandomGeneratorFactory > 实现
      • Blake2xbPRNG::refill_buffer 实现
      • Shake256PRNG::refill_buffer 函数实现
  • seal/util/hash.h
    • HashFunction 类
  • seal/util/hash.cpp
  • seal/encryptionparameters.h
    • scheme_type 枚举
    • 别名
    • EncryptionParameters 类
      • 类说明
      • 声明友元结构体
      • private 成员
        • 包括加密方案,多项式模的次数,明文模数,多项式系数的模数,伪随机数生成器工厂,哈希值
      • 构造函数,调用 compute_parms_id 函数
      • 赋值运算符
      • set_poly_modulus_degree 函数
      • set_coeff_modulus 函数
      • set_plain_modulus 函数
      • set_random_generator 函数
      • 一些 getter 函数
      • 比较运算
      • save_size,save,load 函数
      • compute_parms_id 函数实现
    • std::hash 特化

最终目的要分析 seal/encryptionparams.h

seal/dynarray.h

引用的头文件

#include "seal/memorymanager.h"
#include "seal/serialization.h"
#include "seal/version.h"
#include "seal/util/common.h"
#include "seal/util/defines.h"
#include "seal/util/pointer.h"
#include 
#include 
#include 
#include 
#ifdef SEAL_USE_MSGSL
#include "gsl/span"
#endif
一些声明
namespace seal
{
    class Ciphertext;

    // Forward-declaring the deflate_size_bound function
    namespace util
    {
        namespace ztools
        {
            template 
            SEAL_NODISCARD SizeT deflate_size_bound(SizeT in_size);
        } // namespace ztools
    } // namespace util
DynArray 类,位于 namespace seal 中 类说明
 

一个动态数组,用于存储从Microsoft SEAL内存池分配的对象。DynArray类主要用于内部使用,并为明文和密文类提供底层数据结构。

@par大小和容量
DynArray允许用户为数组预分配内存(容量),在数组已知将在未来调整大小的情况下,并在调整大小时避免内存移动。DynArray的大小永远不能超过它的容量。容量和大小可以分别使用reserve和resize函数进行更改。

@par线程安全
一般来说,从DynArray读取数据是线程安全的,只要没有其他线程并发地修改它。

声明友元类
    template 
    class DynArray
    {
        friend class Ciphertext;
定义别名
    public:
        using type = T;

构造函数,不分配空间
        
        DynArray(MemoryPoolHandle pool = MemoryManager::GetPool()) : pool_(std::move(pool))  // 默认参数是default
        {
            if (!pool_)
            {
                throw std::invalid_argument("pool is uninitialized");
            }
        }
给定 size 的构造函数,调用 resize 函数
        
        explicit DynArray(std::size_t size, MemoryPoolHandle pool = MemoryManager::GetPool()) : pool_(std::move(pool))
        {
            if (!pool_)
            {
                throw std::invalid_argument("pool is uninitialized");
            }

            // Reserve memory, resize, and set to zero
            resize(size);
        }
给定 capacity 和 size 的构造函数,调用 reserve(预留) 和 resize 函数
        
        explicit DynArray(std::size_t capacity, std::size_t size, MemoryPoolHandle pool = MemoryManager::GetPool())
            : pool_(std::move(pool))
        {
            if (!pool_)
            {
                throw std::invalid_argument("pool is uninitialized");
            }
            if (capacity < size)
            {
                throw std::invalid_argument("capacity cannot be smaller than size");
            }

            // Reserve memory, resize, and set to zero
            reserve(capacity);
            resize(size);
        }
包装指针的构造函数

创建一个给定大小的新DynArray包装给定的指针。这个构造函数不分配内存。如果DynArray超出作用域,这里给出的指针对象将被销毁。在调整DynArray的大小到更大的大小,数据将被复制到一个新的分配内存池指针由给定的MemoryPoolHandle和这里给出的指针对象随后将被销毁。与其他构造函数不同,这个构造函数提供了不自动填充已分配内存的选项。

        
        explicit DynArray(
            util::Pointer &&ptr, std::size_t capacity, std::size_t size, bool fill_zero,
            MemoryPoolHandle pool = MemoryManager::GetPool())
            : pool_(std::move(pool)), capacity_(capacity)
        {
            if (!ptr && capacity)
            {
                throw std::invalid_argument("ptr cannot be null");
            }
            if (!pool_)
            {
                throw std::invalid_argument("pool is uninitialized");
            }
            if (capacity < size)
            {
                throw std::invalid_argument("capacity cannot be smaller than size");
            }

            // Grab the given Pointer
            data_ = std::move(ptr);

            // Resize, and optionally set to zero
            resize(size, fill_zero);
        }

        
        explicit DynArray(
            util::Pointer &&ptr, std::size_t size, bool fill_zero, MemoryPoolHandle pool = MemoryManager::GetPool())
            : DynArray(std::move(ptr), size, size, fill_zero, std::move(pool))
        {}
构造函数, initialized with data from a given buffer.
#ifdef SEAL_USE_MSGSL
        
        explicit DynArray(
            gsl::span values, std::size_t capacity, MemoryPoolHandle pool = MemoryManager::GetPool())
            : DynArray(capacity, values.size(), std::move(pool))
        {
            std::copy(values.begin(), values.end(), data_.get());
        }

        
        explicit DynArray(gsl::span values, MemoryPoolHandle pool = MemoryManager::GetPool())
            : DynArray(values, values.size(), std::move(pool))
        {}
#endif
拷贝构造和移动构造
        
        DynArray(const DynArray ©)
            : pool_(MemoryManager::GetPool()), capacity_(copy.size_), size_(copy.size_),
              data_(util::allocate(copy.size_, pool_))
        {
            // Copy over value
            std::copy(copy.cbegin(), copy.cend(), begin());
        }

        
        DynArray(DynArray &&source) noexcept
            : pool_(std::move(source.pool_)), capacity_(source.capacity_), size_(source.size_),
              data_(std::move(source.data_))
        {}
析构函数
        
        ~DynArray()
        {
            release();
        }
begin 函数,返回指向第一个元素的指针
        
        SEAL_NODISCARD inline T *begin() noexcept
        {
            return data_.get();
        }
begin函数 和 cbegin 函数,返回指向第一个元素的常量指针

常量指针

        
        SEAL_NODISCARD inline const T *begin() const noexcept
        {
            return cbegin();
        }

        
        SEAL_NODISCARD inline const T *cbegin() const noexcept
        {
            return data_.get();
        }
end 函数,返回指向最后一个元素的指针,跟 begin 类似
        
        SEAL_NODISCARD inline T *end() noexcept
        {
            return begin() + size_;
        }

        
        SEAL_NODISCARD inline const T *end() const noexcept
        {
            return cend();
        }

        
        SEAL_NODISCARD inline const T *cend() const noexcept
        {
            return cbegin() + size_;
        }
gsl span

GSL库入门
GSL参考手册

#ifdef SEAL_USE_MSGSL
        
        SEAL_NODISCARD inline gsl::span span()
        {
            return gsl::span(begin(), size_);
        }

        
        SEAL_NODISCARD inline gsl::span span() const
        {
            return gsl::span(cbegin(), size_);
        }
#endif
at 函数,两个版本
        
        SEAL_NODISCARD inline const T &at(std::size_t index) const
        {
            if (index >= size_)
            {
                throw std::out_of_range("index must be within [0, size)");
            }
            return data_[index];
        }

        
        SEAL_NODISCARD inline T &at(std::size_t index)
        {
            if (index >= size_)
            {
                throw std::out_of_range("index must be within [0, size)");
            }
            return data_[index];
        }
[ ] 运算符,跟 at 函数差不多
        
        SEAL_NODISCARD inline const T &operator[](std::size_t index) const
        {
            return data_[index];
        }

        
        SEAL_NODISCARD inline T &operator[](std::size_t index)
        {
            return data_[index];
        }
empty 函数,判断是否为空
        
        SEAL_NODISCARD inline bool empty() const noexcept
        {
            return (size_ == 0);
        }
max_size 函数,返回数组可能的最大size
        
        SEAL_NODISCARD inline std::size_t max_size() const noexcept
        {
            return (std::numeric_limits::max)();
        }

size 函数,返回此时数组的大小
        
        SEAL_NODISCARD inline std::size_t size() const noexcept
        {
            return size_;
        }
capacity 函数
        
        SEAL_NODISCARD inline std::size_t capacity() const noexcept
        {
            return capacity_;
        }
pool 函数
        
        SEAL_NODISCARD inline MemoryPoolHandle pool() const noexcept
        {
            return pool_;
        }
release 函数,把内存还给 memory pool
        
        inline void release() noexcept
        {
            capacity_ = 0;
            size_ = 0;
            data_.release();
        }
clear 函数
        
        inline void clear() noexcept
        {
            size_ = 0;
        }
reserve 函数
    Allocates enough memory for storing a given number of elements without
    changing the size of the array. If the given capacity is smaller than
    the current size, the size is automatically set to equal the new capacity.

std::copy_n
功能:第一个参数为源起始位置,第二个参数是要复制的大小,第三个参数是目标起始位置

        
        inline void reserve(std::size_t capacity)
        {
            std::size_t copy_size = std::min<>(capacity, size_);

            // Create new allocation and copy over value
            auto new_data(util::allocate(capacity, pool_));
            std::copy_n(cbegin(), copy_size, new_data.get());
            std::swap(data_, new_data);

            // Set the coeff_count and capacity
            capacity_ = capacity;
            size_ = copy_size;
        }
shrink_to_fit 函数
        
        inline void shrink_to_fit()
        {
            reserve(size_);
        }
resize 函数
	Resizes the array to given size. When resizing to larger size the data
    in the array remains unchanged and any new space is initialized to zero
    if fill_zero is set to true; when resizing to smaller size the last
    elements of the array are dropped. If the capacity is not already large
    enough to hold the new size, the array is also reallocated.

将数组的大小调整为给定的大小。当调整到更大的大小,数组中的数据保持不变,任何新的空间初始化为零,如果fill_zero设置为true;当将数组大小调整为更小时,将删除数组的最后一个元素。如果容量还不足以容纳新大小,则还会重新分配数组。

        
        inline void resize(std::size_t size, bool fill_zero = true)
        {
            if (size <= capacity_)
            {
                // Are we changing size to bigger within current capacity?
                // If so, need to set top terms to zero
                if (size > size_ && fill_zero)
                {
                    std::fill(end(), begin() + size, T(0));
                }

                // Set the size
                size_ = size;

                return;
            }

            // At this point we know for sure that size_ <= capacity_ < size so need
            // to reallocate to bigger
            auto new_data(util::allocate(size, pool_));
            std::copy(cbegin(), cend(), new_data.get());
            if (fill_zero)
            {
                std::fill(new_data.get() + size_, new_data.get() + size, T(0));
            }
            std::swap(data_, new_data);

            // Set the coeff_count and capacity
            capacity_ = size;
            size_ = size;
        }
赋值运算符
#ifdef SEAL_USE_MSGSL
        
        inline DynArray &operator=(gsl::span values)
        {
            // First resize to correct size ignoring any existing data
            resize(0, false);
            resize(values.size(), false);

            // Size is guaranteed to be OK now so copy over
            std::copy(values.begin(), values.end(), begin());

            return *this;
        }
#endif
        
        inline DynArray &operator=(const DynArray &assign)
        {
            // Check for self-assignment
            if (this == &assign)
            {
                return *this;
            }

            // First resize to correct size
            resize(assign.size_);

            // Size is guaranteed to be OK now so copy over
            std::copy(assign.cbegin(), assign.cend(), begin());

            return *this;
        }

        
        DynArray &operator=(DynArray &&assign) noexcept
        {
            capacity_ = assign.capacity_;
            size_ = assign.size_;
            data_ = std::move(assign.data_);
            pool_ = std::move(assign.pool_);

            return *this;
        }
save_size 函数
        
        SEAL_NODISCARD inline std::streamoff save_size(
            compr_mode_type compr_mode = Serialization::compr_mode_default) const
        {
            std::size_t members_size = Serialization::ComprSizeEstimate(
                util::add_safe(
                    sizeof(std::uint64_t), // size_
                    util::mul_safe(size_, sizeof(T))), // data_
                compr_mode);

            return util::safe_cast(util::add_safe(sizeof(Serialization::SEALHeader), members_size));
        }
save 和 load 函数
        
        inline std::streamoff save(
            std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const
        {
            using namespace std::placeholders;
            return Serialization::Save(
                std::bind(&DynArray::save_members, this, _1), save_size(compr_mode_type::none), stream, compr_mode,
                false);
        }

        
        inline std::streamoff load(std::istream &stream, std::size_t in_size_bound = 0)
        {
            using namespace std::placeholders;
            return Serialization::Load(
                std::bind(&DynArray::load_members, this, _1, _2, in_size_bound), stream, false);
        }

        
        inline std::streamoff save(
            seal_byte *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const
        {
            using namespace std::placeholders;
            return Serialization::Save(
                std::bind(&DynArray::save_members, this, _1), save_size(compr_mode_type::none), out, size,
                compr_mode, false);
        }

        
        inline std::streamoff load(const seal_byte *in, std::size_t size, std::size_t in_size_bound = 0)
        {
            using namespace std::placeholders;
            return Serialization::Load(
                std::bind(&DynArray::load_members, this, _1, _2, in_size_bound), in, size, false);
        }
save_members 和 load_members 函数,私有
    private:
        void save_members(std::ostream &stream) const
        {
            auto old_except_mask = stream.exceptions();
            try
            {
                // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit
                stream.exceptions(std::ios_base::badbit | std::ios_base::failbit);

                std::uint64_t size64 = size_;
                stream.write(reinterpret_cast(&size64), sizeof(std::uint64_t));
                if (size_)
                {
                    stream.write(
                        reinterpret_cast(cbegin()),
                        util::safe_cast(util::mul_safe(size_, sizeof(T))));
                }
            }
            catch (const std::ios_base::failure &)
            {
                stream.exceptions(old_except_mask);
                throw std::runtime_error("I/O error");
            }
            catch (...)
            {
                stream.exceptions(old_except_mask);
                throw;
            }
            stream.exceptions(old_except_mask);
        }

        void load_members(std::istream &stream, SEAL_MAYBE_UNUSED SEALVersion version, std::size_t in_size_bound)
        {
            auto old_except_mask = stream.exceptions();
            try
            {
                // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit
                stream.exceptions(std::ios_base::badbit | std::ios_base::failbit);

                std::uint64_t size64 = 0;
                stream.read(reinterpret_cast(&size64), sizeof(std::uint64_t));

                // Check (optionally) that the size in the metadata does not exceed
                // in_size_bound
                if (in_size_bound && util::unsigned_gt(size64, in_size_bound))
                {
                    throw std::logic_error("unexpected size");
                }

                // Set new size; this is potentially unsafe if size64 was not checked
                // against expected_size
                resize(util::safe_cast(size64));

                // Read data
                if (size_)
                {
                    stream.read(
                        reinterpret_cast(begin()),
                        util::safe_cast(util::mul_safe(size_, sizeof(T))));
                }
            }
            catch (const std::ios_base::failure &)
            {
                stream.exceptions(old_except_mask);
                throw std::runtime_error("I/O error");
            }
            catch (...)
            {
                stream.exceptions(old_except_mask);
                throw;
            }
            stream.exceptions(old_except_mask);
        }
私有成员

数据是利用 Pointer 类型来实现的

        MemoryPoolHandle pool_;

        std::size_t capacity_ = 0;

        std::size_t size_ = 0;

        util::Pointer data_;
seal/randomgen.h

引用的头文件

#include "seal/dynarray.h"
#include "seal/memorymanager.h"
#include "seal/version.h"
#include "seal/util/common.h"
#include "seal/util/defines.h"
#include 
#include 
#include 
#include 
#include 
#include 
定义两个常量和一个别名

在 array 类模板中,T 用于指明容器中的存储的具体数据类型,N 用于指明容器的大小,需要注意的是,这里的 N 必须是常量,不能用变量表示。
std::array

    constexpr std::size_t prng_seed_uint64_count = 8;

    constexpr std::size_t prng_seed_byte_count = prng_seed_uint64_count * util::bytes_per_uint64;

    using prng_seed_type = std::array;
prng_type 枚举类型,用于确定使用哪种伪随机数生成器
    
    enum class prng_type : std::uint8_t
    {
        unknown = 0,

        blake2xb = 1,

        shake256 = 2
    };

random_bytes 函数
    
    void random_bytes(seal_byte *buf, std::size_t count);
random_uint64 函数
    
    SEAL_NODISCARD inline std::uint64_t random_uint64()
    {
        std::uint64_t result;
        random_bytes(reinterpret_cast(&result), sizeof(result));
        return result;
    }
UniformRandomGeneratorInfo 类

这个类保存伪随机数生成器的类型和种子

声明友元类
    class UniformRandomGenerator;

    class UniformRandomGeneratorInfo
    {
        friend class UniformRandomGenerator;
构造函数
        
        UniformRandomGeneratorInfo() = default;

        
        UniformRandomGeneratorInfo(prng_type type, prng_seed_type seed) : type_(type), seed_(std::move(seed))
        {}

        
        UniformRandomGeneratorInfo(const UniformRandomGeneratorInfo ©) = default;
赋值运算符
        
        UniformRandomGeneratorInfo &operator=(const UniformRandomGeneratorInfo &assign) = default;
比较运算符
        
        SEAL_NODISCARD inline bool operator==(const UniformRandomGeneratorInfo &compare) const noexcept
        {
            return (seed_ == compare.seed_) && (type_ == compare.type_);
        }
        
        
        SEAL_NODISCARD inline bool operator!=(const UniformRandomGeneratorInfo &compare) const noexcept
        {
            return !operator==(compare);
        }

clear 函数,清除数据
        
        void clear() noexcept
        {
            type_ = prng_type::unknown;
            util::seal_memzero(seed_.data(), prng_seed_byte_count);
        }
析构函数,调用 clear 函数
        
        ~UniformRandomGeneratorInfo()
        {
            clear();
        }
make_prng 函数,生成一个伪随机数生成器

在 cpp 文件中实现

        
        std::shared_ptr make_prng() const;
has_valid_prng_type 函数
        
        SEAL_NODISCARD inline bool has_valid_prng_type() const noexcept
        {
            switch (type_)
            {
            case prng_type::blake2xb:
                

            case prng_type::shake256:
                

            case prng_type::unknown:
                return true;
            }
            return false;
        }
type 函数
        
        SEAL_NODISCARD inline prng_type type() const noexcept
        {
            return type_;
        }

        
        SEAL_NODISCARD inline prng_type &type() noexcept
        {
            return type_;
        }
seed 函数
        
        SEAL_NODISCARD inline const prng_seed_type &seed() const noexcept
        {
            return seed_;
        }

        
        SEAL_NODISCARD inline prng_seed_type &seed() noexcept
        {
            return seed_;
        }

save_size 函数
        
        SEAL_NODISCARD static inline std::streamoff SaveSize(
            compr_mode_type compr_mode = Serialization::compr_mode_default)
        {
            std::size_t members_size =
                Serialization::ComprSizeEstimate(sizeof(prng_type) + prng_seed_byte_count, compr_mode);
            return static_cast(sizeof(Serialization::SEALHeader) + members_size);
        }

        
        SEAL_NODISCARD inline std::streamoff save_size(
            compr_mode_type compr_mode = Serialization::compr_mode_default) const
        {
            return UniformRandomGeneratorInfo::SaveSize(compr_mode);
        }
save 和 load 函数
        
        inline std::streamoff save(
            std::ostream &stream, compr_mode_type compr_mode = Serialization::compr_mode_default) const
        {
            using namespace std::placeholders;
            return Serialization::Save(
                std::bind(&UniformRandomGeneratorInfo::save_members, this, _1), save_size(compr_mode_type::none),
                stream, compr_mode, true);
        }

        
        inline std::streamoff load(std::istream &stream)
        {
            using namespace std::placeholders;
            UniformRandomGeneratorInfo new_info;
            auto in_size = Serialization::Load(
                std::bind(&UniformRandomGeneratorInfo::load_members, &new_info, _1, _2), stream, true);
            std::swap(*this, new_info);
            return in_size;
        }

        
        inline std::streamoff save(
            seal_byte *out, std::size_t size, compr_mode_type compr_mode = Serialization::compr_mode_default) const
        {
            using namespace std::placeholders;
            return Serialization::Save(
                std::bind(&UniformRandomGeneratorInfo::save_members, this, _1), save_size(compr_mode_type::none), out,
                size, compr_mode, true);
        }

        
        inline std::streamoff load(const seal_byte *in, std::size_t size)
        {
            using namespace std::placeholders;
            UniformRandomGeneratorInfo new_info;
            auto in_size = Serialization::Load(
                std::bind(&UniformRandomGeneratorInfo::load_members, &new_info, _1, _2), in, size, true);
            std::swap(*this, new_info);
            return in_size;
        }
成员变量
    public:
        void save_members(std::ostream &stream) const;

        void load_members(std::istream &stream, SEALVersion version);

        prng_type type_ = prng_type::unknown;

        prng_seed_type seed_ = {};
UniformRandomGenerator 类 类说明
Provides the base class for a seeded uniform random number generator. Instances
of this class are meant to be created by an instance of the factory class
UniformRandomGeneratorFactory. This class is meant for users to sub-class to
implement their own random number generators.

提供种子均匀随机数生成器的基类。该类的实例是由工厂类UniformRandomGeneratorFactory的实例创建的。这个类是为了让用户子类化来实现他们自己的随机数生成器。

构造函数
        
        UniformRandomGenerator(prng_seed_type seed)
            : seed_([&seed]() {
                  // Create a new seed allocation
                  DynArray new_seed(
                      seed.size(), MemoryManager::GetPool(mm_prof_opt::mm_force_new, true));

                  // Assign the given seed and return
                  std::copy(seed.cbegin(), seed.cend(), new_seed.begin());
                  return new_seed;
              }()),
              buffer_(buffer_size_, MemoryManager::GetPool(mm_prof_opt::mm_force_new, true)),
              buffer_begin_(buffer_.begin()), buffer_end_(buffer_.end()), buffer_head_(buffer_.end())
        {}
seed 函数,返回种子的副本
        SEAL_NODISCARD inline prng_seed_type seed() const noexcept
        {
            prng_seed_type ret{};
            std::copy(seed_.cbegin(), seed_.cend(), ret.begin());
            return ret;
        }
generate 函数,生成一组伪随机数
        
        void generate(std::size_t byte_count, seal_byte *destination);
generate 函数,生成一个32-bit伪随机数
        
        SEAL_NODISCARD inline std::uint32_t generate()
        {
            std::uint32_t result;
            generate(sizeof(result), reinterpret_cast(&result));
            return result;
        }
refresh 函数,重新生成一组伪随机数,调用 refill_buffer 函数
        
        inline void refresh()
        {
            std::lock_guard lock(mutex_);
            refill_buffer();
            buffer_head_ = buffer_begin_;
        }

info 函数,返回信息的副本
        
        SEAL_NODISCARD inline UniformRandomGeneratorInfo info() const noexcept
        {
            UniformRandomGeneratorInfo result;
            std::copy_n(seed_.cbegin(), prng_seed_uint64_count, result.seed_.begin());
            result.type_ = type();
            return result;
        }
析构函数
        
        virtual ~UniformRandomGenerator() = default;
成员变量
    protected:
        SEAL_NODISCARD virtual prng_type type() const noexcept = 0;

        virtual void refill_buffer() = 0;

        const DynArray seed_;

        const std::size_t buffer_size_ = 4096;

    private:
        DynArray buffer_;

        std::mutex mutex_;

    protected:
        seal_byte *const buffer_begin_;

        seal_byte *const buffer_end_;

        seal_byte *buffer_head_;
UniformRandomGeneratorFactory 类 类说明
Provides the base class for a factory instance that creates instances of
UniformRandomGenerator. This class is meant for users to sub-class to implement
their own random number generators.

为创建UniformRandomGenerator实例的工厂实例提供基类。这个类是为了让用户子类化来实现他们自己的随机数生成器。

构造函数
        
        UniformRandomGeneratorFactory() : use_random_seed_(true)
        {}

        
        UniformRandomGeneratorFactory(prng_seed_type default_seed)
            : default_seed_(default_seed), use_random_seed_(false)
        {}
create 函数,创建新的伪随机数生成器
        
        SEAL_NODISCARD auto create() -> std::shared_ptr
        {
            return use_random_seed_ ? create_impl([]() {
                prng_seed_type seed;
                random_bytes(reinterpret_cast(seed.data()), prng_seed_byte_count);
                return seed;
            }())
                                    : create_impl(default_seed_);
        }

        
        SEAL_NODISCARD auto create(prng_seed_type seed) -> std::shared_ptr
        {
            return create_impl(seed);
        }
析构函数
        
        virtual ~UniformRandomGeneratorFactory() = default;
static DefaultFactory 函数,返回默认的 random number generator factory
        
        static auto DefaultFactory() -> std::shared_ptr;
use_random_seed 函数,判断是否使用随机的种子
        
        SEAL_NODISCARD inline prng_seed_type default_seed() noexcept
        {
            return default_seed_;
        }
create_impl 函数,protected
    protected:
        SEAL_NODISCARD virtual auto create_impl(prng_seed_type seed) -> std::shared_ptr = 0;
private 成员
    private:
        prng_seed_type default_seed_ = {};

        bool use_random_seed_ = false;
Blake2xbPRNG 类
    
    class Blake2xbPRNG : public UniformRandomGenerator
    {
    public:
        
        Blake2xbPRNG(prng_seed_type seed) : UniformRandomGenerator(seed)
        {}

        
        ~Blake2xbPRNG() = default;

    protected:
        SEAL_NODISCARD prng_type type() const noexcept override
        {
            return prng_type::blake2xb;
        }

        void refill_buffer() override;

    private:
        std::uint64_t counter_ = 0;
    };
Blake2xbPRNGFactory 类
    class Blake2xbPRNGFactory : public UniformRandomGeneratorFactory
    {
    public:
        
        Blake2xbPRNGFactory() : UniformRandomGeneratorFactory()
        {}

        
        Blake2xbPRNGFactory(prng_seed_type default_seed) : UniformRandomGeneratorFactory(default_seed)
        {}

        
        ~Blake2xbPRNGFactory() = default;

    protected:
        SEAL_NODISCARD auto create_impl(prng_seed_type seed) -> std::shared_ptr override
        {
            return std::make_shared(seed);
        }

    private:
    };
Shake256PRNG 类
    
    class Shake256PRNG : public UniformRandomGenerator
    {
    public:
        
        Shake256PRNG(prng_seed_type seed) : UniformRandomGenerator(seed)
        {}

        
        ~Shake256PRNG() = default;

    protected:
        SEAL_NODISCARD prng_type type() const noexcept override
        {
            return prng_type::shake256;
        }

        void refill_buffer() override;

    private:
        std::uint64_t counter_ = 0;
    };
Shake256PRNGFactory 类
    class Shake256PRNGFactory : public UniformRandomGeneratorFactory
    {
    public:
        
        Shake256PRNGFactory() : UniformRandomGeneratorFactory()
        {}

        
        Shake256PRNGFactory(prng_seed_type default_seed) : UniformRandomGeneratorFactory(default_seed)
        {}

        
        ~Shake256PRNGFactory() = default;

    protected:
        SEAL_NODISCARD auto create_impl(prng_seed_type seed) -> std::shared_ptr override
        {
            return std::make_shared(seed);
        }

    private:
    };
seal/randomgen.cpp

对同文件中的一些函数的实现

#include "seal/randomgen.h"
#include "seal/util/blake2.h"
#include "seal/util/common.h"
#include "seal/util/fips202.h"
#include 
#include 
#include 
#if (SEAL_SYSTEM == SEAL_SYSTEM_WINDOWS)
#include 
#include 
#pragma comment(lib, "bcrypt")
#endif

using namespace std;
using namespace seal::util;

#if (SEAL_SYSTEM == SEAL_SYSTEM_WINDOWS)

constexpr auto RTL_GENRANDOM = "SystemFunction036";

// Preserve error codes to diagnose in case of failure
NTSTATUS last_bcrypt_error = 0;
DWORD last_genrandom_error = 0;

#endif
random_bytes 实现
    void random_bytes(seal_byte *buf, size_t count)
    {
#if SEAL_SYSTEM == SEAL_SYSTEM_UNIX_LIKE
        random_device rd("/dev/urandom");
        while (count >= 4)
        {
            *reinterpret_cast(buf) = rd();
            buf += 4;
            count -= 4;
        }
        if (count)
        {
            uint32_t last = rd();
            memcpy(buf, &last, count);
        }
#elif SEAL_SYSTEM == SEAL_SYSTEM_WINDOWS
        NTSTATUS status = BCryptGenRandom(
            NULL, reinterpret_cast(buf), safe_cast(count), BCRYPT_USE_SYSTEM_PREFERRED_RNG);

        if (BCRYPT_SUCCESS(status))
        {
            return;
        }

        last_bcrypt_error = status;

        HMODULE hAdvApi = LoadLibraryA("ADVAPI32.DLL");
        if (!hAdvApi)
        {
            last_genrandom_error = GetLastError();
            throw runtime_error("Failed to load ADVAPI32.DLL");
        }

        BOOLEAN(APIENTRY * RtlGenRandom)
        (void *, ULONG) = (BOOLEAN(APIENTRY *)(void *, ULONG))GetProcAddress(hAdvApi, RTL_GENRANDOM);

        BOOLEAN genrand_result = FALSE;
        if (RtlGenRandom)
        {
            genrand_result = RtlGenRandom(buf, bytes_per_uint64);
        }

        DWORD dwError = GetLastError();
        FreeLibrary(hAdvApi);

        if (!genrand_result)
        {
            last_genrandom_error = dwError;
            throw runtime_error("Failed to call RtlGenRandom");
        }
#elif SEAL_SYSTEM == SEAL_SYSTEM_OTHER
#warning "SECURITY WARNING: System detection failed; falling back to a potentially insecure randomness source!"
        random_device rd;
        while (count >= 4)
        {
            *reinterpret_cast(buf) = rd();
            buf += 4;
            count -= 4;
        }
        if (count)
        {
            uint32_t last = rd();
            memcpy(buf, &last, count);
        }
#endif
    }
UniformRandomGeneratorInfo::save_members 实现
    void UniformRandomGeneratorInfo::save_members(ostream &stream) const
    {
        // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit
        auto old_except_mask = stream.exceptions();
        try
        {
            stream.exceptions(ios_base::badbit | ios_base::failbit);

            stream.write(reinterpret_cast(&type_), sizeof(prng_type));
            stream.write(reinterpret_cast(seed_.data()), prng_seed_byte_count);
        }
        catch (const ios_base::failure &)
        {
            stream.exceptions(old_except_mask);
            throw runtime_error("I/O error");
        }
        catch (...)
        {
            stream.exceptions(old_except_mask);
            throw;
        }
        stream.exceptions(old_except_mask);
    }
UniformRandomGeneratorInfo::load_members 实现
    void UniformRandomGeneratorInfo::load_members(istream &stream, SEAL_MAYBE_UNUSED SEALVersion version)
    {
        // Throw exceptions on std::ios_base::badbit and std::ios_base::failbit
        auto old_except_mask = stream.exceptions();
        try
        {
            stream.exceptions(ios_base::badbit | ios_base::failbit);

            UniformRandomGeneratorInfo info;

            // Read the PRNG type
            stream.read(reinterpret_cast(&info.type_), sizeof(prng_type));
            if (!info.has_valid_prng_type())
            {
                throw logic_error("prng_type is invalid");
            }

            // Read the seed data
            stream.read(reinterpret_cast(info.seed_.data()), prng_seed_byte_count);

            swap(*this, info);

            stream.exceptions(old_except_mask);
        }
        catch (const ios_base::failure &)
        {
            stream.exceptions(old_except_mask);
            throw runtime_error("I/O error");
        }
        catch (...)
        {
            stream.exceptions(old_except_mask);
            throw;
        }
        stream.exceptions(old_except_mask);
    }
UniformRandomGeneratorInfo::make_prng() 实现
    shared_ptr UniformRandomGeneratorInfo::make_prng() const
    {
        switch (type_)
        {
        case prng_type::blake2xb:
            return make_shared(seed_);

        case prng_type::shake256:
            return make_shared(seed_);

        case prng_type::unknown:
            return nullptr;
        }
        return nullptr;
    }
UniformRandomGenerator::generate 实现
    void UniformRandomGenerator::generate(size_t byte_count, seal_byte *destination)
    {
        lock_guard lock(mutex_);
        while (byte_count)
        {
            size_t current_bytes = min(byte_count, static_cast(distance(buffer_head_, buffer_end_)));
            copy_n(buffer_head_, current_bytes, destination);
            buffer_head_ += current_bytes;
            destination += current_bytes;
            byte_count -= current_bytes;

            if (buffer_head_ == buffer_end_)
            {
                refill_buffer();
                buffer_head_ = buffer_begin_;
            }
        }
    }
UniformRandomGeneratorFactory::DefaultFactory() -> shared_ptr< UniformRandomGeneratorFactory > 实现
    auto UniformRandomGeneratorFactory::DefaultFactory() -> shared_ptr
    {
        static shared_ptr default_factory{ new SEAL_DEFAULT_PRNG_FACTORY() };
        return default_factory;
    }
Blake2xbPRNG::refill_buffer 实现
    void Blake2xbPRNG::refill_buffer()
    {
        // Fill the randomness buffer
        if (blake2xb(
                buffer_begin_, buffer_size_, &counter_, sizeof(counter_), seed_.cbegin(),
                seed_.size() * sizeof(decltype(seed_)::type)) != 0)
        {
            throw runtime_error("blake2xb failed");
        }
        counter_++;
    }
Shake256PRNG::refill_buffer 函数实现
    void Shake256PRNG::refill_buffer()
    {
        // Fill the randomness buffer
        array seed_ext;
        copy_n(seed_.cbegin(), prng_seed_uint64_count, seed_ext.begin());
        seed_ext[prng_seed_uint64_count] = counter_;
        shake256(
            reinterpret_cast(buffer_begin_), buffer_size_,
            reinterpret_cast(seed_ext.data()), seed_ext.size() * bytes_per_uint64);
        seal_memzero(seed_ext.data(), seed_ext.size() * bytes_per_uint64);
        counter_++;
    }
seal/util/hash.h

用 blake2 作为哈希的实现

HashFunction 类
#include "seal/util/blake2.h"
#include "seal/util/common.h"
#include "seal/util/defines.h"
#include 
#include 
#include 

namespace seal
{
    namespace util
    {
        class HashFunction
        {
        public:
            HashFunction() = delete;

            static constexpr std::size_t hash_block_uint64_count = 4;

            static constexpr std::size_t hash_block_byte_count = hash_block_uint64_count * bytes_per_uint64;

            using hash_block_type = std::array;

            static constexpr hash_block_type hash_zero_block{ { 0, 0, 0, 0 } };

            inline static void hash(const std::uint64_t *input, std::size_t uint64_count, hash_block_type &destination)
            {
                if (blake2b(&destination, hash_block_byte_count, input, uint64_count * bytes_per_uint64, nullptr, 0) !=
                    0)
                {
                    throw std::runtime_error("blake2b failed");
                }
            }
        };
    } // namespace util
} // namespace seal
seal/util/hash.cpp
#include "seal/util/hash.h"

using namespace std;

namespace seal
{
    namespace util
    {
        // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to
        // ensure symbol is created.
        constexpr size_t HashFunction::hash_block_uint64_count;

        // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to
        // ensure symbol is created.
        constexpr size_t HashFunction::hash_block_byte_count;

        // Required for C++14 compliance: static constexpr member variables are not necessarily inlined so need to
        // ensure symbol is created.
        constexpr HashFunction::hash_block_type HashFunction::hash_zero_block;
    } // namespace util
} // namespace seal

seal/encryptionparameters.h

引用的头文件

#include "seal/memorymanager.h"
#include "seal/modulus.h"
#include "seal/randomgen.h"
#include "seal/serialization.h"
#include "seal/version.h"
#include "seal/util/defines.h"
#include "seal/util/globals.h"
#include "seal/util/hash.h"
#include "seal/util/ztools.h"
#include 
#include 
#include 
#include 
scheme_type 枚举

位于 namespace seal 中

    
    enum class scheme_type : std::uint8_t
    {
        // No scheme set; cannot be used for encryption
        none = 0x0,

        // Brakerski/Fan-Vercauteren scheme
        bfv = 0x1,

        // Cheon-Kim-Kim-Song scheme
        ckks = 0x2,

        // Brakerski-Gentry-Vaikuntanathan scheme
        bgv = 0x3
    };
别名

这个为 4 个 uint64 类型构成的数组

    
    using parms_id_type = util::HashFunction::hash_block_type;

    
    extern const parms_id_type parms_id_zero;
EncryptionParameters 类 类说明
 

表示用户可自定义的加密方案设置。其中的参数(最重要的是poly_modulus、coeff_modulus、plain_modulus)对加密方案的性能、性能和安全性有很大的影响。使用适当的参数填充EncryptionParameters的实例之后,就可以使用它来创建SEALContext类的实例,该实例验证参数的有效性,并执行必要的预计算。

选择适当的加密参数对于启用特定应用程序、同时平衡性能和安全性至关重要。一些加密设置不允许某些输入(例如,试图加密系数大于poly_modulus或大于plain_modulus的多项式),或者支持所需的计算(由于plain_modulus过大而coeff_modulus过小而导致噪声增长过快)。

@par parms_id
EncryptionParameters类始终维护当前设置的加密参数的256位散列,称为parms_id。此散列用作加密参数的唯一标识符,并由为这些加密参数创建的所有进一步对象使用。parms_id不打算由用户直接修改,而是在内部用于计算前的数据查找和输入有效性检查。在模切换中,用户可以使用parms_id来跟踪加密参数链。parms_id不暴露在EncryptionParameters的公共API中,但是一旦创建了SEALContext,就可以通过SEALContext::ContextData类访问。

@par线程安全
通常,从EncryptionParameters读取是线程安全的,而突变则不是。

@warning
选择不合适的加密参数可能导致加密方案不安全,性能不佳,和/或不支持所需应用程序的输入和计算。我们强烈建议在选择参数时咨询基于rlwe的加密专家,因为这是经验不足的用户最容易犯严重错误的地方。

声明友元结构体
        friend struct std::hash;
private 成员 包括加密方案,多项式模的次数,明文模数,多项式系数的模数,伪随机数生成器工厂,哈希值
    private:
        
        SEAL_NODISCARD bool is_valid_scheme(std::uint8_t scheme) const noexcept
        {
            switch (scheme)
            {
            case static_cast(scheme_type::none):
                

            case static_cast(scheme_type::bfv):
                

            case static_cast(scheme_type::ckks):
                

            case static_cast(scheme_type::bgv):
                return true;
            }
            return false;
        }

        void compute_parms_id();

        void save_members(std::ostream &stream) const;

        void load_members(std::istream &stream, SEALVersion version);

        MemoryPoolHandle pool_ = MemoryManager::GetPool();

        scheme_type scheme_;

        std::size_t poly_modulus_degree_ = 0;

        std::vector coeff_modulus_{};

        std::shared_ptr random_generator_{ nullptr };

        Modulus plain_modulus_{};

        parms_id_type parms_id_ = parms_id_zero;
构造函数,调用 compute_parms_id 函数
        
        EncryptionParameters(scheme_type scheme = scheme_type::none) : scheme_(scheme)
        {
            compute_parms_id();
        }

        
        EncryptionParameters(std::uint8_t scheme)
        {
            // Check that a valid scheme is given
            if (!is_valid_scheme(scheme))
            {
                throw std::invalid_argument("unsupported scheme");
            }

            scheme_ = static_cast(scheme);
            compute_parms_id();
        }

        
        EncryptionParameters(const EncryptionParameters ©) = default;
赋值运算符
        
        EncryptionParameters &operator=(const EncryptionParameters &assign) = default;

        
        EncryptionParameters(EncryptionParameters &&source) = default;

        
        EncryptionParameters &operator=(EncryptionParameters &&assign) = default;
set_poly_modulus_degree 函数

设置多项式模的次数

    Sets the degree of the polynomial modulus parameter to the specified value.
    The polynomial modulus directly affects the number of coefficients in
    plaintext polynomials, the size of ciphertext elements, the computational
    performance of the scheme (bigger is worse), and the security level (bigger
    is better). In Microsoft SEAL the degree of the polynomial modulus must be
    a power of 2 (e.g.  1024, 2048, 4096, 8192, 16384, or 32768).
        
        inline void set_poly_modulus_degree(std::size_t poly_modulus_degree)
        {
            if (scheme_ == scheme_type::none && poly_modulus_degree)
            {
                throw std::logic_error("poly_modulus_degree is not supported for this scheme");
            }

            // Set the degree
            poly_modulus_degree_ = poly_modulus_degree;

            // Re-compute the parms_id
            compute_parms_id();
        }
set_coeff_modulus 函数

设置多项式系数模数
每个素数都要满足同余于 1 模 2*多项式模的次数
Sets the coefficient modulus parameter. The coefficient modulus consists
of a list of distinct prime numbers, and is represented by a vector of
Modulus objects. The coefficient modulus directly affects the size
of ciphertext elements, the amount of computation that the scheme can
perform (bigger is better), and the security level (bigger is worse). In
Microsoft SEAL each of the prime numbers in the coefficient modulus must
be at most 60 bits, and must be congruent to 1 modulo 2*poly_modulus_degree.

        
        inline void set_coeff_modulus(const std::vector &coeff_modulus)
        {
            // Check that a scheme is set
            if (scheme_ == scheme_type::none)
            {
                if (!coeff_modulus.empty())
                {
                    throw std::logic_error("coeff_modulus is not supported for this scheme");
                }
            }
            else if (coeff_modulus.size() > SEAL_COEFF_MOD_COUNT_MAX || coeff_modulus.size() < SEAL_COEFF_MOD_COUNT_MIN)
            {
                throw std::invalid_argument("coeff_modulus is invalid");
            }

            coeff_modulus_ = coeff_modulus;

            // Re-compute the parms_id
            compute_parms_id();
        }
set_plain_modulus 函数
	Sets the plaintext modulus parameter. The plaintext modulus is an integer
    modulus represented by the Modulus class. The plaintext modulus
    determines the largest coefficient that plaintext polynomials can represent.
    It also affects the amount of computation that the scheme can perform
    (bigger is worse). In Microsoft SEAL the plaintext modulus can be at most
    60 bits long, but can otherwise be any integer. Note, however, that some
    features (e.g. batching) require the plaintext modulus to be of a particular
    form.
        
        inline void set_plain_modulus(const Modulus &plain_modulus)
        {
            // Check that scheme is CKKS
            if (scheme_ != scheme_type::bfv && scheme_ != scheme_type::bgv && !plain_modulus.is_zero())
            {
                throw std::logic_error("plain_modulus is not supported for this scheme");
            }

            plain_modulus_ = plain_modulus;

            // Re-compute the parms_id
            compute_parms_id();
        }

        
        inline void set_plain_modulus(std::uint64_t plain_modulus)
        {
            set_plain_modulus(Modulus(plain_modulus));
        }
set_random_generator 函数

设置伪随机数生成器

        
        inline void set_random_generator(std::shared_ptr random_generator) noexcept
        {
            random_generator_ = std::move(random_generator);
        }

一些 getter 函数
        
        SEAL_NODISCARD inline scheme_type scheme() const noexcept
        {
            return scheme_;
        }

        
        SEAL_NODISCARD inline std::size_t poly_modulus_degree() const noexcept
        {
            return poly_modulus_degree_;
        }

        
        SEAL_NODISCARD inline const std::vector &coeff_modulus() const noexcept
        {
            return coeff_modulus_;
        }

        
        SEAL_NODISCARD inline const Modulus &plain_modulus() const noexcept
        {
            return plain_modulus_;
        }

        
        SEAL_NODISCARD inline std::shared_ptr random_generator() const noexcept
        {
            return random_generator_;
        }

        
        SEAL_NODISCARD inline const parms_id_type &parms_id() const noexcept
        {
            return parms_id_;
        }
比较运算
        
        SEAL_NODISCARD inline bool operator==(const EncryptionParameters &other) const noexcept
        {
            return (parms_id_ == other.parms_id_);
        }

        
        SEAL_NODISCARD inline bool operator!=(const EncryptionParameters &other) const noexcept
        {
            return (parms_id_ != other.parms_id_);
        }
save_size,save,load 函数 compute_parms_id 函数实现

功能是将所有成员变量放置在一个结构中,然后计算这个结构的哈希值,保存在 parms_id 中

    void EncryptionParameters::compute_parms_id()
    {
        size_t coeff_modulus_size = coeff_modulus_.size();

        size_t total_uint64_count = add_safe(
            size_t(1), // scheme
            size_t(1), // poly_modulus_degree
            coeff_modulus_size, plain_modulus_.uint64_count());

        auto param_data(allocate_uint(total_uint64_count, pool_));
        uint64_t *param_data_ptr = param_data.get();

        // Write the scheme identifier
        *param_data_ptr++ = static_cast(scheme_);

        // Write the poly_modulus_degree. Note that it will always be positive.
        *param_data_ptr++ = static_cast(poly_modulus_degree_);

        for (const auto &mod : coeff_modulus_)
        {
            *param_data_ptr++ = mod.value();
        }

        set_uint(plain_modulus_.data(), plain_modulus_.uint64_count(), param_data_ptr);
        param_data_ptr += plain_modulus_.uint64_count();

        HashFunction::hash(param_data.get(), total_uint64_count, parms_id_);

        // Did we somehow manage to get a zero block as result? This is reserved for
        // plaintexts to indicate non-NTT-transformed form.
        if (parms_id_ == parms_id_zero)
        {
            throw logic_error("parms_id cannot be zero");
        }
    }
std::hash 特化
namespace std
{
    template <>
    struct hash
    {
        std::size_t operator()(const seal::parms_id_type &parms_id) const
        {
            std::uint64_t result = 17;
            result = 31 * result + parms_id[0];
            result = 31 * result + parms_id[1];
            result = 31 * result + parms_id[2];
            result = 31 * result + parms_id[3];
            return static_cast(result);
        }
    };

    template <>
    struct hash
    {
        std::size_t operator()(const seal::EncryptionParameters &parms) const
        {
            hash parms_id_hash;
            return parms_id_hash(parms.parms_id_);
        }
    };
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1012684.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号