SEAL开源库源码02
本篇的最终目的是要分析 seal/modulus.h
文章目录
- SEAL开源库源码02
-
- seal/version.h
- seal/util/hestdparms.h
- seal/util/common.h
-
- VoidType结构体 和 seal_void_t类型
- seal_for_each_n函数
- seal_apply_impl 和 seal_apply 函数
- IsUInt64 结构体
- IsUint32结构体
- 一些 unsigned 比较运算
- 一些安全的加减乘运算
- fits_in 函数,判断类型是否兼容
- sum_fits_in 函数,判断参数的和是否与 T 类型兼容
- product_fits_in 函数,判断参数的积是否与 T 类型兼容
- safe_cast 函数,安全类型转换
- 一些常量
- hamming_weight 函数,计算汉明权重
- reverse_bits 函数,反转比特
- get_msb_index_generic 函数,返回最高位的 index
- get_significant_bit_count 函数,获取有效位数
- is_hex_char 函数,判断一个字符是否是 16 进制字符
- nibble_to_upper_hex 函数,将一个int类型的十六进制数转换为char类型
- hex_to_nibble 函数,上一个的逆过程
- get_hex_string_bit_count 函数,返回十六进制数的比特长度
- divide_round_up 函数,四舍五入除法运算
- epsilon 常量,double类型
- are_close 函数,判断两个数是否足够接近
- is_zero 函数,判断参数是否为 0
- seal_memzero 函数,唯一不是 inline 的函数,在 cpp 文件中实现
- seal/util/common.cpp
- seal/util/globals.h
- seal/util/globals.cpp
- seal/util/lock.h
- seal/util/memorypool.h
- seal/util.pointer.h
- seal/util/ztools.h
seal/version.h
保存版本号信息
具有相同主版本和小版本的库的两个版本完全兼容。它们保证具有相同的公共API。补丁版本号的变化表明完全是内部变化,比如不需要修改公共API的bug修复。微调版本号目前没有使用,预计为0。
#pragma once
#include "seal/util/defines.h"
#include <cstdint>
namespace seal
{
/**
Holds Microsoft SEAL version information. A SEALVersion contains four values:
1. The major version number;
2. The minor version number;
3. The patch version number;
4. The tweak version number.
Two versions of the library with the same major and minor versions are fully
compatible with each other. They are guaranteed to have the same public API.
Changes in the patch version number indicate totally internal changes, such
as bug fixes that require no changes to the public API. The tweak version
number is currently not used, and is expected to be 0.
*/
struct SEALVersion
{
/**
Holds the major version number.
*/
std::uint8_t major = SEAL_VERSION_MAJOR;
/**
Holds the minor version number.
*/
std::uint8_t minor = SEAL_VERSION_MINOR;
/**
Holds the patch version number.
*/
std::uint8_t patch = SEAL_VERSION_PATCH;
std::uint8_t tweak = 0;
};
} // namespace seal
seal/util/hestdparms.h
定义了一些基于不同安全性的参数选择。
Largest allowed bit counts for coeff_modulus based on the security estimates from HomomorphicEncryption.org security standard. Microsoft SEAL samples the secret key from a ternary {-1, 0, 1} distribution.
位于命名空间seal中的命名空间util中
/**
Largest allowed bit counts for coeff_modulus based on the security estimates from
HomomorphicEncryption.org security standard. Microsoft SEAL samples the secret key
from a ternary {-1, 0, 1} distribution.
*/
128-bit 安全性
// Ternary secret; 128 bits classical security
SEAL_NODISCARD constexpr int seal_he_std_parms_128_tc(std::size_t poly_modulus_degree) noexcept
{
switch (poly_modulus_degree)
{
case std::size_t(1024):
return 27;
case std::size_t(2048):
return 54;
case std::size_t(4096):
return 109;
case std::size_t(8192):
return 218;
case std::size_t(16384):
return 438;
case std::size_t(32768):
return 881;
}
return 0;
}
192-bit安全性
// Ternary secret; 192 bits classical security
SEAL_NODISCARD constexpr int seal_he_std_parms_192_tc(std::size_t poly_modulus_degree) noexcept
{
switch (poly_modulus_degree)
{
case std::size_t(1024):
return 19;
case std::size_t(2048):
return 37;
case std::size_t(4096):
return 75;
case std::size_t(8192):
return 152;
case std::size_t(16384):
return 305;
case std::size_t(32768):
return 611;
}
return 0;
}
256-bit安全性
// Ternary secret; 256 bits classical security
SEAL_NODISCARD constexpr int seal_he_std_parms_256_tc(std::size_t poly_modulus_degree) noexcept
{
switch (poly_modulus_degree)
{
case std::size_t(1024):
return 14;
case std::size_t(2048):
return 29;
case std::size_t(4096):
return 58;
case std::size_t(8192):
return 118;
case std::size_t(16384):
return 237;
case std::size_t(32768):
return 476;
}
return 0;
}
128-bit量子安全性
// Ternary secret; 128 bits quantum security
SEAL_NODISCARD constexpr int seal_he_std_parms_128_tq(std::size_t poly_modulus_degree) noexcept
{
switch (poly_modulus_degree)
{
case std::size_t(1024):
return 25;
case std::size_t(2048):
return 51;
case std::size_t(4096):
return 101;
case std::size_t(8192):
return 202;
case std::size_t(16384):
return 411;
case std::size_t(32768):
return 827;
}
return 0;
}
192-bit量子安全性
// Ternary secret; 192 bits quantum security
SEAL_NODISCARD constexpr int seal_he_std_parms_192_tq(std::size_t poly_modulus_degree) noexcept
{
switch (poly_modulus_degree)
{
case std::size_t(1024):
return 17;
case std::size_t(2048):
return 35;
case std::size_t(4096):
return 70;
case std::size_t(8192):
return 141;
case std::size_t(16384):
return 284;
case std::size_t(32768):
return 571;
}
return 0;
}
256-bit量子安全性
// Ternary secret; 256 bits quantum security
SEAL_NODISCARD constexpr int seal_he_std_parms_256_tq(std::size_t poly_modulus_degree) noexcept
{
switch (poly_modulus_degree)
{
case std::size_t(1024):
return 13;
case std::size_t(2048):
return 27;
case std::size_t(4096):
return 54;
case std::size_t(8192):
return 109;
case std::size_t(16384):
return 220;
case std::size_t(32768):
return 443;
}
return 0;
}
误差分布的标准差
定义为常量 3.2 3.2 3.2
// Standard deviation for error distribution
constexpr double seal_he_std_parms_error_std_dev = 3.2;
seal/util/common.h
里面定义的所有函数位于namespace seal中的namespace util中
VoidType结构体 和 seal_void_t类型
template <typename... Ts>
struct VoidType
{
using type = void;
};
template <typename... Ts>
using seal_void_t = typename VoidType<Ts...>::type;
seal_for_each_n函数
传入迭代器 first 和 大小 size 和 要执行的函数 func,对每个执行 func 函数
template <typename ForwardIt, typename Size, typename Func>
inline ForwardIt seal_for_each_n(ForwardIt first, Size size, Func &&func)
{
for (; size--; (void)++first)
{
func(*first);
}
return first;
}
seal_apply_impl 和 seal_apply 函数
std::forward通常是用于完美转发的,它会将输入的参数原封不动地传递到下一个函数中,这个“原封不动”指的是,如果输入的参数是左值,那么传递给下一个函数的参数的也是左值;如果输入的参数是右值,那么传递给下一个函数的参数的也是右值。
大概意思就是对 tuple 中 index 元素执行 func 函数,然后返回执行结果。
std::Tuple
函数中的 Tuple 不一定是 std::Tuple
template <typename Func, typename Tuple, std::size_t... Is>
inline decltype(auto) seal_apply_impl(Func &&func, Tuple &&tp, std::index_sequence<Is...>)
{
return func(std::get<Is>(std::forward<Tuple>(tp))...);
}
template <typename Func, typename Tuple, std::size_t... Is>
inline decltype(auto) seal_apply(Func &&func, Tuple &&tp)
{
using iseq_t = std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>;
return seal_apply_impl(std::forward<Func>(func), std::forward<Tuple>(tp), iseq_t{
});
}
IsUInt64 结构体
判断是否是 unsigned int64 类型
template <typename T, typename...>
struct IsUInt64
: std::conditional<
std::is_integral<T>::value && std::is_unsigned<T>::value && (sizeof(T) == sizeof(std::uint64_t)),
std::true_type, std::false_type>::type
{
};
template <typename T, typename U, typename... Rest>
struct IsUInt64<T, U, Rest...>
: std::conditional<IsUInt64<T>::value && IsUInt64<U, Rest...>::value, std::true_type, std::false_type>::type
{
};
template <typename T, typename... Rest>
constexpr bool is_uint64_v = IsUInt64<T, Rest...>::value;
IsUint32结构体
判断是否为 unsigned int32 类型
template <typename T, typename...>
struct IsUInt32
: std::conditional<
std::is_integral<T>::value && std::is_unsigned<T>::value && (sizeof(T) == sizeof(std::uint32_t)),
std::true_type, std::false_type>::type
{
};
template <typename T, typename U, typename... Rest>
struct IsUInt32<T, U, Rest...>
: std::conditional<IsUInt32<T>::value && IsUInt32<U, Rest...>::value, std::true_type, std::false_type>::type
{
};
template <typename T, typename... Rest>
constexpr bool is_uint32_v = IsUInt32<T, Rest...>::value;
一些 unsigned 比较运算
包括小于、小于等于、大于、大于等于、等于、不等于
template <
typename T, typename S, typename = std::enable_if_t<std::is_integral<T>::value>,
typename = std::enable_if_t<std::is_integral<S>::value>>
SEAL_NODISCARD inline constexpr bool unsigned_lt(T in1, S in2) noexcept
{
return static_cast<std::uint64_t>(in1) < static_cast<std::uint64_t>(in2);
}
template <
typename T, typename S, typename = std::enable_if_t<std::is_integral<T>::value>,
typename = std::enable_if_t<std::is_integral<S>::value>>
SEAL_NODISCARD inline constexpr bool unsigned_leq(T in1, S in2) noexcept
{
return static_cast<std::uint64_t>(in1) <= static_cast<std::uint64_t>(in2);
}
template <
typename T, typename S, typename = std::enable_if_t<std::is_integral<T>::value>,
typename = std::enable_if_t<std::is_integral<S>::value>>
SEAL_NODISCARD inline constexpr bool unsigned_gt(T in1, S in2) noexcept
{
return static_cast<std::uint64_t>(in1) > static_cast<std::uint64_t>(in2);
}
template <
typename T, typename S, typename = std::enable_if_t<std::is_integral<T>::value>,
typename = std::enable_if_t<std::is_integral<S>::value>>
SEAL_NODISCARD inline constexpr bool unsigned_geq(T in1, S in2) noexcept
{
return static_cast<std::uint64_t>(in1) >= static_cast<std::uint64_t>(in2);
}
template <
typename T, typename S, typename = std::enable_if_t<std::is_integral<T>::value>,
typename = std::enable_if_t<std::is_integral<S>::value>>
SEAL_NODISCARD inline constexpr bool unsigned_eq(T in1, S in2) noexcept
{
return static_cast<std::uint64_t>(in1) == static_cast<std::uint64_t>(in2);
}
template <
typename T, typename S, typename = std::enable_if_t<std::is_integral<T>::value>,
typename = std::enable_if_t<std::is_integral<S>::value>>
SEAL_NODISCARD inline constexpr bool unsigned_neq(T in1, S in2) noexcept
{
return static_cast<std::uint64_t>(in1) != static_cast<std::uint64_t>(in2);
}
一些安全的加减乘运算
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
SEAL_NODISCARD inline constexpr T mul_safe(T in1) noexcept
{
return in1;
}
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
SEAL_NODISCARD inline constexpr T mul_safe(T in1, T in2)
{
SEAL_IF_CONSTEXPR(std::is_unsigned<T>::value)
{
if (in1 && (in2 > (std::numeric_limits<T>::max)() / in1))
{
throw std::logic_error("unsigned overflow");
}
}
else
{
// Positive inputs
if ((in1 > 0) && (in2 > 0) && (in2 > (std::numeric_limits<T>::max)() / in1))
{
throw std::logic_error("signed overflow");
}
#if (SEAL_COMPILER == SEAL_COMPILER_MSVC) && !defined(SEAL_USE_IF_CONSTEXPR)
#pragma warning(push)
#pragma warning(disable : 4146)
#endif
// Negative inputs
else if ((in1 < 0) && (in2 < 0) && ((-in2) > (std::numeric_limits<T>::max)() / (-in1)))
{
throw std::logic_error("signed overflow");
}
// Negative in1; positive in2
else if ((in1 < 0) && (in2 > 0) && (in2 > (std::numeric_limits<T>::max)() / (-in1)))
{
throw std::logic_error("signed underflow");
}
#if (SEAL_COMPILER == SEAL_COMPILER_MSVC) && !defined(SEAL_USE_IF_CONSTEXPR)
#pragma warning(pop)
#endif
// Positive in1; negative in2
else if ((in1 > 0) && (in2 < 0) && (in2 < (std::numeric_limits<T>::min)() / in1))
{
throw std::logic_error("signed underflow");
}
}
return static_cast<T>(in1 * in2);
}
template <typename T, typename... Args, typename = std::enable_if_t<std::is_integral<T>::value>>
SEAL_NODISCARD inline constexpr T mul_safe(T in1, T in2, Args &&...args)
{
return mul_safe(mul_safe(in1, in2), mul_safe(std::forward<Args>(args)...));
}
template <typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
SEAL_NODISCARD inline constexpr T add_safe(T in1) noexcept
{
return in1;
}
template <typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
SEAL_NODISCARD inline constexpr T add_safe(T in1, T in2)
{
SEAL_IF_CONSTEXPR(std::is_unsigned<T>::value)
{
if (in2 > (std::numeric_limits<T>::max)() - in1)
{
throw std::logic_error("unsigned overflow");
}
}
else
{
if (in1 > 0 && (in2 > (std::numeric_limits<T>::max)() - in1))
{
throw std::logic_error("signed overflow");
}
else if (in1 < 0 && (in2 < (std::numeric_limits<T>::min)() - in1))
{
throw std::logic_error("signed underflow");
}
}
return static_cast<T>(in1 + in2);
}
template <typename T, typename... Args, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
SEAL_NODISCARD inline constexpr T add_safe(T in1, T in2, Args &&...args)
{
return add_safe(add_safe(in1, in2), add_safe(std::forward<Args>(args)...));
}
template <typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
SEAL_NODISCARD inline T sub_safe(T in1, T in2)
{
SEAL_IF_CONSTEXPR(std::is_unsigned<T>::value)
{
if (in1 < in2)
{
throw std::logic_error("unsigned underflow");
}
}
else
{
if (in1 < 0 && (in2 > (std::numeric_limits<T>::max)() + in1))
{
throw std::logic_error("signed underflow");
}
else if (in1 > 0 && (in2 < (std::numeric_limits<T>::min)() + in1))
{
throw std::logic_error("signed overflow");
}
}
return static_cast<T>(in1 - in2);
}
fits_in 函数,判断类型是否兼容
template <
typename T, typename S, typename = std::enable_if_t<std::is_arithmetic<T>::value>,
typename = std::enable_if_t<std::is_arithmetic<S>::value>>
SEAL_NODISCARD inline constexpr bool fits_in(S value SEAL_MAYBE_UNUSED) noexcept
{
bool result = false;
SEAL_IF_CONSTEXPR(std::is_same<T, S>::value)
{
// Same type
result = true;
}
else SEAL_IF_CONSTEXPR(sizeof(S) <= sizeof(T))
{
// Converting to bigger type
SEAL_IF_CONSTEXPR(std::is_integral<T>::value && std::is_integral<S>::value)
{
// Converting to at least equally big integer type
SEAL_IF_CONSTEXPR(
(std::is_unsigned<T>::value && std::is_unsigned<S>::value) ||
(!std::is_unsigned<T>::value && !std::is_unsigned<S>::value))
{
<