Git Product home page Git Product logo

seal's Introduction

Microsoft SEAL

Microsoft SEAL is an easy-to-use open-source (MIT licensed) homomorphic encryption library developed by the Cryptography and Privacy Research Group at Microsoft. Microsoft SEAL is written in modern standard C++ and is easy to compile and run in many different environments. For more information about the Microsoft SEAL project, see sealcrypto.org.

This document pertains to Microsoft SEAL version 4.1. Users of previous versions of the library should look at the list of changes.

News

The BGV scheme is now available in Microsoft SEAL. Implementation details are described in this paper. We truly appreciate Alibaba Gemini Lab for making massive efforts to develop the BGV scheme and integrate it in Microsoft SEAL. And we would like to thank Privacy Technologies Research, Intel Labs, for continuous testing and reporting issues.

Starting from version 3.7.2, Microsoft SEAL will push new changes to the main, master, and contrib branches without creating a new version. We adopt this approach to merge community contribution and resolve issues in a timely manner. These branches will stay ahead of the latest version branch/tag. New versions will be created when there are important bug fixes or new features.

The EVA compiler for CKKS is available at GitHub.com/Microsoft/EVA. See CKKS Programming with EVA below for more information.

The SEAL-Embedded for CKKS Encryption is available at Github.com/Microsoft/SEAL-Embedded.

The APSI library for Asymmetric PSI is available at Github.com/Microsoft/APSI.

Contents

Introduction

Core Concepts

Most encryption schemes consist of three functionalities: key generation, encryption, and decryption. Symmetric-key encryption schemes use the same secret key for both encryption and decryption; public-key encryption schemes use separately a public key for encryption and a secret key for decryption. Therefore, public-key encryption schemes allow anyone who knows the public key to encrypt data, but only those who know the secret key can decrypt and read the data. Symmetric-key encryption can be used for efficiently encrypting very large amounts of data, and enables secure outsourced cloud storage. Public-key encryption is a fundamental concept that enables secure online communication today, but is typically much less efficient than symmetric-key encryption.

While traditional symmetric- and public-key encryption can be used for secure storage and communication, any outsourced computation will necessarily require such encryption layers to be removed before computation can take place. Therefore, cloud services providing outsourced computation capabilities must have access to the secret keys, and implement access policies to prevent unauthorized employees from getting access to these keys.

Homomorphic Encryption

Homomorphic encryption refers to encryption schemes that allow the cloud to compute directly on the encrypted data, without requiring the data to be decrypted first. The results of such encrypted computations remain encrypted, and can be only decrypted with the secret key (by the data owner). Multiple homomorphic encryption schemes with different capabilities and trade-offs have been invented over the past decade; most of these are public-key encryption schemes, although the public-key functionality may not always be needed.

Homomorphic encryption is not a generic technology: only some computations on encrypted data are possible. It also comes with a substantial performance overhead, so computations that are already very costly to perform on unencrypted data are likely to be infeasible on encrypted data. Moreover, data encrypted with homomorphic encryption is many times larger than unencrypted data, so it may not make sense to encrypt, e.g., entire large databases, with this technology. Instead, meaningful use-cases are in scenarios where strict privacy requirements prohibit unencrypted cloud computation altogether, but the computations themselves are fairly lightweight.

Typically, homomorphic encryption schemes have a single secret key which is held by the data owner. For scenarios where multiple different private data owners wish to engage in collaborative computation, homomorphic encryption is probably not a reasonable solution.

Homomorphic encryption cannot be used to enable data scientists to circumvent GDPR. For example, there is no way for a cloud service to use homomorphic encryption to draw insights from encrypted customer data. Instead, results of encrypted computations remain encrypted and can only be decrypted by the owner of the data, e.g., a cloud service customer.

Most homomorphic encryption schemes provide weaker security guarantees than traditional encryption schemes. You need to read SECURITY.md if you are thinking of building production software using Microsoft SEAL.

Microsoft SEAL

Microsoft SEAL is a homomorphic encryption library that allows additions and multiplications to be performed on encrypted integers or real numbers. Other operations, such as encrypted comparison, sorting, or regular expressions, are in most cases not feasible to evaluate on encrypted data using this technology. Therefore, only specific privacy-critical cloud computation parts of programs should be implemented with Microsoft SEAL.

It is not always easy or straightforward to translate an unencrypted computation into a computation on encrypted data, for example, it is not possible to branch on encrypted data. Microsoft SEAL itself has a steep learning curve and requires the user to understand many homomorphic encryption specific concepts, even though in the end the API is not too complicated. Even if a user is able to program and run a specific computation using Microsoft SEAL, the difference between efficient and inefficient implementations can be several orders of magnitude, and it can be hard for new users to know how to improve the performance of their computation.

Microsoft SEAL comes with two different homomorphic encryption schemes with very different properties. The BFV and BGV schemes allow modular arithmetic to be performed on encrypted integers. The CKKS scheme allows additions and multiplications on encrypted real or complex numbers, but yields only approximate results. In applications such as summing up encrypted real numbers, evaluating machine learning models on encrypted data, or computing distances of encrypted locations CKKS is going to be by far the best choice. For applications where exact values are necessary, the BFV and BGV schemes are more suitable.

Getting Started

There are multiple ways of installing Microsoft SEAL and starting to use it. The easiest way is to use a package manager to download, build, and install the library. For example, vcpkg works on most platforms and will be up-to-date with the latest release of Microsoft SEAL (C++17 only). On macOS you can also use Homebrew. On FreeBSD you can use pkg install seal to install security/seal. The .NET library is available as a multiplatform NuGet package. Finally, one can build Microsoft SEAL manually with a multiplatform CMake build system; see Building Microsoft SEAL Manually for details.

Optional Dependencies

Microsoft SEAL has no required dependencies, but certain optional features can be enabled when compiling with support for specific third-party libraries.

When building manually, one can choose to have the Microsoft SEAL build system download and build the dependencies, or alternatively search the system directories for pre-installed dependencies. On the other extreme, the downloadable NuGet package cannot be configured at all, but it is always possible to build a custom NuGet package. Other package managers offer varying amounts of opportunities for configuring the dependencies and other build options.

The optional dependencies and their tested versions (other versions may work as well) are as follows:

Optional dependency Tested version Use
Intel HEXL 1.2.5 Acceleration of low-level kernels
Microsoft GSL 4.0.0 API extensions
ZLIB 1.2.13 Compressed serialization
Zstandard 1.5.2 Compressed serialization (much faster than ZLIB)
GoogleTest 1.12.1 For running tests
GoogleBenchmark 1.7.1 For running benchmarks

Intel HEXL

Intel HEXL is a library providing efficient implementations of cryptographic primitives common in homomorphic encryption. The acceleration is particularly evident on Intel processors with the Intel AVX512-IFMA52 instruction set.

Microsoft GSL

Microsoft GSL (Guidelines Support Library) is a header-only library that implements gsl::span: a view type that provides safe (bounds-checked) array access to memory.

For example, if Microsoft GSL is available, Microsoft SEAL can allow BatchEncoder and CKKSEncoder to encode from and decode to a gsl::span instead of std::vector, which can in some cases have a significant performance benefit.

ZLIB and Zstandard

ZLIB and Zstandard are widely used compression libraries. Microsoft SEAL can optionally use these libraries to compress data that is serialized.

One may ask how compression can help when ciphertext and key data is supposed to be indistinguishable from random. In Microsoft SEAL Ciphertext objects consist of a large number of integers modulo specific prime numbers (coeff_modulus primes). When using the CKKS scheme in particular, these prime numbers can be quite small (e.g., 30 bits), but the data is nevertheless serialized as 64-bit integers. Therefore, it is not uncommon that almost half of the ciphertext bytes are zeros, and applying a general-purpose compression algorithm is a convenient way of getting rid this wasted space. The BFV scheme benefits typically less from this technique, because the prime numbers used for the coeff_modulus encryption parameter tend to be larger, and integers modulo these prime numbers fill more of each 64-bit word. Compressed serialization can be applied to any serializable Microsoft SEAL object – not just to Ciphertext and keys .

If Microsoft SEAL is compiled with ZLIB or Zstandard support, compression will automatically be used for serialization; see Serialization::compr_mode_default in native/src/seal/serialization.h. However, it is always possible to explicitly pass compr_mode_type::none to serialization methods to disable compression. If both ZLIB and Zstandard support are enabled, Zstandard is used by default due to its much better performance.

Note: The compression rate for a SecretKey can (in theory at least) reveal information about the key. In most common applications of Microsoft SEAL the size of a SecretKey would not be deliberately revealed to untrusted parties. If this is a concern, one can always save the SecretKey in an uncompressed form.

Installing from NuGet Package (Windows, Linux, macOS, Android, iOS)

For .NET developers the easiest way of installing Microsoft SEAL is by using the multiplatform NuGet package available at NuGet.org. Simply add this package into your .NET project as a dependency and you are ready to go.

To develop mobile applications using Microsoft SEAL and .NET for Android and iOS, just add this package to your Xamarin project. Unlike the Microsoft SEAL C++ library, the .NET wrapper library works only on 64-bit platforms, so only arm64-v8a/x86_64 Android ABIs and arm64/x86_64 iOS architectures are supported.

