当前位置: 首页 > 工具软件 > SEAL > 使用案例 >

SEAL开源库源码03

金高飞
2023-12-01

SEAL开源库源码03


接上一篇,继续分析 modulus

seal/util/uintcore.h

引用的头文件

#include "seal/util/common.h"
#include "seal/util/defines.h"
#include "seal/util/pointer.h"
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <limits>
#include <stdexcept>

所有函数位于namespace util中

uint_to_hex_string 和 uint_to_dec_string 函数

unsigned int 转换为 十六进制字符串或者十进制字符串
除这两个函数之外,剩下的都是inline函数

		SEAL_NODISCARD std::string uint_to_hex_string(const std::uint64_t *value, std::size_t uint64_count);

        SEAL_NODISCARD std::string uint_to_dec_string(
            const std::uint64_t *value, std::size_t uint64_count, MemoryPool &pool);

hex_string_to_uint 函数,将一个十六进制字符串转换为unsigned int

第一个参数为需要转换的字符串,第二个为字符串数组中字符的个数,第三个参数为64位int的个数,结果保存在第四个参数中,为一个数组,低索引保存低位,高索引保存高位

        inline void hex_string_to_uint(
            const char *hex_string, int char_count, std::size_t uint64_count, std::uint64_t *result)
        {
#ifdef SEAL_DEBUG
            if (!hex_string && char_count > 0)
            {
                throw std::invalid_argument("hex_string");
            }
            if (uint64_count && !result)
            {
                throw std::invalid_argument("result");
            }
            if (unsigned_gt(
                    get_hex_string_bit_count(hex_string, char_count),
                    mul_safe(uint64_count, static_cast<size_t>(bits_per_uint64))))
            {
                throw std::invalid_argument("hex_string");
            }
#endif
            const char *hex_string_ptr = hex_string + char_count;
            for (std::size_t uint64_index = 0; uint64_index < uint64_count; uint64_index++)
            {
                std::uint64_t value = 0;
                for (int bit_index = 0; bit_index < bits_per_uint64; bit_index += bits_per_nibble)
                {
                    if (hex_string_ptr == hex_string)
                    {
                        break;
                    }
                    char hex = *--hex_string_ptr;
                    int nibble = hex_to_nibble(hex);
                    if (nibble == -1)
                    {
                        throw std::invalid_argument("hex_value");
                    }
                    value |= static_cast<std::uint64_t>(nibble) << bit_index;
                }
                result[uint64_index] = value;
            }
        }

allocate_uint 函数

为数组分配内存

        SEAL_NODISCARD inline auto allocate_uint(std::size_t uint64_count, MemoryPool &pool)
        {
            return allocate<std::uint64_t>(uint64_count, pool);
        }

set_zero_uint 函数

将 uint64_count 个数都赋予值 0

        inline void set_zero_uint(std::size_t uint64_count, std::uint64_t *result)
        {
#ifdef SEAL_DEBUG
            if (!result && uint64_count)
            {
                throw std::invalid_argument("result");
            }
#endif
            std::fill_n(result, uint64_count, std::uint64_t(0));
        }

allocate_zero_uint 函数

先分配内存,再赋予 0

        SEAL_NODISCARD inline auto allocate_zero_uint(std::size_t uint64_count, MemoryPool &pool)
        {
            auto result(allocate_uint(uint64_count, pool));
            set_zero_uint(uint64_count, result.get());
            return result;

            // The following looks better but seems to yield worse results.
            // return allocate<std::uint64_t>(uint64_count, pool, std::uint64_t(0));
        }

set_uint 函数

value为 64位数,要总共赋值 uint64_count 个 64 位数,最低位赋予 value,剩余高位赋予 0

        inline void set_uint(std::uint64_t value, std::size_t uint64_count, std::uint64_t *result)
        {
#ifdef SEAL_DEBUG
            if (!uint64_count)
            {
                throw std::invalid_argument("uint64_count");
            }
            if (!result)
            {
                throw std::invalid_argument("result");
            }
#endif
            *result++ = value;
            for (; --uint64_count; result++)
            {
                *result = 0;
            }
        }

set_uint 函数

现在 value 为一个数组,依旧剩余高位赋予 0

        inline void set_uint(const std::uint64_t *value, std::size_t uint64_count, std::uint64_t *result)
        {
#ifdef SEAL_DEBUG
            if (!value && uint64_count)
            {
                throw std::invalid_argument("value");
            }
            if (!result && uint64_count)
            {
                throw std::invalid_argument("result");
            }
#endif
            if ((value == result) || !uint64_count)
            {
                return;
            }
            std::copy_n(value, uint64_count, result);
        }

is_zero_uint 函数

判断整个数是否为0

        SEAL_NODISCARD inline bool is_zero_uint(const std::uint64_t *value, std::size_t uint64_count)
        {
#ifdef SEAL_DEBUG
            if (!value && uint64_count)
            {
                throw std::invalid_argument("value");
            }
#endif
            return std::all_of(value, value + uint64_count, [](auto coeff) -> bool { return !coeff; });
        }

is_equal_uint 函数

判断整个数是否等于 scalar

        SEAL_NODISCARD inline bool is_equal_uint(
            const std::uint64_t *value, std::size_t uint64_count, std::uint64_t scalar)
        {
#ifdef SEAL_DEBUG
            if (!value)
            {
                throw std::invalid_argument("value");
            }
            if (!uint64_count)
            {
                throw std::invalid_argument("uint64_count");
            }
#endif
            if (*value++ != scalar)
            {
                return false;
            }
            return std::all_of(value, value + uint64_count - 1, [](auto coeff) -> bool { return !coeff; });
        }