Installing from vcpkg

You can download and install seal using the vcpkg dependency manager.

git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh  # ./bootstrap-vcpkg.bat for Windows
./vcpkg integrate install
./vcpkg install seal

The "seal" port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository.

Examples

Using Microsoft SEAL will require the user to invest some time in learning fundamental concepts in homomorphic encryption. The code comes with heavily commented examples that are designed to gradually teach such concepts as well as demonstrate a large fraction of the API. The examples are available (and identical) in C++ and C#, and are divided into several source files in native/examples/ (C++) and dotnet/examples/ (C#), as follows:

C++ C# Description
examples.cpp Examples.cs The example runner application
1_bfv_basics.cpp 1_BFV_Basics.cs Encrypted modular arithmetic using the BFV scheme
2_encoders.cpp 2_Encoders.cs Encoding more complex data into Microsoft SEAL plaintext objects
3_levels.cpp 3_Levels.cs Introduces the concept of levels; prerequisite for using the CKKS scheme
4_bgv_basics.cpp 4_BGV_Basics.cs Encrypted modular arithmetic using the BGV scheme
5_ckks_basics.cpp 5_CKKS_Basics.cs Encrypted real number arithmetic using the CKKS scheme
6_rotation.cpp 6_Rotation.cs Performing cyclic rotations on encrypted vectors in the BFV and CKKS schemes
7_serialization.cpp 7_Serialization.cs Serializing objects in Microsoft SEAL
8_performance.cpp 8_Performance.cs Performance tests

It is recommended to read the comments and the code snippets along with command line printout from running an example. For easier navigation, command line printout provides the line number in the associated source file where the associated code snippets start. To build the examples, see Examples, Tests, and Benchmark (C++) and Building .NET Components (C#).

Note: It is impossible to know how to use Microsoft SEAL correctly without studying examples 1–6. They are designed to provide the reader with the necessary conceptual background on homomorphic encryption. Reusing code directly from the examples will not work well, as the examples are often demonstrating individual pieces of functionality, and are not optimized for performance. Writing Microsoft SEAL code without studying the examples in depth will inevitably result in code that is vulnerable, malfunctioning, or extremely slow.

CKKS Programming with EVA

When studying the examples above, it will become clear that the CKKS scheme can be unfriendly to beginners. Even relatively simple computations can be challenging to get to work due to the limitations of the rescaling operation and the requirement of aligning scales at different levels.

We have created a new compiler tool called EVA that helps resolve these challenges to a large extent. EVA allows programmers to express desired encrypted computations in Python. It optimizes the computations for Microsoft SEAL, selects appropriate encryption parameters, and provides a convenient Python API for encrypting the input, executing the computation, and decrypting the result. EVA is available at GitHub.com/Microsoft/EVA. Try it out, and let us know what you think!

Note: EVA only supports the CKKS scheme. There are no immediate plans to support the BFV or BGV scheme.

Building Microsoft SEAL Manually

Building C++ Components

On all platforms Microsoft SEAL is built with CMake. We recommend using out-of-source build although in-source build works. Below we give instructions for how to configure, build, and install Microsoft SEAL either globally (system-wide), or locally (for a single user). A global install requires elevated (root or administrator) privileges.

Requirements

System Toolchain
Windows Visual Studio 2022 with C++ CMake Tools for Windows
Linux Clang++ (>= 5.0) or GNU G++ (>= 6.0), CMake (>= 3.13)
macOS/iOS Xcode toolchain (>= 9.3), CMake (>= 3.13)
Android Android Studio
FreeBSD CMake (>= 3.13)

Note: Microsoft SEAL compiled with Clang++ has much better runtime performance than one compiled with GNU G++.

Building Microsoft SEAL

We assume that Microsoft SEAL has been cloned into a directory called SEAL and all commands presented below are assumed to be executed in the directory SEAL.

You can build the Microsoft SEAL library (out-of-source) for your machine by executing the following commands:

cmake -S . -B build
cmake --build build

After the build completes, the output binaries can be found in build/lib/ and build/bin/ directories.

Various configuration options can be specified and passed to the CMake build system. These are described below in sections Basic CMake Options and Advanced CMake Options.

Installing Microsoft SEAL

If you have root access to the system you can install Microsoft SEAL globally as follows:

cmake -S . -B build
cmake --build build
sudo cmake --install build

To instead install Microsoft SEAL locally, e.g., to ~/mylibs/, do the following:

cmake -S . -B build -DCMAKE_INSTALL_PREFIX=~/mylibs
cmake --build build
sudo cmake --install build

Building and Installing on Windows

On Windows the same scripts above work in a developer command prompt for Visual Studio using either the Ninja or "Visual Studio 17 2022" generators.

When using the Ninja generator, please use the appropriate command prompt depending on the platform you want to build for. If you want to build for x64, please use the x64 Native Tools Command Prompt for Visual Studio 2022 command prompt to configure and build the library. If you want to build for x86, please use the x86 Native Tools Command Prompt for Visual Studio 2022 command prompt to configure and build the library. To build using Ninja, type

cmake -S . -B build -G Ninja
cmake --build build

When using the "Visual Studio 17 2022" generator you can use the Developer Command Prompt for VS 2022 command prompt to configure and build the library. By default the generated platform will be x64. You can specify the desired platform using the architecture flag -A <x64|Win32> and the desired configuration using --config <Debug|Release>.

# Generate and build for x64 in Release mode
cmake -S . -B build -G "Visual Studio 17 2022" -A x64
cmake --build build --config Release
# Generate and build for x86 in Release mode
cmake -S . -B build -G "Visual Studio 17 2022" -A Win32
cmake --build build --config Release

Installing the library in Windows works as well. Instead of using the sudo command, however, you need to run cmake --install build from a command prompt with Administrator permissions. Files will be installed by default to C:\Program Files (x86)\SEAL\.

Visual Studio 2022 provides support for CMake-based projects. You can select the menu option File / Open / Folder... and navigate to the folder where the Microsoft SEAL repository is located. After opening the folder, Visual Studio will detect that this is a CMake-based project and will enable the menu command Project / CMake settings for SEAL. This will open the CMake settings editor that provides a user interface where you can create different configurations and set different CMake options.

After the build completes, the output static library seal-<version>.lib can be found in build\lib\ or build\lib\Release\. When linking with applications, using CMake as is explained in Linking with Microsoft SEAL through CMake is highly recommended. Alternatively, you need to add native\src\ (full path) and build\native\src\ as include directories to locate the Microsoft SEAL header files.

Building for Android and iOS

Microsoft SEAL can be compiled for Android and iOS. Under the android/ directory of the source tree you will find an Android Studio project that you can use to compile the library for Android.

To build the library for iOS, use the following scripts:

# Configure CMake
cmake -S . -B build -GXcode -DSEAL_BUILD_SEAL_C=ON -DSEAL_BUILD_STATIC_SEAL_C=ON -DCMAKE_SYSTEM_NAME=iOS "-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" -C cmake/memset_s.iOS.cmake

# Build libseal*.a for x86_64
xcodebuild -project build/SEAL.xcodeproj -sdk iphonesimulator -arch x86_64 -configuration Release clean build
mkdir -p build/lib/x86_64
cp build/lib/Release/libseal*.a build/lib/x86_64

# Build libseal*.a for arm64
xcodebuild -project SEAL.xcodeproj -sdk iphoneos -arch arm64 -configuration Release clean build
mkdir -p build/lib/arm64
cp build/lib/Release/libseal*.a build/lib/arm64

# Combine libseal-*.a into libseal.a and libsealc-*.a into libsealc.a
lipo -create -output build/lib/libseal.a build/lib/x86_64/libseal-*.a arm64/libseal-*.a
lipo -create -output build/lib/libsealc.a build/lib/x86_64/libsealc-*.a build/lib/arm64/libsealc-*.a

The native libraries generated through these methods are meant to be called only through the .NET library described in the following sections. Specifically, they do not contain any wrappers that can be used from Java (for Android) or Objective C (for iOS).

Building for WebAssembly

Microsoft SEAL can be compiled for JavaScript and WebAssembly using emscripten on Windows, Linux, and macOS. Building for the Web means SEAL can be run in any client/server environment such as all the major browsers (e.g. Edge, Chrome, Firefox, Safari) and NodeJS.

Building for WebAssembly requires the emscripten toolchain to be installed. The easiest way to configure the toolchain is to clone emsdk and follow the instructions (with system-specific notes). For examples, on Linux and macOS, inside the emsdk repo, run the following:

# Install the latest toolchain
./emsdk install latest
./emsdk activate latest
# Source the environment
source ./emsdk_env.sh

On Windows, better run from a developer command prompt for Visual Studio; and replace ./emsdk and source ./emsdk_env.sh with emsdk and emsdk_env.bat, respectively. In other environments, cmake must be added to the path, and either "Ninja" or "MinGW Makefiles" should be specified as generator in the following configuration step. emcmake does not work with Visual Studio 17 2022 generator.

Within the same shell, navigate to the root directory of Microsoft SEAL, run the following commands to build for WebAssembly:

# Configure CMake. Example flags for a release build
emcmake cmake -S . -B build \
 -DBUILD_SHARED_LIBS=OFF \
 -DCMAKE_BUILD_TYPE=Release \
 -DCMAKE_CXX_FLAGS_RELEASE="-DNDEBUG -flto -O3" \
 -DCMAKE_C_FLAGS_RELEASE="-DNDEBUG -flto -O3" \
 -DSEAL_BUILD_BENCH=OFF \ # Benchmark can be built for WASM. Change this to ON.
 -DSEAL_BUILD_EXAMPLES=OFF \
 -DSEAL_BUILD_TESTS=OFF \
 -DSEAL_USE_CXX17=ON \
 -DSEAL_USE_INTRIN=ON \
 -DSEAL_USE_MSGSL=OFF \
 -DSEAL_USE_ZLIB=ON \
 -DSEAL_THROW_ON_TRANSPARENT_CIPHERTEXT=ON

# Make the static library (shared libs are not supported with emscripten)
emmake make -C build -j

# Build the WebAssembly module
emcc \
 -Wall \
 -flto \
 -O3 \
 build/lib/libseal-4.1.a \
 --bind \
 -o "build/bin/seal_wasm.js" \
 -s WASM=1 \
 -s ALLOW_MEMORY_GROWTH=1

Note: There are many flags to consider when building a WebAssembly module. Please refer to the settings.js file for advanced build flags.

Building will generate two output files, seal_wasm.js and seal_wasm.wasm, in the build/bin/ directory. The file sizes for the artifacts are very small. This is because that the optimization flags perform dead code elimination (DCE) as there are no bindings generated to JavaScript. Defining these bindings is necessary in order to call into WebAssembly from the JavaScript domain; however, Microsoft SEAL does not include any definitions at this time. The build flag --bind expects the bindings to be specified using the embind syntax.

Basic CMake Options

The following options can be used with CMake to configure the build. The default value for each option is denoted with boldface in the Values column.

CMake option Values Information
CMAKE_BUILD_TYPE Release
Debug
RelWithDebInfo
MinSizeRel
Debug and MinSizeRel have worse run-time performance. Debug inserts additional assertion code. Set to Release unless you are developing Microsoft SEAL itself or debugging some complex issue.
SEAL_BUILD_EXAMPLES ON / OFF Build the C++ examples in native/examples.
SEAL_BUILD_TESTS ON / OFF Build the tests to check that Microsoft SEAL works correctly.
SEAL_BUILD_BENCH ON / OFF Build the performance benchmark.
SEAL_BUILD_DEPS ON / OFF Set to ON to automatically download and build optional dependencies; otherwise CMake will attempt to locate pre-installed dependencies.
SEAL_USE_INTEL_HEXL ON / OFF Set to ON to use Intel HEXL for low-level kernels.
SEAL_USE_MSGSL ON / OFF Build with Microsoft GSL support.
SEAL_USE_ZLIB ON / OFF Build with ZLIB support.
SEAL_USE_ZSTD ON / OFF Build with Zstandard support.
BUILD_SHARED_LIBS ON / OFF Set to ON to build a shared library instead of a static library. Not supported in Windows.
SEAL_BUILD_SEAL_C ON / OFF Build the C wrapper library SEAL_C. This is used by the C# wrapper and most users should have no reason to build it.
SEAL_USE_CXX17 ON / OFF Set to ON to build Microsoft SEAL as C++17 for a positive performance impact.
SEAL_USE_INTRIN ON / OFF Set to ON to use compiler intrinsics for improved performance. CMake will automatically detect which intrinsics are available and enable them accordingly.

As usual, these options can be passed to CMake with the -D flag. For example, one could run

cmake -S . -B build -DSEAL_BUILD_EXAMPLES=ON

to configure a release build of a static Microsoft SEAL library and also build the examples.

Advanced CMake Options

The following options can be used with CMake to further configure the build. Most users should have no reason to change these, which is why they are marked as advanced.

CMake option Values Information
SEAL_THROW_ON_TRANSPARENT_CIPHERTEXT ON / OFF Set to ON to throw an exception when Microsoft SEAL produces a ciphertext with no key-dependent component. For example, subtracting a ciphertext from itself, or multiplying a ciphertext with a plaintext zero yield identically zero ciphertexts that should not be considered as valid ciphertexts.
SEAL_BUILD_STATIC_SEAL_C ON / OFF Set to ON to build SEAL_C as a static library instead of a shared library.
SEAL_DEFAULT_PRNG Blake2xb
Shake256
Microsoft SEAL supports both Blake2xb and Shake256 XOFs for generating random bytes. Blake2xb is much faster, but it is not standardized, whereas Shake256 is a FIPS standard.
SEAL_USE_GAUSSIAN_NOISE ON / OFF Set to ON to use a non-constant time rounded continuous Gaussian for the error distribution; otherwise a centered binomial distribution – with slightly larger standard deviation – is used.
SEAL_AVOID_BRANCHING ON / OFF Set to ON to eliminate branching in critical functions when compiler has maliciously inserted flags; otherwise assume cmov is used.
SEAL_SECURE_COMPILE_OPTIONS ON / OFF Set to ON to compile/link with Control-Flow Guard (/guard:cf) and Spectre mitigations (/Qspectre). This has an effect only when compiling with MSVC.
SEAL_USE_ALIGNED_ALLOC ON / OFF Set to ON to use 64-byte aligned memory allocations. This can improve performance of AVX512 primitives when Intel HEXL is enabled. This depends on C++17 and is disabled on Android.

Linking with Microsoft SEAL through CMake

It is very easy to link your own applications and libraries with Microsoft SEAL if you use CMake. Simply add the following to your CMakeLists.txt:

find_package(SEAL 4.1 REQUIRED)
target_link_libraries(<your target> SEAL::seal)

If Microsoft SEAL was installed globally, the above find_package command will likely find the library automatically. To link with a Microsoft SEAL installed locally, e.g., installed in ~/mylibs as described above, you may need to tell CMake where to look for Microsoft SEAL when you configure your application by running:

cd <directory containing your CMakeLists.txt>
cmake . -DCMAKE_PREFIX_PATH=~/mylibs

If Microsoft SEAL was installed using a package manager like vcpkg or Homebrew, please refer to their documentation for how to link with the installed library. For example, vcpkg requires you to specify the vcpkg CMake toolchain file when configuring your project.

Examples, Tests, and Benchmarks

When building Microsoft SEAL, examples, tests, and benchmarks can be built by setting SEAL_BUILD_EXAMPLES=ON, SEAL_BUILD_TESTS=ON, and SEAL_BUILD_BENCH=ON; see Basic CMake Options. Alternatively, examples, tests, and benchmark can be built as standalone CMake projects linked with Microsoft SEAL (installed in ~/mylibs), by following the commands below. Omit setting SEAL_ROOT if the library is installed globally.

cd native/<examples|tests|bench>
cmake -S . -B build -DSEAL_ROOT=~/mylibs
cmake --build build

By default, benchmarks run for a vector of parameters and primitives, which can be overwhelmingly informative. To execute a subset of benchmark cases, see Google Benchmark README. For advanced users, the bm_parms_vec variable in native/bench/bench.cpp can be overwritten with custom parameter sets.

Note: The benchmark code is strictly for experimental purposes; it allows insecure parameters that must not be used in real applications. Do not follow the benchmarks as examples.

Building .NET Components

Microsoft SEAL provides a .NET Standard library that wraps the functionality in Microsoft SEAL for use in .NET development. Using the existing NuGet package is highly recommended, unless development of Microsoft SEAL or building a custom NuGet package is intended. Prior to building .NET components, the C wrapper library SEAL_C must be built following Building C++ Components. The SEAL_C library is meant to be used only by the .NET library, not by end-users.

Note: SEAL_C and the .NET library only support 64-bit platforms.

Windows, Linux, and macOS

For compiling .NET code you will need to install a .NET SDK (>= 6.0). Building the SEAL_C library with CMake will generate project files for the .NET wrapper library, examples, and unit tests. The SEAL_C library must be discoverable when running a .NET application, e.g., be present in the same directory as your executable, which is taken care of by the .NET examples and tests project files. Run the following scripts to build each project:

dotnet build build/dotnet/src --configuration <Debug|Release> # Build .NET wrapper library
dotnet test build/dotnet/tests # Build and run .NET unit tests
dotnet run -p build/dotnet/examples # Build and run .NET examples

You can use --configuration <Debug|Release> to run Debug or Release examples and unit tests. You can use --verbosity detailed to print the list of unit tests that are being run.

On Windows, you can also use the Microsoft Visual Studio 2022 solution file, for example, out/build/x64-Debug/dotnet/SEALNet.sln to build all three projects.

Android and iOS

While it is possible to build your own custom NuGet package for Android or iOS (see Building for Android and iOS for the native component), this is not easy and is not recommended. Instead, please add a reference to the multiplatform NuGet package to your Xamarin project.

Using Microsoft SEAL for .NET

To use Microsoft SEAL for .NET in your own application you need to:

  1. Add a reference in your project to SEALNet.dll;
  2. Ensure the native shared library is available for your application when run. The easiest way to ensure this is to copy the native shared library to the same directory where your application's executable is located.

Building Your Own NuGet Package

You can build your own NuGet package for Microsoft SEAL by following the instructions in NUGET.md.

Contributing

For contributing to Microsoft SEAL, please see CONTRIBUTING.md.

Citing Microsoft SEAL

To cite Microsoft SEAL in academic papers, please use the following BibTeX entries.

Version 4.1

    @misc{sealcrypto,
        title = {{M}icrosoft {SEAL} (release 4.1)},
        howpublished = {\url{https://github.com/Microsoft/SEAL}},
        month = jan,
        year = 2023,
        note = {Microsoft Research, Redmond, WA.},
        key = {SEAL}
    }

Version 4.0

    @misc{sealcrypto,
        title = {{M}icrosoft {SEAL} (release 4.0)},
        howpublished = {\url{https://github.com/Microsoft/SEAL}},
        month = mar,
        year = 2022,
        note = {Microsoft Research, Redmond, WA.},
        key = {SEAL}
    }

Version 3.7

    @misc{sealcrypto,
        title = {{M}icrosoft {SEAL} (release 3.7)},
        howpublished = {\url{https://github.com/Microsoft/SEAL}},
        month = sep,
        year = 2021,
        note = {Microsoft Research, Redmond, WA.},
        key = {SEAL}
    }

Version 3.6

    @misc{sealcrypto,
        title = {{M}icrosoft {SEAL} (release 3.6)},
        howpublished = {\url{https://github.com/Microsoft/SEAL}},
        month = nov,
        year = 2020,
        note = {Microsoft Research, Redmond, WA.},
        key = {SEAL}
    }

Version 3.5

    @misc{sealcrypto,
        title = {{M}icrosoft {SEAL} (release 3.5)},
        howpublished = {\url{https://github.com/Microsoft/SEAL}},
        month = apr,
        year = 2020,
        note = {Microsoft Research, Redmond, WA.},
        key = {SEAL}
    }

Version 3.4

    @misc{sealcrypto,
        title = {{M}icrosoft {SEAL} (release 3.4)},
        howpublished = {\url{https://github.com/Microsoft/SEAL}},
        month = oct,
        year = 2019,
        note = {Microsoft Research, Redmond, WA.},
        key = {SEAL}
    }

Version 3.3

    @misc{sealcrypto,
        title = {{M}icrosoft {SEAL} (release 3.3)},
        howpublished = {\url{https://github.com/Microsoft/SEAL}},
        month = jun,
        year = 2019,
        note = {Microsoft Research, Redmond, WA.},
        key = {SEAL}
    }

Version 3.2

    @misc{sealcrypto,
        title = {{M}icrosoft {SEAL} (release 3.2)},
        howpublished = {\url{https://github.com/Microsoft/SEAL}},
        month = feb,
        year = 2019,
        note = {Microsoft Research, Redmond, WA.},
        key = {SEAL}
    }

Version 3.1

    @misc{sealcrypto,
        title = {{M}icrosoft {SEAL} (release 3.1)},
        howpublished = {\url{https://github.com/Microsoft/SEAL}},
        month = dec,
        year = 2018,
        note = {Microsoft Research, Redmond, WA.},
        key = {SEAL}
    }

Version 3.0

    @misc{sealcrypto,
        title = {{M}icrosoft {SEAL} (release 3.0)},
        howpublished = {\url{http://sealcrypto.org}},
        month = oct,
        year = 2018,
        note = {Microsoft Research, Redmond, WA.},
        key = {SEAL}
    }

Acknowledgments

Many people have contributed substantially to Microsoft SEAL without being represented in the Git history. We wish to express special gratitude to John Wernsing, Hao Chen, Yongsoo Song, Olli Saarikivi, Rachel Player, Gizem S. Cetin, Peter Rindal, Amir Jalali, Kyoohyung Han, Sadegh Riazi, Ilia Iliashenko, Roshan Dathathri, Pardis Emami-Naeini, Sangeeta Chowdhary, Deepika Natarajan, and Michael Rosenberg.

seal's People

Contributors

0xflotus avatar alexanderviand avatar bastienvialla avatar cheney-w avatar chrdavis avatar codedust avatar dkaidalov avatar dnat112 avatar elkanatovey avatar fboemer avatar fionser avatar florentclmichel avatar gelilaseifu avatar haochenuw avatar imadchabounia avatar jharrilim avatar jlhcrawford avatar joshbeal avatar kimlaine avatar kiromaru avatar lwhsu avatar marinthiercelin avatar microsoftopensource avatar msftgits avatar qix- avatar rand0musername avatar rav1kantsingh avatar s0l0ist avatar sivanov-work avatar youben11 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

seal's Issues

Accuracy along the output vector with CKKS

Regarding the use of CKKS without batching, I was wondering why I observe different accuracy along the output vector. I noticed on multiple examples that the first 3 or 4 values of the vector have less accuracy compared to the following ones.
Here is one example showing this behavior, I have as input 98.123456789, and I simply encrypt then decrypt it.

// Parameters
EncryptionParameters parms(scheme_type::CKKS);
size_t poly_modulus_degree = 8192;
parms.set_poly_modulus_degree(poly_modulus_degree);
parms.set_coeff_modulus(CoeffModulus::Create(poly_modulus_degree, { 40, 30, 30, 40 }));
double scale = pow(2.0, 30);

auto context = SEALContext::Create(parms);
KeyGenerator keygen(context);
auto public_key = keygen.public_key();
auto secret_key = keygen.secret_key();
auto relin_keys = keygen.relin_keys();
Encryptor encryptor(context, public_key);
Evaluator evaluator(context);
Decryptor decryptor(context, secret_key);
CKKSEncoder encoder(context);
size_t slot_count = encoder.slot_count();

Plaintext plain, plain_output;
Ciphertext cipher;
vector<double> res;

float val = 98.123456789;

// Encode then encrypt the value
encoder.encode(val, scale, plain);
encryptor.encrypt(plain, cipher);

// Decrypt then decode the cipher
decryptor.decrypt(cipher, plain_output);
encoder.decode(plain_output, res);

cout << "Result = " << endl;
std::cout << std::setprecision(20);
int acc;
for (std::size_t i = 0; i < 20; i++)
{
        std::cout << res[i];
        acc = (-1) * round(val>res[i] ? log2(val-res[i]) : log2(res[i]-val));
        std::cout << ", accuracy : " << acc << "\n";
}

This is the output I get:

Result = 
98.123208870796077008, accuracy : 12
98.123450072802540944, accuracy : 17
98.123455446539892932, accuracy : 18
98.12346096075420121, accuracy : 19
98.123461018082238638, accuracy : 19
98.123459733768370938, accuracy : 20
98.123459644911221744, accuracy : 20
98.123459607719823339, accuracy : 20
98.123458459306192481, accuracy : 21
98.123459128922007721, accuracy : 22
98.123459203155206865, accuracy : 21
98.123457288371128016, accuracy : 19
98.123459230694592748, accuracy : 21
98.123458432719559141, accuracy : 21
98.123458786141469545, accuracy : 24
98.123457520335165327, accuracy : 20
98.123459134442754248, accuracy : 22
98.123459030688607641, accuracy : 23
98.123459054974986771, accuracy : 22
98.123457867560333057, accuracy : 20

Compiling SEAL with the -fPIC Flag

Is it possible to add an option when using CMake to create the libseal.a to pass some optional flags e.g the -fPIC flag? This will make libseal.a portable, which is important when building own libraries that link against libseal.a.

For now I'm changing the CMakeLists.txt of SEAL manually after each version update by adding the option set(CMAKE_POSITION_INDEPENDENT_CODE ON).

Regarding CoeffModulus::Create() for CKKS

The following 2 lines below both give a value of 60 using total_coeff_modulus_bit_count():

  1. <SmallModulus> q_primes = CoeffModulus::Create(8192, { 60});
    parms.set_coeff_modulus(q_primes);

  2. <SmallModulus> q_primes = CoeffModulus::Create(8192, { 60, 60});
    parms.set_coeff_modulus(q_primes);

Is it a bug? Thanks.

Tests fail to link despite availability of libgtest.a

MacOS Mojave 10.14.2, Xcode-10.1.

I've modified tests/CMakeLists.txt this way:

diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index ae15119..7be1116 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -18,9 +18,11 @@ if(SEAL_ENFORCE_HE_STD_SECURITY)
 endif()
 
 # Import Google target_link_libraries
-find_library(GTEST gtest)
+find_library(GTEST gtest HINTS /opt/local/lib /opt/local)
 if (NOT GTEST)
     message(FATAL_ERROR "Failed to find Google Test library required for unit tests")
+else(NOT GTEST)
+    message("Found library at ${GTEST}")
 endif()
 
 # Link SEAL

Screen log is self-explanatory:

$ cmake ..
-- The CXX compiler identification is AppleClang 10.0.0.10001145
-- Check for working CXX compiler: /opt/local/bin/clang++
-- Check for working CXX compiler: /opt/local/bin/clang++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Looking for C++ include pthread.h
-- Looking for C++ include pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - found
-- Found Threads: TRUE  
-- SEAL detected (version 3.1.0)
Found library at /opt/local/lib/libgtest.a
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/ur20980/src/SEAL/tests/build
$ make
Scanning dependencies of target sealtest
[  2%] Building CXX object CMakeFiles/sealtest.dir/seal/testrunner.cpp.o
[  5%] Building CXX object CMakeFiles/sealtest.dir/seal/batchencoder.cpp.o
[  7%] Building CXX object CMakeFiles/sealtest.dir/seal/biguint.cpp.o
[ 10%] Building CXX object CMakeFiles/sealtest.dir/seal/ciphertext.cpp.o
[ 12%] Building CXX object CMakeFiles/sealtest.dir/seal/ckks.cpp.o
[ 15%] Building CXX object CMakeFiles/sealtest.dir/seal/context.cpp.o
[ 17%] Building CXX object CMakeFiles/sealtest.dir/seal/encoder.cpp.o
[ 20%] Building CXX object CMakeFiles/sealtest.dir/seal/encryptionparams.cpp.o
[ 23%] Building CXX object CMakeFiles/sealtest.dir/seal/encryptor.cpp.o
[ 25%] Building CXX object CMakeFiles/sealtest.dir/seal/evaluator.cpp.o
[ 28%] Building CXX object CMakeFiles/sealtest.dir/seal/galoiskeys.cpp.o
[ 30%] Building CXX object CMakeFiles/sealtest.dir/seal/intarray.cpp.o
[ 33%] Building CXX object CMakeFiles/sealtest.dir/seal/keygenerator.cpp.o
[ 35%] Building CXX object CMakeFiles/sealtest.dir/seal/memorymanager.cpp.o
[ 38%] Building CXX object CMakeFiles/sealtest.dir/seal/plaintext.cpp.o
[ 41%] Building CXX object CMakeFiles/sealtest.dir/seal/publickey.cpp.o
[ 43%] Building CXX object CMakeFiles/sealtest.dir/seal/randomgen.cpp.o
[ 46%] Building CXX object CMakeFiles/sealtest.dir/seal/relinkeys.cpp.o
[ 48%] Building CXX object CMakeFiles/sealtest.dir/seal/secretkey.cpp.o
[ 51%] Building CXX object CMakeFiles/sealtest.dir/seal/smallmodulus.cpp.o
[ 53%] Building CXX object CMakeFiles/sealtest.dir/seal/util/clipnormal.cpp.o
[ 56%] Building CXX object CMakeFiles/sealtest.dir/seal/util/common.cpp.o
[ 58%] Building CXX object CMakeFiles/sealtest.dir/seal/util/hash.cpp.o
[ 61%] Building CXX object CMakeFiles/sealtest.dir/seal/util/locks.cpp.o
[ 64%] Building CXX object CMakeFiles/sealtest.dir/seal/util/mempool.cpp.o
[ 66%] Building CXX object CMakeFiles/sealtest.dir/seal/util/numth.cpp.o
[ 69%] Building CXX object CMakeFiles/sealtest.dir/seal/util/polyarith.cpp.o
[ 71%] Building CXX object CMakeFiles/sealtest.dir/seal/util/polyarithmod.cpp.o
[ 74%] Building CXX object CMakeFiles/sealtest.dir/seal/util/polyarithsmallmod.cpp.o
[ 76%] Building CXX object CMakeFiles/sealtest.dir/seal/util/polycore.cpp.o
[ 79%] Building CXX object CMakeFiles/sealtest.dir/seal/util/randomtostd.cpp.o
[ 82%] Building CXX object CMakeFiles/sealtest.dir/seal/util/smallntt.cpp.o
[ 84%] Building CXX object CMakeFiles/sealtest.dir/seal/util/stringtouint64.cpp.o
[ 87%] Building CXX object CMakeFiles/sealtest.dir/seal/util/uint64tostring.cpp.o
[ 89%] Building CXX object CMakeFiles/sealtest.dir/seal/util/uintarith.cpp.o
[ 92%] Building CXX object CMakeFiles/sealtest.dir/seal/util/uintarithmod.cpp.o
[ 94%] Building CXX object CMakeFiles/sealtest.dir/seal/util/uintarithsmallmod.cpp.o
[ 97%] Building CXX object CMakeFiles/sealtest.dir/seal/util/uintcore.cpp.o
[100%] Linking CXX executable /Users/ur20980/src/SEAL/bin/sealtest
ld: library not found for -lgtest
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [/Users/ur20980/src/SEAL/bin/sealtest] Error 1
make[1]: *** [CMakeFiles/sealtest.dir/all] Error 2
make: *** [all] Error 2
$ 

Noise budget above 0 in BFV example

Went through the bfv basics example, and came across this:

/*
Finally, we multiply (x^2 + 1) * (x + 1)^2 * 2.
*/
print_line(__LINE__);
cout << "Compute encrypted_result (2(x^2+1)(x+1)^2)." << endl;
Ciphertext encrypted_result;
Plaintext plain_two("2");
evaluator.multiply_plain_inplace(x_sq_plus_one, plain_two);
evaluator.multiply(x_sq_plus_one, x_plus_one_sq, encrypted_result);
cout << " + size of encrypted_result: " << encrypted_result.size() << endl;
cout << " + noise budget in encrypted_result: "
<< decryptor.invariant_noise_budget(encrypted_result) << " bits" << endl;
cout << "NOTE: Decryption can be incorrect if noise budget is zero." << endl;
cout << endl;
cout << "~~~~~~ A better way to calculate 2(x^2+1)(x+1)^2. ~~~~~~" << endl;
/*
Noise budget has reached 0, which means that decryption cannot be expected
to give the correct result. This is because both ciphertexts x_sq_plus_one
and x_plus_one_sq consist of 3 polynomials due to the previous squaring
operations, and homomorphic operations on large ciphertexts consume much more
noise budget than computations on small ciphertexts. Computing on smaller
ciphertexts is also computationally significantly cheaper.

To me the comment seems to suggest that the noise budget should be 0 when the operations are done. However when I'm running them the noise budget end up on 7 to 10 bits.

Possible inconsistent size reported for Plaintext in save_size

When serializing/deserializing Plaintexts, there was an inconsistent size estimation resulting from an improper type when computing ComprSizeEstimate.

Previously, when running the following code:

plaintext.h line ~572:

SEAL_NODISCARD inline std::streamoff save_size(
            compr_mode_type compr_mode) const
        {
            std::size_t members_size = Serialization::ComprSizeEstimate(
                util::add_safe(
                    sizeof(parms_id_),
                    sizeof(coeff_count_), // <--------------------- Offending member
                    sizeof(scale_),
                    util::safe_cast<std::size_t>(
                        data_.save_size(compr_mode_type::none))),
                compr_mode);
            std::cout << "Plaintext::save_size member_size (" << members_size << ")" <<std::endl;

            auto size = util::safe_cast<std::streamoff>(util::add_safe(
                    sizeof(Serialization::SEALHeader),
                    members_size
                ));
            std::cout << "Plaintext::save_size size (" << size << ")" <<std::endl;

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

Results in the incorrect member_size:

Plaintext::save_size member_size (32836)
Plaintext::save_size size (32852)

This, in turn, becomes an issue when deserializing a saved Plaintext stream where the stream.tellg() position calculation throws here:

serialization.cpp line ~657:

if (header.size != stream.tellg() - stream_start_pos)

Replacing it with the following:

SEAL_NODISCARD inline std::streamoff save_size(
            compr_mode_type compr_mode) const
        {
            std::size_t members_size = Serialization::ComprSizeEstimate(
                util::add_safe(
                    sizeof(parms_id_),
                    sizeof(uint64_t), // coeff_count_ <--------------------- Modified member
                    sizeof(scale_),
                    util::safe_cast<std::size_t>(
                        data_.save_size(compr_mode_type::none))),
                compr_mode);
            std::cout << "Plaintext::save_size member_size (" << members_size << ")" <<std::endl;

            auto size = util::safe_cast<std::streamoff>(util::add_safe(
                    sizeof(Serialization::SEALHeader),
                    members_size
                ));
            std::cout << "Plaintext::save_size size (" << size << ")" <<std::endl;

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

Results in the correct member_size:

Plaintext::save_size member_size (32840)
Plaintext::save_size size (32856)

This change in Plaintext.h resembles the uint64_t setting for coeff_mod_count_ in Ciphertext.cpp.

Parameters to reproduce (pseudo code):

EncParms: {
    schemeType: BFV,
    polyModulusDegree: 4096,
    security: tc128,
    plainModulus: Batching(polyModulusDegree: 4096, bitsize: 20)
    coeffModulus: BFVDefault(polyModulusDegree: 4096,
          security: tc128)
}

Context: {
    expandModChain: true,
    security: tc128
}

Create a Plaintext and encode 4096 (max size of polyModulusDegree) misc values to it (within range)

Save the plaintext to a stream. (where the header size is computed incorrectly)

Attempt to load from the same stream. (where it throws during runtime)

add_many and multiply_many API should be extended

add_many and multiply_many API should be extended by:

  • making these variadic (allow any number of input arguments);
  • adding support for C++ input iterators, e.g. could pass myvec.begin() and myvec.end() for the range to operate on.

Serializing Public Key and Context

I understand that a Ciphertext can be serialized using the Ciphertext::save(std::ostream &) method. I also saw a test for the same. However, I did not see one for the keys or the context.
Are they serialized along with the ciphertext?
To encrypt a plaintext or perform operations on a ciphertext at a different machine, I will require context and the public key. Is there a procedure to serialize them?
Moreover, is there an example or a test that demonstrates this usecase (serializing various components of the scheme)?

Substantially lower noise budget on fresh encryptions in 3.3.0

We are seeing fresh encryptions of ciphertexts with poly_modulus_degree 4096 and higher have much less noise budget in 3.3.0 than they did in 3.2.0. This contradicts what is in Changes.md ("Moreover, fresh ciphertexts now have a larger noise budget.") so I'm wondering this is working as intended or not.

To demonstrate, I wrote a short program that just follows the example code to make a fresh ciphertext using batching and print its noise budget:

#include "seal/seal.h"

using namespace std;
using namespace seal;

int main() {
#ifdef SEAL_VERSION
    cout << "Microsoft SEAL version: " << SEAL_VERSION << endl;
#endif

    vector<size_t> degrees = {4096, 8192, 16384, 32768};

    for (size_t i = 0; i < degrees.size(); i++) {
        size_t degree = degrees.at(i);

        EncryptionParameters parms(scheme_type::BFV);
        parms.set_poly_modulus_degree(degree);
        parms.set_coeff_modulus(DefaultParams::coeff_modulus_128(degree));
        parms.set_plain_modulus(65537);
        auto context = SEALContext::Create(parms);

        KeyGenerator keygen(context);
        auto public_key = keygen.public_key();
        auto secret_key = keygen.secret_key();

        Encryptor encryptor(context, public_key);
        Decryptor decryptor(context, secret_key);
        BatchEncoder batch_encoder(context);

        size_t slot_count = batch_encoder.slot_count();
        vector<uint64_t> data(slot_count);
			
        data.at(0) = 1ULL;

        Plaintext plaintext;
        Ciphertext ciphertext;

        batch_encoder.encode(data, plaintext);
        encryptor.encrypt(plaintext, ciphertext);

        cout << "Fresh encryption noise budget for degree " << degree << ": " << decryptor.invariant_noise_budget(ciphertext) << " bits." << endl;
    }
}

When I compile this sample code against SEAL 3.2.0 I get the output:

Microsoft SEAL version: 3.2.0
Fresh encryption noise budget for degree 4096: 79 bits.
Fresh encryption noise budget for degree 8192: 188 bits.
Fresh encryption noise budget for degree 16384: 407 bits.
Fresh encryption noise budget for degree 32768: 848 bits.

When I take the same code and compile against 3.3.0 (changing DefaultParams::coeff_modulus_128(degree) to CoeffModulus::BFVDefault(degree) following the updated example code) I get the following output:

Microsoft SEAL version: 3.3.0
Fresh encryption noise budget for degree 4096: 40 bits.
Fresh encryption noise budget for degree 8192: 142 bits.
Fresh encryption noise budget for degree 16384: 357 bits.
Fresh encryption noise budget for degree 32768: 794 bits.

The noise budget is much lower in all cases; for degree 4096 almost half the initial noise budget is lost.

Is there any way to restore the old noise budgets in 3.3.0? We are using SEAL at my organization and this issue makes it not worth it for us to upgrade from 3.2.0.

Noise Budget and Modulus Switching

Is it possible to get an estimation of noise budget without the decryptor (or the secret key)? For example, a noise heuristic that maintains the upper bound on current noise in a ciphertext.

Conventionally, modulus switching is primarily used to make the noise growth linear, as opposed to exponential. However, in the BFV examples, it has been introduced as a tool to shave off primes (thereby reducing the bitlength of coefficient modulus) and improve computational efficiency.
Does it help in reducing noise growth in the BFV scheme as well? Will I observe exponential growth in noise without (manually) switching modulus?

noise budget lower than expected for 3.3.1

It seems like for poly_modulus_degree equal to 16384 and a 40 bit plaintext modulus which enables batching, the noise budget of a encryption of zero is 340 bits but noise budget of a encryption of random vector with has only 310 bits of noise budget. The code below reproduces this issue.

#include "examples.h"

using namespace std;
using namespace seal;

void example_noise_budget()
{

    EncryptionParameters parms(scheme_type::BFV);


    size_t poly_modulus_degree = 16384;
    parms.set_poly_modulus_degree(poly_modulus_degree);


    parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree));


    parms.set_plain_modulus(PlainModulus::Batching(poly_modulus_degree, 40));


    auto context = SEALContext::Create(parms);

    print_line(__LINE__);
    cout << "Set encryption parameters and print" << endl;
    print_parameters(context);


    KeyGenerator keygen(context);
    PublicKey public_key = keygen.public_key();
    SecretKey secret_key = keygen.secret_key();

    Encryptor encryptor(context, public_key);


    Decryptor decryptor(context, secret_key);
    BatchEncoder batch_encoder(context);

    size_t slot_count = batch_encoder.slot_count();

   
    
    random_device rd;

    vector<uint64_t> data_1(slot_count, 0);
    vector<uint64_t> data_2(slot_count ,0); 
    for(size_t i =0; i < slot_count; i++){
	data_1[i] = rd() % parms.plain_modulus().value();
    }    


    Plaintext plain_1(parms.poly_modulus_degree(), 0);
    batch_encoder.encode(data_1, plain_1);

    Plaintext plain_2(parms.poly_modulus_degree(), 0);
    batch_encoder.encode(data_2, plain_2);

    Ciphertext encrypted_1(context);
    encryptor.encrypt(plain_1, encrypted_1);

    Ciphertext encrypted_2(context);
    encryptor.encrypt(plain_2, encrypted_2);


    cout << " noise budget of fresh encryption = "
        << decryptor.invariant_noise_budget(encrypted_1)  << endl;
    
    cout << " noise budget of fresh encryption of zero = " << decryptor.invariant_noise_budget(encrypted_2) << endl;  

}

Can Relin & Galois Keys be exposed like the Public Key?

Not an issue, but is it safe to share Relin & Galois keys as you would with a public key?

I'm trying to share these keys to allow a 3rd party to perform relinearizations and galois vector rotations on ciphertexts, but I don't know if this is safe. What are the implications (if any) of exposing these keys publically?

BTW, great job on this library and the amazing documentation.

Thanks in advance!

Regarding saving and loading of EncryptionParameters for CKKS scheme

In the void EncryptionParameters::Save(const EncryptionParameters &parms, ostream &stream) and EncryptionParameters EncryptionParameters::Load(istream &stream) functions, there is writing and reading of plain_modulus.

As the CKKS scheme does not require plain_modulus, an logic error "unsupported scheme" is thrown due to set_plain_modulus() when loading CKKS EncryptionParameters.

The checking of writing and saving of plain_modulus depending on scheme should be performed in Save() and Load() instead.

Thanks.

Typo

In the second CKKS example, the comment says We use a slightly smaller scale in this example. But it's still 2^60 like in the first one.

Add use_count for MemoryPoolHandle

Just a suggestion, it might help users for debugging memory issues if we can conveniently know how many objects are holding the shared ownership of the pool pointed by MemoryPoolHandle.

For example, add the following method to MemoryPoolHandle:

long int use_count() const noexcept { return pool_.use_count(); }

How to Print Ciphertext ?

Hello, I need your help. Thank you!
I am learning the SEAL example. In example_basic_i(), use enoode.encode(value), we can get plain. And plain.to_string() can print the plaintext. After encrypting, we get encryptend1. I want to print encrypted1, but I can't find a method to print it.
Please help me, Thank you!

I want to get more slots in one ciphertext.Can i put the polyModulusDegree bigger than 32768?

I am sorry to bother you.
I'm just beginning to learn to use seal.When i try to let the polyModulusDegree greater than 32768,the program was incorrectly reported.Because i want to get more slots.
And i notice that "In Microsoft SEAL the degree of the polynomial modulus must be a power
of 2 (e.g. 1024, 2048, 4096, 8192, 16384, or 32768)."
Why the slots only the half of the polyModulusDegree?
Can i get more slots in one ciphertext?
Thank you!

A question about Creating a NuGet package

Creating a NuGet package
。。。。。。。
You will need to:

1.Compile binaries
i. native\src\SEAL.vcxproj
ii. dotnet\native\SEALNetNative.vcxproj
iii.dotnet\src\SEALNet.csproj
2.Download the NuGet command line tool
Run the command below to create NuGet package
Add NuGet package reference to your .NET projects

How should I compile binaries?Can you give me a lot of details?
Looking forward to your reply.

CUDA support

Is there any ongoing work to add CUDA support to SEAL? Would you expect to see a significant speedup with the way FHE is implemented in SEAL?

Amortizing operations when rotating a ciphertext multiple times

Hello! I am currently re-implementing the Gazelle protocol using SEAL. In the paper, they use a technique they deem 'rotation hoisting' (sec 5.5) , which is essentially amortizing the cost of certain repeated operations when rotating the same ciphertext multiple times.

I haven't looked to closely at how exactly SEAL does rotation under the hood, but before I do I was simply wondering:

  • Does SEAL already include this functionality?
  • If not, would it be feasible to implement this and how would I go about doing it?

Thanks for your time!

Exception tests fail on VS2019, apparently Microsoft.VisualStudio.TestPlatform.Common.resources is not found

I realize this is not a supported configuration according to README.md, but maybe it's worth reporting since VS2019 is already very common and its community license more permissive than with VS2017. I'm on Windows 10 fi-FI with latest updates and SDKs and the project updated.

Apparently the issue is that file Microsoft.VisualStudio.TestPlatform.Common.resources is not found. I try to look deeper at this some point, but I wonder if anyone has pointers? Would it be OK to open an issue to track update to VS2019?

<edit: The update branch is at https://github.com/veikkoeeva/SEAL/tree/update-to-vs2019 .
<edit 2: There is a similar question at Visual Studio Developer Community, but the solution proposed there, adding a missing package, isn't the problem here.

Of the whole set two fails when run in VS2019, the stack I receive is

ExceptionsTest
Source: BatchEncoderTests.cs line: 219
Duration: 40 ms

Message:
Assert.ThrowsException failed. Threw exception FileNotFoundException, but exception ArgumentException was expected.
Exception Message: Could not load the specified file.
Stack Trace: at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingEvent(AssemblyName assemblyName)
at System.Runtime.Loader.AssemblyLoadContext.ResolveUsingResolvingEvent(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName)
at Microsoft.Research.SEAL.NativeMethods.BatchEncoder_Encode(IntPtr thisptr, IntPtr plain, IntPtr pool)
at Microsoft.Research.SEAL.BatchEncoder.Encode(Plaintext plain, MemoryPoolHandle pool) in C:\projektit\SEAL\dotnet\src\BatchEncoder.cs:line 155
at SEALNetTest.BatchEncoderTests.<>c__DisplayClass4_0.b__6() in C:\projektit\SEAL\dotnet\tests\BatchEncoderTests.cs:line 249
at Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsException[T](Action action, String message, Object[] parameters)
Stack Trace:
at BatchEncoderTests.ExceptionsTest() in BatchEncoderTests.cs line: 249

TheFailure

When debugging the tests, the actual error looks like
actualerror

and from there

$exception | {"Could not load the specified File.":"Microsoft.VisualStudio.TestPlatform.Common.resources"} | System.IO.FileNotFoundException

data format

Could you tell me the format of publickey.save(), secretkey.save() and ciphertext.save(). There is no doc to explain these.

BFV binary decoding

Hi,

Binary decoding of integer 1 returns a negative value with IntegerEncoder in SEAL 3.2.

Example:

            EncryptionParameters parms(scheme_type::BFV);
            parms.set_poly_modulus_degree(8192);                       
            parms.set_coeff_modulus(DefaultParams::coeff_modulus_128(8192));
            parms.set_plain_modulus(2);
            auto context = SEALContext::Create(parms); 
            IntegerEncoder encoder(context);
            int32_t integer(1);
            Plaintext plaintext=encoder.encode(integer);
            cout << "encode = " << plaintext.to_string() <<endl ;
            cout << "decode = " << encoder.decode_int32(plaintext) << endl;
    }

To-be-confirmed fix:

Replace

bool coeff_is_negative = coeff >= coeff_neg_threshold_;

in file intencoder.cpp, line 183 by:

bool coeff_is_negative = coeff > coeff_neg_threshold_;

Thanks.

reverse_bits template type - 32bits/64bits mismatch

I am currently working on making SEAL usable on ARM microcontrollers, and I discovered a bug related to the automatic selection of the 32bits/64bits variant of the reverse_bits function.

With GCC 7.3.1 and 8.2.1 for ARM processors, the 64 bits overload of the reverse_bits function is resolved instead of the 32bits one when called with a 32bits size_t argument (as is the case in the SmallNTT tables generation process, here). When the argument is instead a uint32_t there is no problem and the correct (32bits) overload is used.

The debugger output shows that the template<typename T, typename = std::enable_if<is_uint64_v<T>>> definition is resolved as <false, void> when the 64bits function is used with the 32bits argument.

This might also be a more general bug related to 32bits GCC, I am not proficient enough in C++ to understand the SFINAE issue here, and I would be really happy to understand why the overload resolution is incorrect.

For the records, I also tried compiling SEAL for the x86 architecture on Windows (using MSVC compiler), and I did not encounter any issue there).

I understand that microcontrollers are not the priority for SEAL, but I can say that I have successfully managed to encrypt a plaintext using the default parameters for a degree-1024 polynomial. To this end, I modified the reverse_bits overload resolution to make it more generic (I will propose a PR with my solution in a few minutes).

I open this issue to document the "bug", and to see if anyone with experience with GCC could explain the problem here.

Implementing Halevi's RNS.

  • It seems the current SEAL implements Bajard et al. 's residue number system (RNS).
  • Halevi et al. has proposed an improved version for this, see Section 3.3
  • For the improved version, we can save one scalar-ciphertext multiplication in the relinearization.

Hints to circumvent scale out of bounds

Hello everyone :)

I have an application, in which I perform some homomorphic multiplications.
When I perform x2^2, x2x, and x2x3, the result is correct.
But when performing the last multiplication, x2*x7, the application simply breakes with the following error:

terminate called after throwing an instance of 'std::invalid_argument'
what(): scale out of bounds

This is the snippet code of function:
`
Ciphertext g(Ciphertext x, Evaluator* evaluator, RelinKeys relin_keys){

    Ciphertext x1 = x;
    Ciphertext x2 = x;
    (*evaluator).square_inplace(x2);
    (*evaluator).relinearize_inplace(x2, relin_keys);

    Ciphertext x3 = x2;
    (*evaluator).multiply_inplace(x3,x);
    (*evaluator).relinearize_inplace(x3, relin_keys);

    Ciphertext x5 = x2;
    (*evaluator).multiply_inplace(x5,x3);
    (*evaluator).relinearize_inplace(x5, relin_keys);

    Ciphertext x7 = x2;
    (*evaluator).multiply_inplace(x7,x5);
    (*evaluator).relinearize_inplace(x7, relin_keys);

    return x7;

}`

This is the vector I am trying:
vector<double> input{ 2.2 , 0, 1, -3, -0.5 };

And this is my setup:
`EncryptionParameters parms = createParameters();

    auto context = SEALContext::Create(parms);
    print_line(__LINE__);
    cout << "Set encryption parameters and print" << endl;
    print_parameters(context);
    cout << endl;

    KeyGenerator keygen(context);
    auto public_key = keygen.public_key();
    auto secret_key = keygen.secret_key();
    auto relin_keys = keygen.relin_keys();

    Encryptor encryptor(context, public_key);
    Evaluator evaluator(context);
    Decryptor decryptor(context, secret_key);

    CKKSEncoder encoder(context);

    size_t slot_count = encoder.slot_count();
    cout << "Number of slots: " << slot_count << endl;

    double scale = pow(2.0, 30);`

Could anyone point a direction for me to solve this issue?
Actually, I will need to perform lots of multiplications, and I was thinking that the relinearize function would allow me to lighten my polynomial so that it could handle several multiplications.

Best regards :)

Support for hoisting in rotations

Hi folks. Is there any plan for, or existing work on, implementing hoisting in SEAL? That is, ordering the constituent parts of the rotation algorithm (for CRT batched plaintexts) so that some of those parts can be reused (instead of recalculated) in subsequent rotations? This is described in Section 5 of Faster Homomorphic Linear Transformations in HELib by Halevi and Shoup.

Hoisting would be very useful to me. I am considering implementing it myself, but (what I believe is) the relevant function is a bit... involved, so I don't want to dig in until I'm sure no one else has done it already.

Or perhaps there's a way to achieve hoisting with the current interface that I have missed? If so, please let me know!

Thanks in advance and thanks heaps for your work on SEAL.

Regarding the new features of v3.3.0

Hi there,
The released new version (3.3.0) has some nice properties, but there are little explanations.

  1. What is the mathematical background of preserving the noise budget after relinearization and rotation operations?
  2. What is the exact definition of "special prime"? why using this special prime?
  3. The new version also brings larger noise budgets of fresh ciphertext, what is the basic idea behind that?

Looking forward to detailed explanations or references.

best

Regarding CKKS decoding

Hi, there seems to be NAN returned during decoding of the CKKS scheme when the coefficient modulus is more than some multiples of small modulus prime.

Below is an example (20 50-bit small modulus) of just encoding and then decoding:
/ Encryption parameters:
| scheme: CKKS
| poly_modulus_degree: 8192
| coeff_modulus size: 1000 bits
\ noise_standard_deviation: 3.2

Number of slots: 4096
scale = 50 bits
Input vector:
[ 0.000, 1.100, 2.200, 3.300, ..., 0.000, 0.000, 0.000, 0.000 ]
decode output:
[ -nan, -nan, -nan, -nan, ..., -nan, -nan, -nan, -nan ]

Thanks.

Different results in Linux and macOS

I implemented the same code in both Linux and macOS, but the results are different. Here's a small example to show the difference: Just push back the value -11668621335293.000000 785 times into a vector, encrypt then decrypt the value, and the results are different between Linux and macOS. The Linux version resulted with a much larger fluctuation.

macOS version: 10.13.6
Linux version: Ubuntu 16.04.6 LTS

Scheme is CKKS, poly_modulus_degree 32768.

Here's the code (the utils.h is used for print_parameters and print_vector as in \examples):

#include <vector>
#include "utils.h"
#include "seal/seal.h"

using namespace std;
using namespace seal;

int main(){
    EncryptionParameters parms(scheme_type::CKKS);
    size_t poly_modulus_degree = 32768;
    parms.set_poly_modulus_degree(poly_modulus_degree);
    parms.set_coeff_modulus(CoeffModulus::Create(
        poly_modulus_degree, { 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 }));
    double scale = pow(2.0, 360);
    auto context = SEALContext::Create(parms);
    print_parameters(context);
    
    KeyGenerator keygen(context);
    auto public_key = keygen.public_key();
    auto secret_key = keygen.secret_key();
    Encryptor encryptor(context, public_key);
    Decryptor decryptor(context, secret_key);
    CKKSEncoder encoder(context);

    vector<double> input_vector;
    for(int i = 0; i < 785; i++){
        input_vector.push_back(-11668621335293.000000);
    }

    Plaintext input_plain;
    encoder.encode(input_vector, scale, input_plain);
    Ciphertext input_cipher;
    encryptor.encrypt(input_plain, input_cipher);
    decryptor.decrypt(input_cipher, input_plain);
    encoder.decode(input_plain, input_vector);
    print_vector(input_vector);
    return 0;
}

The results from macOS:

/
| Encryption parameters :
|   scheme: CKKS
|   poly_modulus_degree: 32768
|   coeff_modulus size: 840 (60 + 60 + 60 + 60 + 60 + 60 + 60 + 60 + 60 + 60 + 60 + 60 + 60 + 60) bits
\

    [ -11668621335293.000, -11668621335293.002, -11668621335293.000, -11668621335293.000, ..., 0.000, -0.000, 0.001, 0.001 ]

The results from Linux:

/
| Encryption parameters :
|   scheme: CKKS
|   poly_modulus_degree: 32768
|   coeff_modulus size: 840 (60 + 60 + 60 + 60 + 60 + 60 + 60 + 60 + 60 + 60 + 60 + 60 + 60 + 60) bits
\

    [ -11668621335268.215, -11668621335271.973, -11668621335271.979, -11668621335279.500, ..., -0.342, -0.342, -0.029, 0.033 ]

What could cause this difference?

Effectiveness of the Karatsuba multiplication in ciphertext multiplication.

Description

To multiply two size-2 ciphertext, (c0, c1) and (d0, d1), we compute three values c0*d0, c0*d1 + c1*d0 and c1*d1.

Current Status

  • Currently, SEAL uses Karatsuba to compute the second value as
    c0*d1 + c1*d0 = (c0 + d0) * (c1 + d1) - (c0*d0 + c1*d1)
    which save one multiplication as the cost of two more additions and one more subtraction, since the first and the third values are computed after all.

Observation

  • However, these multiplication, addition, subtraction are done over the finite field, i.e., mod p. I found the one more addition and subtraction of the Karatsuba method is somehow expensive, because it increases the mis-prediction of CPU instructions.

Simpler is Better

  • If we directly compute the second value c0 * d1 + c1 * d0, we actually only need one modulo reduction. Because the two multiplications can be done with lazy reduction.
  • I have do some experiences with NFLlib, can found that the naive method can be $10% -- 50%$ faster.

Regarding "scale of out bounds" error in SEAL 3.3 CKKS

Hi,

The following code is working fine in SEAL 3.2 CKKS:

    EncryptionParameters parms(scheme_type::CKKS);
    parms.set_poly_modulus_degree(8192);

    vector<SmallModulus> q_primes;
    q_primes.push_back(DefaultParams::small_mods_60bit(0));
    q_primes.push_back(DefaultParams::small_mods_60bit(1));
    parms.set_coeff_modulus(q_primes);

    auto context = SEALContext::Create(parms);
    CKKSEncoder encoder(context);
    auto scale = static_cast<double>(parms.coeff_modulus().back().value());
 
    vector<double> values(4096, 0);
    values[0] = 0.123;
    Plaintext plain_value;
    encoder.encode(values, scale, plain_value);

The equivalent code is throwing "scale of out bounds" error in SEAL 3.3 CKKS:

    EncryptionParameters parms(scheme_type::CKKS);
    parms.set_poly_modulus_degree(8192);

    vector<SmallModulus> q_primes = CoeffModulus::Create(8192, {60,60});
    parms.set_coeff_modulus(q_primes);

    auto context = SEALContext::Create(parms);
    CKKSEncoder encoder(context);
    auto scale = static_cast<double>(parms.coeff_modulus().back().value());

    vector<double> values(4096, 0);
    values[0] = 0.123;
    Plaintext plain_value;
    encoder.encode(values, scale, plain_value);

If scale is chosen less than 60 bit e.g. pow(2, 40), the encode() will proceed fine without error.

Is it an intended behavioural change in SEAL 3.3 compared to SEAL 3.2?

Is this related to the "special prime" being consumed?

In other words, the "special prime" is included in the overall loqQ but not being available for usage for encoding, encryption etc?

Thanks.

Context parameter values combination to operate on large integers

My configuration is as follows:

seal::EncryptionParameters parms(scheme_type::BFV);
size_t poly_modulus_degree = 16384;
parms.set_poly_modulus_degree(poly_modulus_degree);
parms.set_coeff_modulus(CoeffModulus::BFVDefault(poly_modulus_degree));
parms.set_plain_modulus(256);

The results are accurate when computing encrypted integers with values lesser than 10.
If I go with even bigger integers say over 100, I get "plain is not valid for encryption parameters" for a simple operation like adding.

CKKS default coeffmodulus

Hello,

I noticed there is a helper method CoeffModulus::BFVDefault which returns a good default vector of SmallModulus. Is there a way to generate the same for CKKS? If it will not be planned, how do you suggest to create a good vector of SmallModulus for the three security types (128, 192, 256) with say 4096, 8192, and 16384 poly modulus degrees?

Thank you!

Homomorphic operations on floating point numbers

Hello everyone

Is there any way of performing addition and multiplication over float? I noticed there is the CKKS encoder, but one aspect I didn't understand well is that it operates over a vector. I was wondering if there is a form of operating over two Cyphertexts instead of vectors. Does anyone have an example like this?

Best regards

Can I build this project on Visual Studio 2019 ?

Can I build this project on Visual Studio 2019? What's kind modification I need to make, or it is not possible?

I tried on VS 2019 and this is what I got in out put:

1>------ Build started: Project: SEAL, Configuration: Debug x64 ------
1>Configure Microsoft SEAL through CMake
1>Configuring Microsoft SEAL through CMake
1>Found CMake at C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe
1>Running CMake configuration in C:\Users\RustedWizard\Downloads\SEAL-master\SEAL-master\native\src.config
1>Not searching for unused variables given on the command line.
1>CMake Error at CMakeLists.txt:6 (project):
1> Generator
1>
1> Visual Studio 15 2017
1>-- Configuring incomplete, errors occurred!
1>See also "C:/Users/RustedWizard/Downloads/SEAL-master/SEAL-master/native/src/.config/CMakeFiles/CMakeOutput.log".
1>
1> could not find any instance of Visual Studio.
1>
1>
1>
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Microsoft\VC\v150\Microsoft.CppCommon.targets(128,5): error MSB3073: The command ""C:\Users\RustedWizard\Downloads\SEAL-master\SEAL-master\native\src\CMakeConfig.cmd" Debug "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE" "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.16.27023\include;;C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.16.27023\atlmfc\include;;C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\VS\include;;C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\ucrt;;;C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\winrt;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\Include\um;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\Include\um;"
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Microsoft\VC\v150\Microsoft.CppCommon.targets(128,5): error MSB3073: :VCEnd" exited with code 1.
1>Done building project "SEAL.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Also, I tried to modify the generator option in CmakeConfig.cmd to "%CMAKEPATH%" .. -G "Visual Studio 16 2019" and I got following output:

1>------ Build started: Project: SEAL, Configuration: Debug x64 ------
1>Configure Microsoft SEAL through CMake
1>Configuring Microsoft SEAL through CMake
1>Found CMake at C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe
1>Running CMake configuration in C:\Users\RustedWizard\Downloads\SEAL-master\SEAL-master\native\src.config
1>Not searching for unused variables given on the command line.
1>CMake Error : error : generator : Visual Studio 16 2019
1>Does not match the generator used previously: Visual Studio 15 2017
1>Either remove the CMakeCache.txt file and CMakeFiles directory or choose a different binary directory.
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Microsoft\VC\v150\Microsoft.CppCommon.targets(128,5): error MSB3073: The command ""C:\Users\RustedWizard\Downloads\SEAL-master\SEAL-master\native\src\CMakeConfig.cmd" Debug "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE" "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.16.27023\include;;C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.16.27023\atlmfc\include;;C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\VS\include;;C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\ucrt;;;C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.16299.0\winrt;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\Include\um;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\Include\um;"
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Microsoft\VC\v150\Microsoft.CppCommon.targets(128,5): error MSB3073: :VCEnd" exited with code 1.
1>Done building project "SEAL.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.