is_high_bit_set_uint 函数

判断value整个数最高位的64位数的最高位是否为1,为1则返回true

        SEAL_NODISCARD inline bool is_high_bit_set_uint(const std::uint64_t *value, std::size_t uint64_count)
        {
#ifdef SEAL_DEBUG
            if (!value)
            {
                throw std::invalid_argument("value");
            }
            if (!uint64_count)
            {
                throw std::invalid_argument("uint64_count");
            }
#endif
            return (value[uint64_count - 1] >> (bits_per_uint64 - 1)) != 0;
        }

is_bit_set_uint 函数

判断 bit_index 位置的比特是否为1,为1则返回true

        SEAL_NODISCARD inline bool is_bit_set_uint(
            const std::uint64_t *value, std::size_t uint64_count SEAL_MAYBE_UNUSED, int bit_index)
        {
#ifdef SEAL_DEBUG
            if (!value)
            {
                throw std::invalid_argument("value");
            }
            if (!uint64_count)
            {
                throw std::invalid_argument("uint64_count");
            }
            if (bit_index < 0 ||
                static_cast<std::int64_t>(bit_index) >= static_cast<std::int64_t>(uint64_count) * bits_per_uint64)
            {
                throw std::invalid_argument("bit_index");
            }
#endif
            int uint64_index = bit_index / bits_per_uint64;
            int sub_bit_index = bit_index - uint64_index * bits_per_uint64;
            return ((value[static_cast<std::size_t>(uint64_index)] >> sub_bit_index) & 1) != 0;
        }

set_bit_uint 函数

将 bit_index 位置的比特置为1

        inline void set_bit_uint(std::uint64_t *value, std::size_t uint64_count SEAL_MAYBE_UNUSED, int bit_index)
        {
#ifdef SEAL_DEBUG
            if (!value)
            {
                throw std::invalid_argument("value");
            }
            if (!uint64_count)
            {
                throw std::invalid_argument("uint64_count");
            }
            if (bit_index < 0 ||
                static_cast<std::int64_t>(bit_index) >= static_cast<std::int64_t>(uint64_count) * bits_per_uint64)
            {
                throw std::invalid_argument("bit_index");
            }
#endif
            int uint64_index = bit_index / bits_per_uint64;
            int sub_bit_index = bit_index % bits_per_uint64;
            value[static_cast<std::size_t>(uint64_index)] |= std::uint64_t(1) << sub_bit_index;
        }

get_significant_bit_count_uint 函数

获取有效位数,从这个函数的实现可以推断value数组保存的整个数低索引保存低位,高索引保存高位

        SEAL_NODISCARD inline int get_significant_bit_count_uint(const std::uint64_t *value, std::size_t uint64_count)
        {
#ifdef SEAL_DEBUG
            if (!value && uint64_count)
            {
                throw std::invalid_argument("value");
            }
            if (!uint64_count)
            {
                throw std::invalid_argument("uint64_count");
            }
#endif
            value += uint64_count - 1;
            for (; *value == 0 && uint64_count > 1; uint64_count--)
            {
                value--;
            }

            return static_cast<int>(uint64_count - 1) * bits_per_uint64 + get_significant_bit_count(*value);
        }

get_significant_uint64_count_uint 函数

获取整个数中 uint64 的个数

        SEAL_NODISCARD inline std::size_t get_significant_uint64_count_uint(
            const std::uint64_t *value, std::size_t uint64_count)
        {
#ifdef SEAL_DEBUG
            if (!value && uint64_count)
            {
                throw std::invalid_argument("value");
            }
            if (!uint64_count)
            {
                throw std::invalid_argument("uint64_count");
            }
#endif
            value += uint64_count - 1;
            for (; uint64_count && !*value; uint64_count--)
            {
                value--;
            }

            return uint64_count;
        }

get_nonzero_uint64_count_uint 函数

获取整个数中非零的 uint64 的个数

        SEAL_NODISCARD inline std::size_t get_nonzero_uint64_count_uint(
            const std::uint64_t *value, std::size_t uint64_count)
        {
#ifdef SEAL_DEBUG
            if (!value && uint64_count)
            {
                throw std::invalid_argument("value");
            }
            if (!uint64_count)
            {
                throw std::invalid_argument("uint64_count");
            }
#endif
            std::size_t nonzero_count = uint64_count;

            value += uint64_count - 1;
            for (; uint64_count; uint64_count--)
            {
                if (*value-- == 0)
                {
                    nonzero_count--;
                }
            }

            return nonzero_count;
        }

set_uint 函数

将 value 赋给 result,截断高位

        inline void set_uint(
            const std::uint64_t *value, std::size_t value_uint64_count, std::size_t result_uint64_count,
            std::uint64_t *result)
        {
#ifdef SEAL_DEBUG
            if (!value && value_uint64_count)
            {
                throw std::invalid_argument("value");
            }
            if (!result && result_uint64_count)
            {
                throw std::invalid_argument("result");
            }
#endif
            if (value == result || !value_uint64_count)
            {
                // Fast path to handle self assignment.
                std::fill(result + value_uint64_count, result + result_uint64_count, std::uint64_t(0));
            }
            else
            {
                std::size_t min_uint64_count = std::min<>(value_uint64_count, result_uint64_count);
                std::copy_n(value, min_uint64_count, result);
                std::fill(result + min_uint64_count, result + result_uint64_count, std::uint64_t(0));
            }
        }

get_power_of_two 函数

If the value is a power of two, return the power; otherwise, return -1.

        /**
        If the value is a power of two, return the power; otherwise, return -1.
        */
        SEAL_NODISCARD inline int get_power_of_two(std::uint64_t value)
        {
            if (value == 0 || (value & (value - 1)) != 0)
            {
                return -1;
            }

            unsigned long result = 0;
            SEAL_MSB_INDEX_UINT64(&result, value);
            return static_cast<int>(result);
        }

filter_highbits_uint 函数

截断从 bit_count 往后的所有高位,都被置为0

        inline void filter_highbits_uint(std::uint64_t *operand, std::size_t uint64_count, int bit_count)
        {
            std::size_t bits_per_uint64_sz = static_cast<std::size_t>(bits_per_uint64);
#ifdef SEAL_DEBUG
            if (!operand && uint64_count)
            {
                throw std::invalid_argument("operand");
            }
            if (bit_count < 0 || unsigned_gt(bit_count, mul_safe(uint64_count, bits_per_uint64_sz)))
            {
                throw std::invalid_argument("bit_count");
            }
#endif
            if (unsigned_eq(bit_count, mul_safe(uint64_count, bits_per_uint64_sz)))
            {
                return;
            }
            int uint64_index = bit_count / bits_per_uint64;
            int subbit_index = bit_count - uint64_index * bits_per_uint64;
            operand += uint64_index;
            *operand++ &= (std::uint64_t(1) << subbit_index) - 1;
            for (int long_index = uint64_index + 1; unsigned_lt(long_index, uint64_count); long_index++)
            {
                *operand++ = 0;
            }
        }

duplicate_uint_if_needed 函数

复制一个数,需要分配内存

        SEAL_NODISCARD inline auto duplicate_uint_if_needed(
            const std::uint64_t *input, std::size_t uint64_count, std::size_t new_uint64_count, bool force,
            MemoryPool &pool)
        {
#ifdef SEAL_DEBUG
            if (!input && uint64_count)
            {
                throw std::invalid_argument("uint");
            }
#endif
            if (!force && uint64_count >= new_uint64_count)
            {
                return ConstPointer<std::uint64_t>::Aliasing(input);
            }

            auto allocation(allocate_uint(new_uint64_count, pool));
            set_uint(input, uint64_count, new_uint64_count, allocation.get());
            return ConstPointer<std::uint64_t>(std::move(allocation));
        }

compare_uint 函数

比较operand1 和 operand2大小,operand1大于operand2返回1,operand1小于operand2返回-1,相等返回0,两个数长度相同

        SEAL_NODISCARD inline int compare_uint(
            const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count)
        {
#ifdef SEAL_DEBUG
            if (!operand1 && uint64_count)
            {
                throw std::invalid_argument("operand1");
            }
            if (!operand2 && uint64_count)
            {
                throw std::invalid_argument("operand2");
            }
#endif
            int result = 0;
            operand1 += uint64_count - 1;
            operand2 += uint64_count - 1;

            for (; (result == 0) && uint64_count--; operand1--, operand2--)
            {
                result = (*operand1 > *operand2) - (*operand1 < *operand2);
            }
            return result;
        }

compare_uint(两个数分别有各自的长度)

        SEAL_NODISCARD inline int compare_uint(
            const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2,
            std::size_t operand2_uint64_count)
        {
#ifdef SEAL_DEBUG
            if (!operand1 && operand1_uint64_count)
            {
                throw std::invalid_argument("operand1");
            }
            if (!operand2 && operand2_uint64_count)
            {
                throw std::invalid_argument("operand2");
            }
#endif
            int result = 0;
            operand1 += operand1_uint64_count - 1;
            operand2 += operand2_uint64_count - 1;

            std::size_t min_uint64_count = std::min<>(operand1_uint64_count, operand2_uint64_count);

            operand1_uint64_count -= min_uint64_count;
            for (; (result == 0) && operand1_uint64_count--; operand1--)
            {
                result = (*operand1 > 0);
            }

            operand2_uint64_count -= min_uint64_count;
            for (; (result == 0) && operand2_uint64_count--; operand2--)
            {
                result = -(*operand2 > 0);
            }

            for (; (result == 0) && min_uint64_count--; operand1--, operand2--)
            {
                result = (*operand1 > *operand2) - (*operand1 < *operand2);
            }
            return result;
        }

is_greater_than_uint, is_greater_than_or_equal_uint, is_less_than_uint, is_less_than_or_equal_uint, is_equal_uint函数(包括长度相同和不相同的版本)

都是利用 compare_uint 函数

        SEAL_NODISCARD inline bool is_greater_than_uint(
            const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count)
        {
            return compare_uint(operand1, operand2, uint64_count) > 0;
        }

        SEAL_NODISCARD inline bool is_greater_than_or_equal_uint(
            const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count)
        {
            return compare_uint(operand1, operand2, uint64_count) >= 0;
        }

        SEAL_NODISCARD inline bool is_less_than_uint(
            const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count)
        {
            return compare_uint(operand1, operand2, uint64_count) < 0;
        }

        SEAL_NODISCARD inline bool is_less_than_or_equal_uint(
            const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count)
        {
            return compare_uint(operand1, operand2, uint64_count) <= 0;
        }

        SEAL_NODISCARD inline bool is_equal_uint(
            const std::uint64_t *operand1, const std::uint64_t *operand2, std::size_t uint64_count)
        {
            return compare_uint(operand1, operand2, uint64_count) == 0;
        }

        SEAL_NODISCARD inline bool is_greater_than_uint(
            const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2,
            std::size_t operand2_uint64_count)
        {
            return compare_uint(operand1, operand1_uint64_count, operand2, operand2_uint64_count) > 0;
        }

        SEAL_NODISCARD inline bool is_greater_than_or_equal_uint(
            const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2,
            std::size_t operand2_uint64_count)
        {
            return compare_uint(operand1, operand1_uint64_count, operand2, operand2_uint64_count) >= 0;
        }

        SEAL_NODISCARD inline bool is_less_than_uint(
            const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2,
            std::size_t operand2_uint64_count)
        {
            return compare_uint(operand1, operand1_uint64_count, operand2, operand2_uint64_count) < 0;
        }

        SEAL_NODISCARD inline bool is_less_than_or_equal_uint(
            const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2,
            std::size_t operand2_uint64_count)
        {
            return compare_uint(operand1, operand1_uint64_count, operand2, operand2_uint64_count) <= 0;
        }

        SEAL_NODISCARD inline bool is_equal_uint(
            const std::uint64_t *operand1, std::size_t operand1_uint64_count, const std::uint64_t *operand2,
            std::size_t operand2_uint64_count)
        {
            return compare_uint(operand1, operand1_uint64_count, operand2, operand2_uint64_count) == 0;
        }

seal/modulus.h

引用的头文件

#include "seal/serialization.h"
#include "seal/version.h"
#include "seal/util/defines.h"
#include "seal/util/hestdparms.h"
#include "seal/util/uintcore.h"
#include "seal/util/ztools.h"
#include <array>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <vector>

serialization.h 是进行序列化的类

Modulus 类

类说明

表示最多61位的整数模量。Modulus类的实例表示最多61位的非负整数模量。其中加密参数plain_modulus和coeff_modulus中的质数都用Modulus的实例表示。这个类的目的是执行和存储Barrett缩减所需的预计算。
位于 namespace seal中

namespace seal
{
    /**
    Represent an integer modulus of up to 61 bits. An instance of the Modulus
    class represents a non-negative integer modulus up to 61 bits. In particular,
    the encryption parameter plain_modulus, and the primes in coeff_modulus, are
    represented by instances of Modulus. The purpose of this class is to
    perform and store the pre-computation required by Barrett reduction.

    @par Thread Safety
    In general, reading from Modulus is thread-safe as long as no other thread
    is concurrently mutating it.

    @see EncryptionParameters for a description of the encryption parameters.
    */
    class Modulus

构造函数

注意注释,注释写得很明白
set_value 为私有成员函数

        /**
        Creates a Modulus instance. The value of the Modulus is set to
        the given value, or to zero by default.

        @param[in] value The integer modulus
        @throws std::invalid_argument if value is 1 or more than 61 bits
        */
        Modulus(std::uint64_t value = 0)
        {
            set_value(value);
        }

C++ =default和=delete

拷贝构造函数

        /**
        Creates a new Modulus by copying a given one.

        @param[in] copy The Modulus to copy from
        */
        Modulus(const Modulus &copy) = default;

        /**
        Creates a new Modulus by copying a given one.

        @param[in] source The Modulus to move from
        */
        Modulus(Modulus &&source) = default;

赋值运算符

        /**
        Copies a given Modulus to the current one.

        @param[in] assign The Modulus to copy from
        */
        Modulus &operator=(const Modulus &assign) = default;

        /**
        Moves a given Modulus to the current one.

        @param[in] assign The Modulus to move from
        */
        Modulus &operator=(Modulus &&assign) = default;

        /**
        Sets the value of the Modulus.

        @param[in] value The new integer modulus
        @throws std::invalid_argument if value is 1 or more than 61 bits
        */
        inline Modulus &operator=(std::uint64_t value)
        {
            set_value(value);
            return *this;
        }

bit_count 函数

        /**
        Returns the significant bit count of the value of the current Modulus.
        */
        SEAL_NODISCARD inline int bit_count() const noexcept
        {
            return bit_count_;
        }

uint64_count 函数

        /**
        Returns the size (in 64-bit words) of the value of the current Modulus.
        */
        SEAL_NODISCARD inline std::size_t uint64_count() const noexcept
        {
            return uint64_count_;
        }

data 函数,返回当前的模数的指针

        /**
        Returns a const pointer to the value of the current Modulus.
        */
        SEAL_NODISCARD inline const uint64_t *data() const noexcept
        {
            return &value_;
        }

value 函数,返回当前模数的值

        /**
        Returns the value of the current Modulus.
        */
        SEAL_NODISCARD inline std::uint64_t value() const noexcept
        {
            return value_;
        }

const_ratio 函数

        /**
        Returns the Barrett ratio computed for the value of the current Modulus.
        The first two components of the Barrett ratio are the floor of 2^128/value,
        and the third component is the remainder.
        */
        SEAL_NODISCARD inline auto &const_ratio() const noexcept
        {
            return const_ratio_;
        }

is_zero 函数,判断当前模数是否为0

        /**
        Returns whether the value of the current Modulus is zero.
        */
        SEAL_NODISCARD inline bool is_zero() const noexcept
        {
            return value_ == 0;
        }

is_prime 函数,判断当前模数是否为素数

        /**
        Returns whether the value of the current Modulus is a prime number.
        */
        SEAL_NODISCARD inline bool is_prime() const noexcept
        {
            return is_prime_;
        }

比较运算

        /**
        Compares two Modulus instances.

        @param[in] compare The Modulus to compare against
        */
        SEAL_NODISCARD inline bool operator==(const Modulus &compare) const noexcept
        {
            return value_ == compare.value_;
        }

        /**
        Compares a Modulus value to an unsigned integer.

        @param[in] compare The unsigned integer to compare against
        */
        SEAL_NODISCARD inline bool operator==(std::uint64_t compare) const noexcept
        {
            return value_ == compare;
        }

        /**
        Compares two Modulus instances.

        @param[in] compare The Modulus to compare against
        */
        SEAL_NODISCARD inline bool operator!=(const Modulus &compare) const noexcept
        {
            return !operator==(compare);
        }

        /**
        Compares a Modulus value to an unsigned integer.

        @param[in] compare The unsigned integer to compare against
        */
        SEAL_NODISCARD inline bool operator!=(std::uint64_t compare) const noexcept
        {
            return !operator==(compare);
        }

        /**
        Compares two Modulus instances.

        @param[in] compare The Modulus to compare against
        */
        SEAL_NODISCARD inline bool operator<(const Modulus &compare) const noexcept
        {
            return value_ < compare.value_;
        }

        /**
        Compares a Modulus value to an unsigned integer.

        @param[in] compare The unsigned integer to compare against
        */
        SEAL_NODISCARD inline bool operator<(std::uint64_t compare) const noexcept
        {
            return value_ < compare;
        }

        /**
        Compares two Modulus instances.

        @param[in] compare The Modulus to compare against
        */
        SEAL_NODISCARD inline bool operator<=(const Modulus &compare) const noexcept
        {
            return value_ <= compare.value_;
        }

        /**
        Compares a Modulus value to an unsigned integer.

        @param[in] compare The unsigned integer to compare against
        */
        SEAL_NODISCARD inline bool operator<=(std::uint64_t compare) const noexcept
        {
            return value_ <= compare;
        }

        /**
        Compares two Modulus instances.

        @param[in] compare The Modulus to compare against
        */
        SEAL_NODISCARD inline bool operator>(const Modulus &compare) const noexcept
        {
            return value_ > compare.value_;
        }

        /**
        Compares a Modulus value to an unsigned integer.

        @param[in] compare The unsigned integer to compare against
        */
        SEAL_NODISCARD inline bool operator>(std::uint64_t compare) const noexcept
        {
            return value_ > compare;
        }

        /**
        Compares two Modulus instances.

        @param[in] compare The Modulus to compare against
        */
        SEAL_NODISCARD inline bool operator>=(const Modulus &compare) const noexcept
        {
            return value_ >= compare.value_;
        }

        /**
        Compares a Modulus value to an unsigned integer.

        @param[in] compare The unsigned integer to compare against
        */
        SEAL_NODISCARD inline bool operator>=(std::uint64_t compare) const noexcept
        {
            return value_ >= compare;
        }

save_size 函数

        /**
        Returns an upper bound on the size of the Modulus, as if it was
        written to an output stream.

        @param[in] compr_mode The compression mode
        @throws std::invalid_argument if the compression mode is not supported
        @throws std::logic_error if the size does not fit in the return type
        */
        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(value_)), compr_mode);

            return util::safe_cast<std::streamoff>(util::add_safe(sizeof(Serialization::SEALHeader), members_size));
        }

save 和 load 函数

        /**
        Saves the Modulus to an output stream. The output is in binary format
        and not human-readable. The output stream must have the "binary" flag set.

        @param[out] stream The stream to save the Modulus to
        @param[in] compr_mode The desired compression mode
        @throws std::invalid_argument if the compression mode is not supported
        @throws std::logic_error if the data to be saved is invalid, or if
        compression failed
        @throws std::runtime_error if I/O operations failed
        */
        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(&Modulus::save_members, this, _1), save_size(compr_mode_type::none), stream, compr_mode,
                false);
        }

        /**
        Loads a Modulus from an input stream overwriting the current Modulus.

        @param[in] stream The stream to load the Modulus from
        @throws std::logic_error if the data cannot be loaded by this version of
        Microsoft SEAL, if the loaded data is invalid, or if decompression failed
        @throws std::runtime_error if I/O operations failed
        */
        inline std::streamoff load(std::istream &stream)
        {
            using namespace std::placeholders;
            return Serialization::Load(std::bind(&Modulus::load_members, this, _1, _2), stream, false);
        }

        /**
        Saves the Modulus to a given memory location. The output is in binary
        format and not human-readable.

        @param[out] out The memory location to write the Modulus to
        @param[in] size The number of bytes available in the given memory location
        @param[in] compr_mode The desired compression mode
        @throws std::invalid_argument if out is null or if size is too small to
        contain a SEALHeader, or if the compression mode is not supported
        @throws std::logic_error if the data to be saved is invalid, or if
        compression failed
        @throws std::runtime_error if I/O operations failed
        */
        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(&Modulus::save_members, this, _1), save_size(compr_mode_type::none), out, size, compr_mode,
                false);
        }

        /**
        Loads a Modulus from a given memory location overwriting the current
        Modulus.

        @param[in] in The memory location to load the Modulus from
        @param[in] size The number of bytes available in the given memory location
        @throws std::invalid_argument if in is null or if size is too small to
        contain a SEALHeader
        @throws std::logic_error if the data cannot be loaded by this version of
        Microsoft SEAL, if the loaded data is invalid, or if decompression failed
        @throws std::runtime_error if I/O operations failed
        */
        inline std::streamoff load(const seal_byte *in, std::size_t size)
        {
            using namespace std::placeholders;
            return Serialization::Load(std::bind(&Modulus::load_members, this, _1, _2), in, size, false);
        }

模约减运算


        /**
        Reduces a given unsigned integer modulo this modulus.

        @param[in] value The unsigned integer to reduce
        @throws std::logic_error if the Modulus is zero
        */
        SEAL_NODISCARD std::uint64_t reduce(std::uint64_t value) const;

private 成员

    private:
        void set_value(std::uint64_t value);

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

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

        std::uint64_t value_ = 0;

        std::array<std::uint64_t, 3> const_ratio_{ { 0, 0, 0 } };

        std::size_t uint64_count_ = 0;

        int bit_count_ = 0;

        bool is_prime_ = false;

set_value 实现

    void Modulus::set_value(uint64_t value)
    {
        if (value == 0)
        {
            // Zero settings
            bit_count_ = 0;
            uint64_count_ = 1;
            value_ = 0;
            const_ratio_ = { { 0, 0, 0 } };
            is_prime_ = false;
        }
        else if ((value >> SEAL_MOD_BIT_COUNT_MAX != 0) || (value == 1))
        {
            throw invalid_argument("value can be at most 61-bit and cannot be 1");
        }
        else
        {
            // All normal, compute const_ratio and set everything
            value_ = value;
            bit_count_ = get_significant_bit_count(value_);

            // Compute Barrett ratios for 64-bit words (barrett_reduce_128)
            uint64_t numerator[3]{ 0, 0, 1 };
            uint64_t quotient[3]{ 0, 0, 0 };

            // Use a special method to avoid using memory pool
            divide_uint192_inplace(numerator, value_, quotient);

            const_ratio_[0] = quotient[0];
            const_ratio_[1] = quotient[1];

            // We store also the remainder
            const_ratio_[2] = numerator[0];

            uint64_count_ = 1;

            // Set the primality flag
            is_prime_ = util::is_prime(*this);
        }
    }

reduce 实现


    uint64_t Modulus::reduce(uint64_t value) const
    {
        if (value_ == 0)
        {
            throw logic_error("cannot reduce modulo a zero modulus");
        }
        return barrett_reduce_64(value, *this);
    }

sec_level_type 枚举类型

表示根据HomomorphicEncryption.org安全标准的标准安全级别。值sec_level_type::none表示不应该施加标准安全级别。sec_level_type::tc128值提供了非常高的安全级别,并且是Microsoft SEAL在构造SEALContext对象时强制执行的默认安全级别。普通用户不应该在任何地方显式地指定安全级别。

    /**
    Represents a standard security level according to the HomomorphicEncryption.org
    security standard. The value sec_level_type::none signals that no standard
    security level should be imposed. The value sec_level_type::tc128 provides
    a very high level of security and is the default security level enforced by
    Microsoft SEAL when constructing a SEALContext object. Normal users should not
    have to specify the security level explicitly anywhere.
    */
    enum class sec_level_type : int
    {
        /**
        No security level specified.
        */
        none = 0,

        /**
        128-bit security level according to HomomorphicEncryption.org standard.
        */
        tc128 = 128,

        /**
        192-bit security level according to HomomorphicEncryption.org standard.
        */
        tc192 = 192,

        /**
        256-bit security level according to HomomorphicEncryption.org standard.
        */
        tc256 = 256
    };

CoeffModulus 类

该类包含用于轻松创建系数模数的静态方法。注意,虽然这些函数接受一个sec_level_type参数,但如果输出与加密参数(poly_modulus_degree的值不匹配)一起使用,那么所有的安全保证都将丢失。

默认值sec_level_type::tc128提供了非常高的安全级别,并且是Microsoft SEAL在构造SEALContext对象时强制执行的默认安全级别。普通用户不应该在任何地方显式地指定安全级别。

默认构造

CoeffModulus() = delete;

MaxBitCount 函数

根据HomomorphicEncryption.org安全标准,返回系数模数的最大位长,即系数模数中质数乘积的位长,在使用给定的poly_modulus_degree时保证给定的安全级别。

        /**
        Returns the largest bit-length of the coefficient modulus, i.e., bit-length
        of the product of the primes in the coefficient modulus, that guarantees
        a given security level when using a given poly_modulus_degree, according
        to the HomomorphicEncryption.org security standard.

        @param[in] poly_modulus_degree The value of the poly_modulus_degree
        encryption parameter
        @param[in] sec_level The desired standard security level
        */
        SEAL_NODISCARD static constexpr int MaxBitCount(
            std::size_t poly_modulus_degree, sec_level_type sec_level = sec_level_type::tc128) noexcept
        {
            switch (sec_level)
            {
            case sec_level_type::tc128:
                return util::seal_he_std_parms_128_tc(poly_modulus_degree);

            case sec_level_type::tc192:
                return util::seal_he_std_parms_192_tc(poly_modulus_degree);

            case sec_level_type::tc256:
                return util::seal_he_std_parms_256_tc(poly_modulus_degree);

            case sec_level_type::none:
                return (std::numeric_limits<int>::max)();

            default:
                return 0;
            }
        }

BFVDefault 函数

    Returns a default coefficient modulus for the BFV scheme that guarantees
    a given security level when using a given poly_modulus_degree, according
    to the HomomorphicEncryption.org security standard. Note that all security
    guarantees are lost if the output is used with encryption parameters with
    a mismatching value for the poly_modulus_degree.
        /**
        Returns a default coefficient modulus for the BFV scheme that guarantees
        a given security level when using a given poly_modulus_degree, according
        to the HomomorphicEncryption.org security standard. Note that all security
        guarantees are lost if the output is used with encryption parameters with
        a mismatching value for the poly_modulus_degree.

        The coefficient modulus returned by this function will not perform well
        if used with the CKKS scheme.

        @param[in] poly_modulus_degree The value of the poly_modulus_degree
        encryption parameter
        @param[in] sec_level The desired standard security level
        @throws std::invalid_argument if poly_modulus_degree is not a power-of-two
        or is too large
        @throws std::invalid_argument if sec_level is sec_level_type::none
        */
        SEAL_NODISCARD static std::vector<Modulus> BFVDefault(
            std::size_t poly_modulus_degree, sec_level_type sec_level = sec_level_type::tc128);

Create 函数

    Returns a custom coefficient modulus suitable for use with the specified
    poly_modulus_degree. The return value will be a vector consisting of
    Modulus elements representing distinct prime numbers such that:
    1) have bit-lengths as given in the bit_sizes parameter (at most 60 bits) and
    2) are congruent to 1 modulo 2*poly_modulus_degree.
        /**
        Returns a custom coefficient modulus suitable for use with the specified
        poly_modulus_degree. The return value will be a vector consisting of
        Modulus elements representing distinct prime numbers such that:
        1) have bit-lengths as given in the bit_sizes parameter (at most 60 bits) and
        2) are congruent to 1 modulo 2*poly_modulus_degree.

        @param[in] poly_modulus_degree The value of the poly_modulus_degree
        encryption parameter
        @param[in] bit_sizes The bit-lengths of the primes to be generated
        @throws std::invalid_argument if poly_modulus_degree is not a power-of-two
        or is too large
        @throws std::invalid_argument if bit_sizes is too large or if its elements
        are out of bounds
        @throws std::logic_error if not enough suitable primes could be found
        */
        SEAL_NODISCARD static std::vector<Modulus> Create(std::size_t poly_modulus_degree, std::vector<int> bit_sizes);

Create 函数,比上一个多了一个参数

        /**
        Returns a custom coefficient modulus suitable for use with the specified
        poly_modulus_degree. The return value will be a vector consisting of
        Modulus elements representing distinct prime numbers such that:
        1) have bit-lengths as given in the bit_sizes parameter (at most 60 bits) and
        2) are congruent to 1 modulo LCM(2*poly_modulus_degree, plain_modulus).

        @param[in] poly_modulus_degree The value of the poly_modulus_degree encryption parameter
        @param[in] plain_modulus The value of the plain_modulus encryption parameter
        @param[in] bit_sizes The bit-lengths of the primes to be generated
        @throws std::invalid_argument if poly_modulus_degree is not a power-of-two
        or is too large
        @throws std::invalid_argument if bit_sizes is too large or if its elements
        are out of bounds
        @throws std::logic_error if LCM(2*poly_modulus_degree, plain_modulus) is more than 64-bit
        @throws std::logic_error if not enough suitable primes could be found
        */
        SEAL_NODISCARD static std::vector<Modulus> Create(
            std::size_t poly_modulus_degree, const Modulus &plain_modulus, std::vector<int> bit_sizes);

BFVDefault 函数实现

    vector<Modulus> CoeffModulus::BFVDefault(size_t poly_modulus_degree, sec_level_type sec_level)
    {
        if (!MaxBitCount(poly_modulus_degree, sec_level))
        {
            throw invalid_argument("non-standard poly_modulus_degree");
        }
        if (sec_level == sec_level_type::none)
        {
            throw invalid_argument("invalid security level");
        }

        switch (sec_level)
        {
        case sec_level_type::tc128:
            return global_variables::GetDefaultCoeffModulus128().at(poly_modulus_degree);

        case sec_level_type::tc192:
            return global_variables::GetDefaultCoeffModulus192().at(poly_modulus_degree);

        case sec_level_type::tc256:
            return global_variables::GetDefaultCoeffModulus256().at(poly_modulus_degree);

        default:
            throw runtime_error("invalid security level");
        }
    }

Create(size_t poly_modulus_degree, vector< int> bit_sizes) 函数实现

    vector<Modulus> CoeffModulus::Create(size_t poly_modulus_degree, vector<int> bit_sizes)
    {
        if (poly_modulus_degree > SEAL_POLY_MOD_DEGREE_MAX || poly_modulus_degree < SEAL_POLY_MOD_DEGREE_MIN ||
            get_power_of_two(static_cast<uint64_t>(poly_modulus_degree)) < 0)
        {
            throw invalid_argument("poly_modulus_degree is invalid");
        }
        if (bit_sizes.size() > SEAL_COEFF_MOD_COUNT_MAX)
        {
            throw invalid_argument("bit_sizes is invalid");
        }
        if (accumulate(
                bit_sizes.cbegin(), bit_sizes.cend(), SEAL_USER_MOD_BIT_COUNT_MIN,
                [](int a, int b) { return max(a, b); }) > SEAL_USER_MOD_BIT_COUNT_MAX ||
            accumulate(bit_sizes.cbegin(), bit_sizes.cend(), SEAL_USER_MOD_BIT_COUNT_MAX, [](int a, int b) {
                return min(a, b);
            }) < SEAL_USER_MOD_BIT_COUNT_MIN)
        {
            throw invalid_argument("bit_sizes is invalid");
        }

        unordered_map<int, size_t> count_table;
        unordered_map<int, vector<Modulus>> prime_table;
        for (int size : bit_sizes)
        {
            ++count_table[size];
        }

        uint64_t factor = mul_safe(uint64_t(2), safe_cast<uint64_t>(poly_modulus_degree));
        for (const auto &table_elt : count_table)
        {
            prime_table[table_elt.first] = get_primes(factor, table_elt.first, table_elt.second);
        }

        vector<Modulus> result;
        for (int size : bit_sizes)
        {
            result.emplace_back(prime_table[size].back());
            prime_table[size].pop_back();
        }
        return result;
    }

Create(size_t poly_modulus_degree, const Modulus &plain_modulus, vector< int > bit_sizes) 函数实现

    vector<Modulus> CoeffModulus::Create(
        size_t poly_modulus_degree, const Modulus &plain_modulus, vector<int> bit_sizes)
    {
        if (poly_modulus_degree > SEAL_POLY_MOD_DEGREE_MAX || poly_modulus_degree < SEAL_POLY_MOD_DEGREE_MIN ||
            get_power_of_two(static_cast<uint64_t>(poly_modulus_degree)) < 0)
        {
            throw invalid_argument("poly_modulus_degree is invalid");
        }
        if (bit_sizes.size() > SEAL_COEFF_MOD_COUNT_MAX)
        {
            throw invalid_argument("bit_sizes is invalid");
        }
        if (accumulate(
                bit_sizes.cbegin(), bit_sizes.cend(), SEAL_USER_MOD_BIT_COUNT_MIN,
                [](int a, int b) { return max(a, b); }) > SEAL_USER_MOD_BIT_COUNT_MAX ||
            accumulate(bit_sizes.cbegin(), bit_sizes.cend(), SEAL_USER_MOD_BIT_COUNT_MAX, [](int a, int b) {
                return min(a, b);
            }) < SEAL_USER_MOD_BIT_COUNT_MIN)
        {
            throw invalid_argument("bit_sizes is invalid");
        }

        unordered_map<int, size_t> count_table;
        unordered_map<int, vector<Modulus>> prime_table;
        for (int size : bit_sizes)
        {
            ++count_table[size];
        }

        uint64_t factor = mul_safe(uint64_t(2), safe_cast<uint64_t>(poly_modulus_degree));
        factor = mul_safe(factor, plain_modulus.value() / gcd(plain_modulus.value(), factor));  // 计算的是 LCM(factor,plain_modulus)
        for (const auto &table_elt : count_table)
        {
            prime_table[table_elt.first] = get_primes(factor, table_elt.first, table_elt.second);
        }

        vector<Modulus> result;
        for (int size : bit_sizes)
        {
            result.emplace_back(prime_table[size].back());
            prime_table[size].pop_back();
        }
        return result;
    }

PlainModulus 类

该类包含用于轻松创建明文模数的静态方法。

默认构造函数

        PlainModulus() = delete;

Batching 函数

Creates a prime number Modulus for use as plain_modulus encryption parameter that supports batching with a given poly_modulus_degree.

        /**
        Creates a prime number Modulus for use as plain_modulus encryption
        parameter that supports batching with a given poly_modulus_degree.

        @param[in] poly_modulus_degree The value of the poly_modulus_degree
        encryption parameter
        @param[in] bit_size The bit-length of the prime to be generated
        @throws std::invalid_argument if poly_modulus_degree is not a power-of-two
        or is too large
        @throws std::invalid_argument if bit_size is out of bounds
        @throws std::logic_error if a suitable prime could not be found
        */
        SEAL_NODISCARD static inline Modulus Batching(std::size_t poly_modulus_degree, int bit_size)
        {
            return CoeffModulus::Create(poly_modulus_degree, { bit_size })[0];
        }

Batching 函数,返回一个模数数组而不是一个模数

Creates several prime number Modulus elements that can be used as plain_modulus encryption parameters, each supporting batching with a given poly_modulus_degree.

        /**
        Creates several prime number Modulus elements that can be used as
        plain_modulus encryption parameters, each supporting batching with a given
        poly_modulus_degree.

        @param[in] poly_modulus_degree The value of the poly_modulus_degree
        encryption parameter
        @param[in] bit_sizes The bit-lengths of the primes to be generated
        @throws std::invalid_argument if poly_modulus_degree is not a power-of-two
        or is too large
        @throws std::invalid_argument if bit_sizes is too large or if its elements
        are out of bounds
        @throws std::logic_error if not enough suitable primes could be found
        */
        SEAL_NODISCARD static inline std::vector<Modulus> Batching(
            std::size_t poly_modulus_degree, std::vector<int> bit_sizes)
        {
            return CoeffModulus::Create(poly_modulus_degree, bit_sizes);
        }

注:modulus.cpp 引用了以下头文件:

#include "seal/modulus.h"
#include "seal/util/common.h"
#include "seal/util/numth.h"
#include "seal/util/uintarith.h"
#include "seal/util/uintarithsmallmod.h"
#include <numeric>
#include <stdexcept>
#include <unordered_map>
 类似资料: