Commit 0005e552 authored by Hoang Gia NGUYEN's avatar Hoang Gia NGUYEN
Browse files

test

parent 3704e126
# Other stuff
cmake/SEALConfig.cmake
cmake/SEALConfigVersion.cmake
cmake/SEALTargets.cmake
native/src/seal/util/config.h
native/src/gsl
**/CMakeCache.txt
**/CMakeFiles
**/Makefile
**/.config
**/autom4te.cache/*
**/cmake_install.cmake
**/install_manifest.txt
.ycm_extra_conf.py
.vimrc
.lvimrc
.local_vimrc
**/*.code-workspace
**/.vscode
**/build
**/*.build
**/compile_commands.json
**/.DS_Store
**/GSL
**/*.args.json
thirdparty/zlib/*
!thirdparty/zlib/CMakeLists.txt
thirdparty/msgsl/*
!thirdparty/msgsl/CMakeLists.txt
thirdparty/googletest/*
!thirdparty/googletest/CMakeLists.txt
dotnet/nuget/nuget.exe
dotnet/nuget/SEALNet.nuspec
dotnet/nuget/SEALNet-multi.nuspec
dotnet/nuget/SEALNet.targets
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ib/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
...@@ -738,11 +738,7 @@ if(SEAL_BUILD_EXAMPLES) ...@@ -738,11 +738,7 @@ if(SEAL_BUILD_EXAMPLES)
add_subdirectory(native/examples) add_subdirectory(native/examples)
add_subdirectory(native/examples/hello) add_subdirectory(native/examples/hello)
add_subdirectory(native/examples/generic) add_subdirectory(native/examples/generic)
#add_subdirectory(native/examples/patternSearch) add_subdirectory(native/examples/patternSearch)
add_subdirectory(native/examples/patternSearch/v1)
add_subdirectory(native/examples/patternSearch/v2)
add_subdirectory(native/examples/similarityMatch/v1)
add_subdirectory(native/examples/ANN/v1)
target_link_libraries(sealexamples PRIVATE seal) target_link_libraries(sealexamples PRIVATE seal)
endif() endif()
......
# Microsoft SEAL
Microsoft SEAL is an easy-to-use open-source ([MIT licensed](LICENSE)) 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](https://www.microsoft.com/en-us/research/project/microsoft-seal).
This document pertains to Microsoft SEAL version 3.5.
Users of previous versions of the library should look at the [list of changes](CHANGES.md).
## Contents
- [Microsoft SEAL](#microsoft-seal)
- [Contents](#contents)
- [Introduction](#introduction)
<!-- - [Core Concepts](#core-concepts)
- [Homomorphic Encryption](#homomorphic-encryption)
- [Microsoft SEAL](#microsoft-seal-1) -->
- [Building Microsoft SEAL](#building-microsoft-seal)
- [Optional Dependencies](#optional-dependencies)
<!-- - [Microsoft GSL](#microsoft-gsl)
- [ZLIB](#zlib) -->
- [Windows](#windows)
<!-- - [Platform](#platform)
- [Building Microsoft SEAL](#building-microsoft-seal-1)
- [[Optional] Debug and Release builds](#optional-debug-and-release-builds)
- [[Optional] Microsoft GSL](#optional-microsoft-gsl)
- [[Optional] ZLIB](#optional-zlib)
- [Building Examples](#building-examples)
- [Building Unit Tests](#building-unit-tests) -->
- [Linux, macOS, and FreeBSD](#linux-macos-and-freebsd)
<!-- - [Building Microsoft SEAL](#building-microsoft-seal-2)
- [[Optional] Debug and Release Modes](#optional-debug-and-release-modes)
- [[Optional] Microsoft GSL](#optional-microsoft-gsl-1)
- [[Optional] ZLIB](#optional-zlib-1)
- [[Optional] Shared Library](#optional-shared-library)
- [Building Examples](#building-examples-1)
- [Building Unit Tests](#building-unit-tests-1)
- [Installing Microsoft SEAL](#installing-microsoft-seal)
- [Linking with Microsoft SEAL through CMake](#linking-with-microsoft-seal-through-cmake) -->
- [Android](#android)
- [Microsoft SEAL for .NET](#microsoft-seal-for-net)
- [From NuGet package](#from-nuget-package)
- [Windows](#windows-1)
<!-- - [Native Library](#native-library)
- [.NET Library](#net-library)
- [.NET Examples](#net-examples)
- [.NET Unit Tests](#net-unit-tests)
- [Using Microsoft SEAL for .NET in Your Own Application](#using-microsoft-seal-for-net-in-your-own-application)
- [Building Your Own NuGet Package](#building-your-own-nuget-package) -->
- [Linux and macOS](#linux-and-macos)
<!-- - [Native Library](#native-library-1)
- [.NET Library](#net-library-1)
- [.NET Examples](#net-examples-1)
- [.NET Unit Tests](#net-unit-tests-1)
- [Using Microsoft SEAL for .NET in Your Own Application](#using-microsoft-seal-for-net-in-your-own-application-1) -->
- [Android](#android-1)
- [Getting Started](#getting-started)
- [Contributing](#contributing)
- [Citing Microsoft SEAL](#citing-microsoft-seal)
<!-- - [Version 3.5](#version-35)
- [Version 3.4](#version-34)
- [Version 3.3](#version-33)
- [Version 3.2](#version-32)
- [Version 3.1](#version-31)
- [Version 3.0](#version-30) -->
## 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 scientist 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.
### 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 straightfoward 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 scheme allows 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 scheme is the only choice.
## Building Microsoft SEAL
### Optional Dependencies
Microsoft SEAL has no required dependencies, but certain optional features can be enabled if it is compiled with support for specific third-party libraries.
#### 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
ZLIB is a widely used compression library that implements the DEFLATE compression algorithm.
Microsoft SEAL can use ZLIB (if present) to automatically compress data that is serialized.
`Ciphertext` objects consist of a large number of integers modulo specific prime numbers (`coeff_modulus` primes).
When using the CKKS scheme, although these prime numbers can often be quite small (e.g., 30 bits), the numbers are nevertheless serialized as 64-bit integers.
In this case, more than half of data in a ciphertext are zeros that can be compressed away with a compression library, such as ZLIB.
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.
The compression is not only applied to `Ciphertext` objects, but to every serializable Microsoft SEAL object.
If ZLIB is available, it will be automatically 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.
**WARNING:** 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 by passing `compr_mode_type::none` to `SecretKey::save`.
### Windows
Microsoft SEAL comes with a Microsoft Visual Studio 2019 solution file `SEAL.sln` that can be used to conveniently build the library, examples, and unit tests.
Visual Studio 2019 is required to build Microsoft SEAL.
#### Platform
The Visual Studio solution `SEAL.sln` is configured to build Microsoft SEAL both for `Win32` and `x64` platforms. Please choose the right platform before building Microsoft SEAL.
The `SEAL_C` project and the .NET wrapper library `SEALNet` can only be built for `x64`.
#### Building Microsoft SEAL
Build the SEAL project `native\src\SEAL.vcxproj` from `SEAL.sln`.
This results in the static library `seal.lib` to be created in `lib\$(Platform)\$(Configuration)`.
When linking with applications, you need to add `native\src\` (full path) as an include directory for Microsoft SEAL header files.
#### [Optional] Debug and Release builds
You can easily switch from Visual Studio build configuration menu whether Microsoft SEAL should be built in `Debug` mode (no optimizations) or in `Release` mode.
Please note that `Debug` mode should not be used except for debugging Microsoft SEAL itself, as the performance will be orders of magnitude worse than in `Release` mode.
#### [Optional] Microsoft GSL
By default Microsoft GSL is downloaded as part of Microsoft SEAL library.
Microsoft GSL's header files are copied to `native\src\GSL` to be portable with Microsoft SEAL at the time of installation.
You can disable the dependency on Microsoft GSL by commenting out `#cmakedefine SEAL_USE_MSGSL` in [native\src\seal\util\config.h.in](native\src\seal\util\config.h.in).
#### [Optional] ZLIB
By default ZLIB is downloaded and compiled as part of Microsoft SEAL library.
ZLIB's static archive is included in Microsoft SEAL's static or shared target object.
You can disable the dependency on ZLIB by commenting out `#cmakedefine SEAL_USE_ZLIB` in [native\src\seal\util\config.h.in](native\src\seal\util\config.h.in).
#### Building Examples
Build the SEALExamples project `native\examples\SEALExamples.vcxproj` from `SEAL.sln`.
This results in an executable `sealexamples.exe` to be created in `bin\$(Platform)\$(Configuration)`.
#### Building Unit Tests
The unit tests require the Google Test framework to be installed.
The appropriate NuGet package is already listed in `native\tests\packages.config`, so once you attempt to build the SEALTest project `native\tests\SEALTest.vcxproj` from `SEAL.sln` Visual Studio will automatically download and install it for you.
### Linux, macOS, and FreeBSD
Microsoft SEAL is very easy to configure and build in Linux and macOS using CMake (>= 3.12).
A modern version of GNU G++ (>= 6.0) or Clang++ (>= 5.0) is needed.
In macOS the Xcode toolchain (>= 9.3) will work.
In macOS you will need CMake with command line tools. For this, you can either
1. install the cmake package with [Homebrew](https://brew.sh), or
1. download CMake directly from [cmake.org/download](https://cmake.org/download) and
[enable command line tools](https://stackoverflow.com/questions/30668601/installing-cmake-command-line-tools-on-a-mac).
Below we give instructions for how to configure, build, and install Microsoft SEAL either system-wide (global install), or for a single user (local install).
A system-wide install requires elevated (root) privileges.
#### 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 Microsoft SEAL library for your machine by executing the following commands:
```shell
cmake .
make
```
#### [Optional] Debug and Release Modes
By default Microsoft SEAL is built in `Release` mode.
You can easily switch between `Debug` mode (no optimizations) or `Release` mode in CMake configuration options as follows:
```shell
cmake . -DCMAKE_BUILD_TYPE=Debug
make
```
Please note that `Debug` mode should not be used except for debugging Microsoft SEAL itself, as the performance will be orders of magnitude worse than in `Release` mode.
#### [Optional] Microsoft GSL
By default Microsoft GSL is downloaded as part of Microsoft SEAL library.
Microsoft GSL's header files are copied to `native/src/GSL` to be portable with Microsoft SEAL at the time of installation.
You can disable the dependency on Microsoft GSL in CMake configuration options as follows:
```shell
cmake . -DSEAL_USE_MSGSL=OFF
make
```
#### [Optional] ZLIB
By default ZLIB is downloaded and compiled as part of Microsoft SEAL library.
ZLIB's static archive is included in Microsoft SEAL's static or shared target object.
You can disable the dependency on ZLIB in CMake configuration options as follows:
```shell
cmake . -DSEAL_USE_ZLIB=OFF
make
```
#### [Optional] Shared Library
By default Microsoft SEAL builds only a static library that is `libseal-3.5.a` on Unix-like platforms.
You can enable building a shared library, `libseal.so*` in Linux or `libseal*.dylib` in macOS, in CMake configuration options as follows:
```shell
cmake . -DBUILD_SHARED_LIBS=ON
make
```
#### Building Examples
By default Microsoft SEAL does not build examples. You can enable building examples in CMake configuration options as follows:
```shell
cmake . -DSEAL_BUILD_EXAMPLES=ON
make
```
The `sealexamples` executable is located in `native/bin/`.
#### Building Unit Tests
By default Microsoft SEAL does not build tests.
You can enable building tests in CMake configuration options as follows:
```shell
cmake . -DSEAL_BUILD_TESTS=ON
make
```
This downloads and compiles the [GoogleTest](https://github.com/google/googletest) framework as a part of Microsoft SEAL.
The `sealtest` executable is located `native/bin/`.
All unit tests should pass successfully.
#### Installing Microsoft SEAL
If you have root access to the system you can install Microsoft SEAL system-wide as follows:
```shell
cmake .
make
sudo make install
```
To instead install Microsoft SEAL locally, e.g., to `~/mylibs/`, do the following:
```shell
cmake . -DCMAKE_INSTALL_PREFIX=~/mylibs
make
make install
```
#### 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`:
```shell
find_package(SEAL 3.5 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 locally installed Microsoft SEAL, 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:
```shell
cd <directory containing your CMakeLists.txt>
cmake . -DCMAKE_PREFIX_PATH=~/mylibs
```
### Android
Microsoft SEAL can be compiled for Android. Under the `android` directory of the source tree you will find an [Android Studio](https://developer.android.com/studio) project that you can use to compile the library for Android. This project is meant only to generate native libraries that can then be called through the .NET library described in the following sections. Specifically, it does not contain any wrappers that can be used from the Java language.
## Microsoft SEAL for .NET
Microsoft SEAL provides a .NET Standard library that wraps the functionality in Microsoft SEAL for use in .NET development.
### From NuGet package
For .NET developers the easiest way of installing Microsoft SEAL is by using the multi-platform NuGet package available at [NuGet.org](https://www.nuget.org/packages/Microsoft.Research.SEALNet).
Simply add this package into your .NET project as a dependency and you are ready to go.
### Windows
The Microsoft Visual Studio 2019 solution file `SEAL.sln` contains the projects necessary to build the .NET assembly, a backing native shared library, .NET examples, and unit tests.
#### Native Library
Microsoft SEAL for .NET requires a native library that is invoked by the managed .NET library.
Build the SEAL_C project `native\src\SEAL_C_.vcxproj` from `SEAL.sln`.
Building SEAL_C results in the dynamic library `sealc.dll` to be created in `lib\$(Platform)\$(Configuration)`.
This library is meant to be used only by the .NET library, not by end users, and needs to be present in the same directory as your executable when running a .NET application.
#### .NET Library
Once you have built the shared native library (see above), build the SEALNet project `dotnet\src\SEALNet.csproj` from `SEAL.sln`.
Building SEALNet results in the assembly `SEALNet.dll` to be created in `lib\dotnet\$(Configuration)\netstandard2.0`.
This is the assembly you can reference in your application.
#### .NET Examples
Build the SEALNetExamples project `dotnet\examples\SEALNetExamples.csproj` from `SEAL.sln`.
This results in the assembly `SEALNetExamples.dll` to be created in `bin\dotnet\$(Configuration)\netcoreapp3.1`.
The project takes care of copying the native SEAL_C library to the output directory.
#### .NET Unit Tests
Build the SEALNet Test project `dotnet\tests\SEALNetTest.csproj` from `SEAL.sln`.
This results in the assembly `SEALNetTest.dll` to be created in `bin\dotnet\$(Configuration)\netcoreapp3.1`.
The project takes care of copying the native SEALNetNative library to the output directory.
#### Using Microsoft SEAL for .NET in Your Own Application
To use Microsoft SEAL for .NET in your own application you need to:
1. add a reference in your project to `SEALNet.dll`;
1. ensure `sealc.dll` is available for your application when run.
The easiest way to ensure this is to copy `sealc.dll` 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](dotnet/nuget/NUGET.md).
### Linux and macOS
Microsoft SEAL for .NET relies on a native shared library that can be easily configured and built using CMake (>= 3.12) and a modern version of GNU G++ (>= 6.0) or Clang++ (>= 5.0).
In macOS the Xcode toolchain (>= 9.3) will work.
For compiling .NET code you will need to install a .NET Core SDK (>= 3.1).
You can follow these [instructions for installing in Linux](https://dotnet.microsoft.com/download?initial-os=linux), or for [installing in macOS](https://dotnet.microsoft.com/download?initial-os=macos).
#### Native Library
If you only intend to run the examples and unit tests provided with Microsoft SEAL, you do not need to install the native shared library, you only need to compile it.
The SEALNetExamples and SEALNetTest projects take care of copying the native shared library to the appropriate assembly output directory.
Microsoft SEAL by default does not build SEAL_C.
You can enable it in CMake configuration options as follows:
```shell
cmake . -DSEAL_BUILD_SEAL_C=ON
make
```
This results in a shared native library `libsealc.so*` in Linux or `libsealc*.dylib` in macOS.
If you have root access to the system, you have the option to install the native shared library globally.
Then your application will always be able to find and load it.
Assuming Microsoft SEAL is build and installed globally, you can install the shared native library globally as follows:
```shell
sudo make install
```
#### .NET Library
To build the .NET Standard library, do the following:
```shell
dotnet build dotnet/src --configuration <Debug|Release>
```
This will result in a `SEALNet.dll` assembly to be created in `lib/dotnet/$(Configuration)/netstandard2.0`.
This assembly is the one you will want to reference in your own projects.
The optional `dotnet` parameter `--configuration <Debug|Release>` can be used to build either a `Debug` or `Release` version of the assembly.
#### .NET Examples
To build and run the .NET examples, do:
```shell
dotnet run -p dotnet/examples
```
As mentioned before, the .NET project will copy the shared native library to the assembly output directory.
You can use the `dotnet` parameter `--configuration <Debug|Release>` to run either `Debug` or `Release` versions of the examples.
#### .NET Unit Tests
To build and run the .NET unit tests, do:
```shell
dotnet test dotnet/tests
```
All unit tests should pass.
You can use the `dotnet` parameter `--configuration <Debug|Release>` to run `Debug` or `Relase` unit tests.
And you can use `--verbosity detailed` to print the list of unit tests that are being run.
#### Using Microsoft SEAL for .NET in Your Own Application
To use Microsoft SEAL for .NET in your own application you need to:
1. add a reference in your project to `SEALNet.dll`;
1. 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.
### Android
You can use [Android Studio](https://developer.android.com/studio) to build the native shared library used by the .NET Standard wrapper library. However, the easiest and recommended way to use Microsoft SEAL in Android is through the multiplatform NuGet package you can find at [NuGet.org](https://www.nuget.org/packages/Microsoft.Research.SEALNet). Just add this package to your [Xamarin](https://dotnet.microsoft.com/apps/xamarin) project in order to develop mobile applications using Microsoft SEAL and .NET. The native shared library and the .NET wrapper compile only for 64 bits, so only `arm64-v8a` and `x86_64` Android ABIs are supported.
## Getting Started
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 to demonstrate much of the API.
The code 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_ckks_basics.cpp` |`4_CKKS_Basics.cs` |Encrypted real number arithmetic using the CKKS scheme |
|`5_rotation.cpp` |`5_Rotation.cs` |Performing cyclic rotations on encrypted vectors in the BFV and CKKS schemes|
|`6_serialization.cpp`|`6_Serialization.cs`|Serializing objects in Microsoft SEAL |
|`7_performance.cpp` |`7_Performance.cs` |Performance tests |
It is recommeded 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.
**WARNING: It is impossible to use Microsoft SEAL correctly without reading all examples or by simply re-using the code from examples.
Any developer attempting to do so will inevitably produce code that is *vulnerable*, *malfunctioning*, or *extremely slow*.**
## Contributing
For contributing to Microsoft SEAL, please see [CONTRIBUTING.md](CONTRIBUTING.md).
## Citing Microsoft SEAL
To cite Microsoft SEAL in academic papers, please use the following BibTeX entries.
### Version 3.5
```tex
@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
```tex
@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
```tex
@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
```tex
@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
```tex
@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
```tex
@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}
}
```
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT license.
cmake_minimum_required(VERSION 3.10)
set(TEST_NAME patternSearch)
set(GENKEY_BIN ${TEST_NAME}_genkey)
set(ENCR_BIN ${TEST_NAME}_encrypt)
set(DECR_BIN ${TEST_NAME}_decrypt)
set(EVAL_BIN ${TEST_NAME}_evaluate)
set(SCR_TEST test.sh)
set(GENKEY_BIN_2 ${TEST_NAME}_genkey_v2)
set(ENCR_BIN_2 ${TEST_NAME}_encrypt_v2)
set(DECR_BIN_2 ${TEST_NAME}_decrypt_v2)
set(DECR_RESULT_BIN_2 ${TEST_NAME}_decrypt_result_v2)
set(EVAL_BIN_2 ${TEST_NAME}_evaluate_v2)
set(SCR_ENC encrypt.sh)
set(SCR_DEC decrypt.sh)
set(SCR_DEC_RESULT decrypt_result.sh)
set(SCR_EVAL eval.sh)
set(SCR_GEN genkey.sh)
set(SCR_TEST_V2 test_v2.sh)
set(GENKEY_SRCS
${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp
${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_genkey.cpp
)
set(ENCR_SRCS
${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp
${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_encrypt.cpp
)
set(DECR_SRCS
${CMAKE_CURRENT_LIST_DIR}/util.cpp
${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp
${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt.cpp
)
set(EVAL_SRCS
${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp
${CMAKE_CURRENT_LIST_DIR}/util.cpp
${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate.cpp
)
set(GENKEY_SRCS_2
${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp
${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_genkey_v2.cpp
)
set(ENCR_SRCS_2
${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp
${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_encrypt_v2.cpp
)
set(DECR_SRCS_2
${CMAKE_CURRENT_LIST_DIR}/util.cpp
${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp
${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt_v2.cpp
)
set(DECR_RESULT_SRCS_2
${CMAKE_CURRENT_LIST_DIR}/util.cpp
${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp
${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_decrypt_result_v2.cpp
)
set(EVAL_SRCS_2
${CMAKE_CURRENT_LIST_DIR}/seal_api.cpp
${CMAKE_CURRENT_LIST_DIR}/util.cpp
${CMAKE_CURRENT_LIST_DIR}/${TEST_NAME}_evaluate_v2.cpp
)
set(HEADER_FILES
${CMAKE_CURRENT_LIST_DIR}/seal_api.h
${CMAKE_CURRENT_LIST_DIR}/util.h
)
add_executable(${GENKEY_BIN} ${GENKEY_SRCS} ${HEADER_FILES})
add_executable(${ENCR_BIN} ${ENCR_SRCS} ${HEADER_FILES})
add_executable(${DECR_BIN} ${DECR_SRCS} ${HEADER_FILES})
add_executable(${EVAL_BIN} ${EVAL_SRCS} ${HEADER_FILES})
#target_include_directories(${TEST_NAME} PRIVATE ${HEADER_DIR})
add_executable(${GENKEY_BIN_2} ${GENKEY_SRCS_2} ${HEADER_FILES})
add_executable(${ENCR_BIN_2} ${ENCR_SRCS_2} ${HEADER_FILES})
add_executable(${DECR_BIN_2} ${DECR_SRCS_2} ${HEADER_FILES})
add_executable(${DECR_RESULT_BIN_2} ${DECR_RESULT_SRCS_2} ${HEADER_FILES})
add_executable(${EVAL_BIN_2} ${EVAL_SRCS_2} ${HEADER_FILES})
#target_include_directories(${TEST_NAME} PRIVATE ${HEADER_DIR})
# Import Microsoft SEAL
find_package(SEAL 3.5 REQUIRED)
# Link Microsoft SEAL
target_link_libraries(${GENKEY_BIN} SEAL::seal)
target_link_libraries(${ENCR_BIN} SEAL::seal)
target_link_libraries(${DECR_BIN} SEAL::seal)
target_link_libraries(${EVAL_BIN} SEAL::seal)
target_link_libraries(${GENKEY_BIN_2} SEAL::seal)
target_link_libraries(${ENCR_BIN_2} SEAL::seal)
target_link_libraries(${DECR_BIN_2} SEAL::seal)
target_link_libraries(${DECR_RESULT_BIN_2} SEAL::seal)
target_link_libraries(${EVAL_BIN_2} SEAL::seal)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
set_target_properties(${GENKEY_BIN}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}"
)
set_target_properties(${ENCR_BIN}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}"
)
set_target_properties(${DECR_BIN}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}"
)
set_target_properties(${EVAL_BIN}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}"
)
set_target_properties(${GENKEY_BIN_2}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}"
)
set_target_properties(${ENCR_BIN_2}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}"
)
set_target_properties(${DECR_BIN_2}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}"
)
set_target_properties(${DECR_RESULT_BIN_2}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}"
)
set_target_properties(${EVAL_BIN_2}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME}"
)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_TEST}
DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME})
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_ENC}
DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME})
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_DEC}
DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME})
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_DEC_RESULT}
DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME})
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_EVAL}
DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME})
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_GEN}
DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME})
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${SCR_TEST_V2}
DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_NAME})
\ No newline at end of file
#include "add.h"
using namespace std;
using namespace seal;
void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, Plaintext &pt, Ciphertext &ct_out)
{
timeval t0, t1;
unsigned long dt = 0;
gettimeofday(&t0, NULL);
op_st.eval->add_plain(ct, pt, ct_out);
gettimeofday(&t1, NULL);
dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec);
cout << "[INFO] Homomorphic addition (pt+ct) time in (us): " << dt << endl;
}
void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out)
{
timeval t0, t1;
unsigned long dt = 0;
gettimeofday(&t0, NULL);
op_st.eval->add(ct1, ct2, ct_out);
gettimeofday(&t1, NULL);
dt = 1000000 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec);
cout << "[INFO] Homomorphic addition (ct+ct) time in (us): " << dt << endl;
}
#ifndef _ADD_H_
#define _ADD_H_
#include <sys/time.h>
#include <iostream>
#include <string>
#include "seal/seal.h"
#include "seal_api.h"
void add_ciphertext(struct evaluator_t& op_st, seal::Ciphertext &ct, seal::Plaintext &pt, seal::Ciphertext &ct_out);
void add_ciphertext(struct evaluator_t& op_st, seal::Ciphertext &ct1, seal::Ciphertext &ct2, seal::Ciphertext &ct_out);
#endif
#decrypt
resultPath=$1
# ex: result/l.ct
sample=$2
# ex: 40
keyDir=$3
# ex: keys/
CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
# time ./patternSearch_decrypt_v2 "$resultPath" "$sample" "$keyDir"
time ${CURR_DIR}/patternSearch_decrypt_v2 "$resultPath" "$sample" "$keyDir"
\ No newline at end of file
#decrypt result
resultPath=$1
# ex: result/l.ct
sample=$2
# ex: 40
keyDir=$3
# ex: keys/
CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
# time ./patternSearch_decrypt_result_v2 "$resultPath" "$sample" "$keyDir"
time ${CURR_DIR}/patternSearch_decrypt_result_v2 "$resultPath" "$sample" "$keyDir"
\ No newline at end of file
#encrypt
licenseNo=$1
# ex: "23 65 78 127 255" (en ASCII)
filename=$2
# ex: "l" (extension will be .ct)
outputDir=$3
# ex: lcheck/
sample=$4
# ex: 40
keyDir=$5
# ex: keys/
CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
# time ./patternSearch_encrypt_v2 "$licenseNo" "$filename" "$outputDir" "$sample" "$keyDir"
time ${CURR_DIR}/patternSearch_encrypt_v2 "$licenseNo" "$filename" "$outputDir" "$sample" "$keyDir"
\ No newline at end of file
# evaluate
licensePath=$1
# ex: lcheck/l.ct
licensePathList=${@: 2:$#-5}
# licensePathList="${@:2:102}"
# for var in "${@: 2:$#-7}"
# do
# echo "$var"
# done
# ex: parent/l0/l.ct parent/l1/l.ct parent/l2/l.ct parent/l3/l.ct parent/l4/l.ct parent/l5/l.ct parent/l6/l.ct parent/l7/l.ct parent/l8/l.ct parent/l9/l.ct
filename=${@: -4:1}
# ex: "l" (extension will be .ct)
outputDir=${@: -3:1}
# ex: result/
sample=${@: -2:1}
# ex: 40
KeyDir=${@: -1}
# ex: keys/
# linkingKeyPath=${@: -3:1}
# # ex: bfv.lk
# galoisKeyPath=${@: -2:1}
# # ex: bfv.gk
# publicKeyPath=${@: -1}
# # ex: bfv.pk
CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
# time ./patternSearch_evaluate_v2 "$licensePath" $licensePathList "$filename" "$outputDir" "$sample" "$linkingKeyPath" "$galoisKeyPath" "$publicKeyPath"
# time ./patternSearch_evaluate_v2 "$licensePath" $licensePathList "$filename" "$outputDir" "$sample" "$KeyDir"
time ${CURR_DIR}/patternSearch_evaluate_v2 "$licensePath" $licensePathList "$filename" "$outputDir" "$sample" "$KeyDir"
\ No newline at end of file
#gen key
keyDir=$1
# ex: keys/
CURR_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
# time ./patternSearch_genkey_v2 "$keyDir"
time ${CURR_DIR}/patternSearch_genkey_v2 "$keyDir"
\ No newline at end of file
84 2 30 99 33 9 38 92 28 47
47 44 39 0 73 83 71 9 86 66
59 28 11 67 99 36 39 28 12 4
36 15 40 12 93 5 20 85 58 98
73 95 64 79 16 52 8 26 8 26
54 24 60 39 41 57 87 7 60 62
94 78 67 66 27 90 87 78 35 50
78 31 21 15 26 57 56 35 65 14
64 99 78 31 58 59 47 55 9 92
6 33 9 68 36 74 67 93 94 77
49 35 62 93 55 16 50 44 42 7
59 76 99 2 20 48 76 25 71 10
51 38 9 66 15 95 44 72 58 76
26 37 47 55 21 55 10 69 18 66
17 6 15 93 28 97 49 87 62 92
15 77 50 72 94 88 58 99 52 21
88 65 84 55 25 15 78 96 37 57
41 26 66 54 70 26 17 14 26 71
11 79 62 25 96 33 99 69 26 74
4 2 58 4 62 92 43 70 86 49
#include "seal_api.h"
#include "util.h"
using namespace seal;
using namespace std;
string ciphertext_name;
string secret_key_path;
string decrypt(string &ciphertext_dir);
bool decrypt_vector(string &ciphertext_dir);
string decrypt_vectors(string &parent_dir);
bool decrypt_isContain(string &result);
int main(int argc, char **argv)
{
if (argc != 3)
// cout << "[ERROR] please enter /full/path/to/file/to/decrypt full/path/key " << endl;
// cout << "[ERROR] please enter prefix_file_to_decrypt full/path/key /full/path/to/storage" << endl;
// cout << "[ERROR] please enter a ciphertext name, ciphertext directory and secret key path" << endl;
cout << "[ERROR] please enter a ciphertext file path and secret key path" << endl;
else
{
string dir = argv[1];
secret_key_path = argv[2];
string result_str = decrypt(dir);
// cout << result_str << endl;
bool result = decrypt_isContain(result_str);
cout << result << endl;
return 0;
}
}
bool decrypt_isContain(string &result)
{
long result_l = atol(result.c_str());
if (result_l == 0)
{
// cout << "true";
return true;
}
else
{
// cout << "false";
return false;
}
}
string decrypt(string &ciphertext_dir)
{
struct decryptor_t decr;
init_operator(decr, secret_key_path);
Ciphertext ct;
string str;
load_ciphertext(decr, ct, ciphertext_dir);
str = to_string(decrypt_ciphertext_and_return_value(decr, ct));
// decrypt_ciphertext(decr, ct);
delete_operator(decr);
return str;
}
// Used for dynamic search
// string decrypt_vectors(string &parent_dir)
// {
// vector<string> directories = get_directories(parent_dir);
// string path_result = "";
// bool result;
// for (const auto &entry : directories)
// {
// string ciphertext_dir = entry + "/";
// cout << ciphertext_dir << endl;
// result = decrypt_vector(ciphertext_dir);
// if (result == true)
// {
// path_result = ciphertext_dir;
// break;
// }
// }
// return path_result;
// }
// Used for dynamic search
// bool decrypt_vector(string &ciphertext_dir)
// {
// int nFiles = findNumberOfFilesInDirectory(ciphertext_dir);
// struct decryptor_t decr;
// init_operator(2048, 256, decr, secret_key_path);
// Ciphertext ct;
// string plaintext;
// stringstream ss;
// for (int index = 0; index <= nFiles - 1; index++)
// {
// load_ciphertext(decr, ct, ciphertext_dir + "/" + ciphertext_name + "_" + to_string(index) + ".ct");
// plaintext = decrypt_ciphertext_and_return_string(decr, ct);
// if (index == nFiles - 1)
// {
// ss << plaintext;
// }
// else
// {
// ss << plaintext << " ";
// }
// }
// // cout << to_string(ss.str().size());
// // cout << ss.str() << endl;
// int x;
// int index = 0;
// bool result = false;
// while (ss >> x)
// {
// if (x == 0)
// {
// result = true;
// }
// else
// {
// result = false;
// break;
// }
// index++;
// }
// // if (index > 0 && result == true)
// // {
// // cout << "true" << endl;
// // }
// delete_operator(decr);
// return result;
// }
#include <iomanip>
#include "seal_api.h"
#include "util.h"
using namespace seal;
using namespace std;
string ciphertext_name;
string key_dir;
// bool decrypt(size_t poly_d, size_t p_modulus, int &sample_size, string &ciphertext_dir);
bool decrypt(int &sample_size, string &ciphertext_dir);
int main(int argc, char **argv)
{
if (argc != 4)
{
// cout << "[ERROR] please enter /full/path/to/file/to/decrypt full/path/key " << endl;
// cout << "[ERROR] please enter prefix_file_to_decrypt full/path/key /full/path/to/storage" << endl;
// cout << "[ERROR] please enter a ciphertext file path, sample size and secret key path" << endl;
return -1;
}
else
{
string dir = argv[1];
int sample_size = atol(argv[2]);
key_dir = argv[3];
bool result_str = decrypt(sample_size, dir);
cout << result_str << endl;
return 0;
}
}
bool decrypt(int &sample_size, string &ciphertext_dir)
{
struct decryptor_t decr;
init_operator_batching(decr, key_dir);
bool isContain = false;
if (sample_size <= decr.bcode->slot_count()/2)
{
Ciphertext cipher_matrix;
vector<int64_t> pod_matrix;
load_ciphertext(decr, cipher_matrix, ciphertext_dir);
pod_matrix = decrypt_ciphermatrix(decr, cipher_matrix);
// cout << pod_matrix.size() << endl;
int no_dual_vectors = (decr.bcode->slot_count() / 2) / (sample_size);
vector<int64_t> v1, v2;
for (size_t i = 0; i < no_dual_vectors * sample_size; i++)
{
v1.push_back(pod_matrix[i]);
v2.push_back(pod_matrix[(pod_matrix.size() / 2) + i]);
}
int64_t sum = 0;
if (isContain == false)
{
// cout << "1 : ";
for (size_t i = 0; i < v1.size(); i++)
{
// cout << v1[i];
if ((i + 1) % sample_size == 0)
{
// cout << endl;
if (i < v1.size() - 1)
{
// cout << ((i + 1) / 40) + 1 << " : ";
}
}
else
{
// cout << ", ";
}
if (v1[i] == 0)
{
sum = sum + 1;
}
else
{
sum = 0;
}
if (sum == sample_size)
{
isContain = true;
}
}
}
// cout << endl;
if (isContain == false)
{
sum = 0;
// cout << (v2.size() + 1) / 40 + 1 << " : ";
for (size_t i = 0; i < v2.size(); i++)
{
// cout << v2[i];
if ((i + 1) % sample_size == 0)
{
// cout << endl;
if (i < v2.size() - 1)
{
// cout << ((v2.size() + i + 1) / 40) + 1 << " : ";
}
}
else
{
// cout << ", ";
}
if (v2[i] == 0)
{
sum = sum + 1;
}
else
{
sum = 0;
}
if (sum == sample_size)
{
isContain = true;
}
}
}
}
else
{
// cout << endl << "Sample size is too large" << endl;
}
delete_operator_batching(decr);
return isContain;
}
#include <iomanip>
#include "seal_api.h"
#include "util.h"
using namespace seal;
using namespace std;
string ciphertext_name;
string key_dir;
// vector<int64_t> decrypt(size_t poly_d, size_t p_modulus, int &sample_size, string &ciphertext_dir);
vector<int64_t> decrypt(int &sample_size, string &ciphertext_dir);
int main(int argc, char **argv)
{
if (argc != 4)
{
// cout << "[ERROR] please enter /full/path/to/file/to/decrypt full/path/key " << endl;
// cout << "[ERROR] please enter prefix_file_to_decrypt full/path/key /full/path/to/storage" << endl;
cout << "[ERROR] please enter a ciphertext file path, sample size and secret key path" << endl;
return -1;
}
else
{
string dir = argv[1];
int sample_size = atol(argv[2]);
key_dir = argv[3];
vector<int64_t> result = decrypt(sample_size, dir);
for (int i = 0; i < result.size(); ++i)
{
std::cout << result[i] << ' ';
}
std::cout << endl;
return 0;
}
}
vector<int64_t> decrypt(int &sample_size, string &ciphertext_dir)
{
struct decryptor_t decr;
init_operator_batching(decr, key_dir);
// init_operator_batching(2048, 4294967296, decr, key_dir);
// init_operator_batching(4096, 4294967296, decr, key_dir);
// init_operator_batching(8192, 4294967296, decr, key_dir);
// init_operator_batching(16384, 4294967296, decr, key_dir);
// init_operator_batching(32768, 4294967296, decr, key_dir);
vector<int64_t> v;
if (sample_size <= decr.bcode->slot_count()/2)
{
Ciphertext cipher_matrix;
vector<int64_t> pod_matrix;
load_ciphertext(decr, cipher_matrix, ciphertext_dir);
pod_matrix = decrypt_ciphermatrix(decr, cipher_matrix);
for (size_t i = 0; i < sample_size; i++)
{
v.push_back(pod_matrix[i]);
}
}
else
{
// cout << endl << "Sample size is too large" << endl;
}
delete_operator_batching(decr);
return v;
}
#include "seal_api.h"
using namespace seal;
using namespace std;
int main(int argc, char **argv)
{
if(argc != 5)
// cout << "[ERROR] please enter 1 plaintext values, prefix pathstorage(exists) " << endl;
// cout << "[ERROR] please enter plaintext value (eg. 75 67 8 23 076 2 23), public key path, ciphertext output directory and ciphertext output file name" << endl;
cout << "[ERROR] please enter plaintext vector value (eg. 75 67 8 23 076 2 23), output ciphertext file name or prefix, public key path and ciphertext output file directory" << endl;
else {
string plaintext = argv[1];
string ciphertext_name = argv[2];
string public_key_path = argv[3];
string ciphertext_dir = argv[4];
// cout << plaintext << endl;
struct encryptor_t encr;
// init_operator(2048, 256, encr, public_key_path);
init_operator(encr, public_key_path);
stringstream ss;
ss << plaintext;
int64_t x = 0;
int index = 0;
Ciphertext ct;
while (ss >> x)
{
/* Encrypt */
init_ciphertext(encr, x, ct);
save_ciphertext(ct, ciphertext_dir + "/" + ciphertext_name + "_" + to_string(index) + ".ct");
index++;
}
delete_operator(encr);
return 0;
}
}
#include "seal_api.h"
using namespace seal;
using namespace std;
int main(int argc, char **argv)
{
if (argc != 6)
{
// cout << "[ERROR] please enter 1 plaintext values, prefix pathstorage(exists) " << endl;
cout << "[ERROR] please enter plaintext vector value (eg. 75 67 8 23 076 2 23), output ciphertext file name or "
"prefix, ciphertext output file directory, sample size and public key path"
<< endl;
return -1;
}
else
{
string plaintext = argv[1];
string ciphertext_name = argv[2];
string ciphertext_dir = argv[3];
int sample_size = atol(argv[4]);
string key_dir = argv[5];
struct encryptor_t encr;
// init_operator_batching(2048, 4294967296, encr, public_key_path);
// init_operator_batching(4096, 4294967296, encr, public_key_path);
init_operator_batching(4096, 4294967296, encr, key_dir);
// init_operator_batching(16384, 4294967296, encr, public_key_path);
// init_operator_batching(32768, 4294967296, encr, public_key_path);
stringstream ss;
ss << plaintext;
vector<int64_t> pod_matrix;
int64_t x = 0;
while (ss >> x)
{
pod_matrix.push_back(x);
}
if (pod_matrix.size() <= encr.bcode->slot_count() / 2 && pod_matrix.size() <= sample_size)
{
Ciphertext encrypted_matrix;
init_ciphermatrix(encr, pod_matrix, encrypted_matrix);
save_ciphertext(encrypted_matrix, ciphertext_dir + "/" + ciphertext_name + ".ct");
delete_operator_batching(encr);
return 0;
}
else
{
delete_operator_batching(encr);
return -1;
}
// delete_operator_batching(encr);
// return 0;
}
}
#include "seal_api.h"
using namespace seal;
using namespace std;
int main(int argc, char **argv)
{
if (argc != 6)
{
// cout << "[ERROR] please enter 1 plaintext values, prefix pathstorage(exists) " << endl;
cout << "[ERROR] please enter plaintext vector value (eg. 75 67 8 23 076 2 23), output ciphertext file name or "
"prefix, ciphertext output file directory, sample size and public key path"
<< endl;
return -1;
}
else
{
string plaintext = argv[1];
string ciphertext_name = argv[2];
string ciphertext_dir = argv[3];
int sample_size = atol(argv[4]);
string key_dir = argv[5];
struct encryptor_t encr;
init_operator_batching(encr, key_dir);
stringstream ss;
ss << plaintext;
vector<int64_t> pod_matrix;
int64_t x = 0;
while (ss >> x)
{
pod_matrix.push_back(x);
}
if (pod_matrix.size() <= encr.bcode->slot_count() / 2 && pod_matrix.size() <= sample_size)
{
Ciphertext encrypted_matrix;
init_ciphermatrix(encr, pod_matrix, encrypted_matrix);
save_ciphertext(encrypted_matrix, ciphertext_dir + "/" + ciphertext_name + ".ct");
delete_operator_batching(encr);
return 0;
}
else
{
delete_operator_batching(encr);
return -1;
}
// delete_operator_batching(encr);
// return 0;
}
}
#include "seal_api.h"
#include "util.h"
#include <iostream>
// #include <algorithm>
// #include <iterator>
// #include <vector>
// #include <filesystem>
using namespace seal;
std::string relink_key_path;
void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out);
void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out);
void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out);
void isContain(std::vector<std::vector<std::string>> &v_v, std::string &result_name, std::string &result_dir, std::string &relink_key_path);
bool is_number(const std::string &s);
void printStrVector(const std::vector<std::string> &v);
std::vector<std::vector<std::string>> split_ends(const std::vector<std::string> &source, const std::vector<int> &ends);
void multiply_ciphertexts(struct evaluator_t &op_st, std::vector<Ciphertext> &cts, Ciphertext &ct_out);
void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct);
void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct);
void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2);
void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out);
void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2);
void negate_inplace__ciphertext(struct evaluator_t &op_st, Ciphertext &ct);
void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain);
void multiply_plain_inplace(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain);
void add_many_ciphertext(struct evaluator_t &op_st, std::vector<Ciphertext> &cts, Ciphertext &ct_out);
void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent);
void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain);
void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct);
// void sub_vector(std::string &ciphertext_name2, std::string &ciphertext_dir2, std::string &result_name, std::string &result_dir);
// void sub_vectors(std::string &parent_dir, std::string &result_name, std::string &result_dir);
int main(int argc, char **argv)
{
// if (argc != 7)
// std::cout << "[ERROR] please enter prefix_file_to_decrypt_1 /full/path/to/storage_1 "
// "/full/path/to/parent prefix_result_file /full/path/to/result_storage full/path/to/relink/key"
// << std::endl;
// cout << "[ERROR] please enter prefix_file_to_decrypt_1 /full/path/to/storage_1 prefix_file_to_decrypt_2 "
// "/full/path/to/storage_2 prefix_result_file /full/path/to/result_storage full/path/to/relink/key"
// << endl;
// cout << "[ERROR] please enter name and directory of 1st ciphertexts, name and directory of 2nd ciphertexts, name
// and directory of result ciphertexts, and relink key path" << endl;
// else
std::string ciphertext_name1 = argv[1];
// ciphertext_dir1 = argv[2];
std::string result_name = argv[argc - 3];
std::string result_dir = argv[argc - 2];
relink_key_path = argv[argc - 1];
std::vector<std::string> source;
// std::vector<int> ends;
std::vector<std::vector<std::string>> v_v;
for (int i = 2; i < argc - 3; i++)
{
if (is_number(argv[i]))
{
// ends.push_back(std::stoi( argv[i]) );
int len = std::stoi( argv[i]);
std::vector<std::string> source;
for (int i2 = 1; i2 <= len; i2++)
{
source.push_back(argv[i + i2]);
}
v_v.push_back(source);
}
// else
// {
// source.push_back(argv[i]);
// std::cout << "[ERROR]" << argv[i] << std::endl;
// }
}
// auto splitted = split_ends(source, ends);
// for (const auto& v: v_v) {
// printStrVector(v);
// // std::cout << '\n';
// }
isContain(v_v, result_name, result_dir, relink_key_path);
std::cout << "done" << std::endl;
return 1;
}
void isContain(std::vector<std::vector<std::string>> &v_v, std::string &result_name, std::string &result_dir, std::string &relink_key_path)
{
struct evaluator_t eval;
// init_operator(8192, 4294967296, eval, relink_key_path);
init_operator(eval, relink_key_path);
Ciphertext result;
std::vector<Ciphertext> cts;
// std::cout << v_v.size() -1 << std::endl;
for (int index = 1; index < v_v.size(); index++)
{
Ciphertext ct3;
int noFiles1 = v_v.at(0).size();
int noFiles2 = v_v.at(index).size();
// std::cout << noFiles1 -1 << std::endl;
if (noFiles1 == noFiles2)
{
std::vector<Ciphertext> cts2;
for (int index2 = 0; index2 < noFiles1; index2++)
{
Ciphertext ct1, ct2;
Ciphertext temp;
// std::cout << "[INFO] loading ciphertext 1" << std::endl;
load_ciphertext(eval, ct1, v_v.at(0).at(index2));
// std::cout << "[INFO] loading ciphertext 2" << std::endl;
load_ciphertext(eval, ct2, v_v.at(index).at(index2));
// std::cout << "[INFO] subtracting ciphertext 2 from ciphertext 1" << std::endl;
sub_ciphertext(eval, ct1, ct2, temp);
// u_int64_t x = 2;
// exponentiate_inplace_ciphertext(eval, temp, x);
cts2.push_back(temp);
}
add_many_ciphertext(eval, cts2, ct3);
relinearize_inplace(eval, ct3);
}
else
{
// number of files is different in 2 directories
}
cts.push_back(ct3);
// if(index == 1)
// {
// result = ct3;
// }
// else
// {
// multiply_inplace_ciphertext(eval, result, ct3);
// relinearize_inplace(eval, result);
// mod_switch_to_next_inplace_ciphertext(eval, result);
// }
}
multiply_ciphertexts(eval, cts, result);
// mod_switch_to_next_inplace_ciphertext(eval, result);
save_ciphertext(result, result_dir + "/" + result_name + ".ct");
delete_operator(eval);
}
void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out)
{
op_st.eval->sub(ct1, ct2, ct_out);
}
void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2)
{
op_st.eval->sub_inplace(ct1, ct2);
}
void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain)
{
op_st.eval->sub_plain_inplace(ct, plain);
}
void negate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct)
{
op_st.eval->negate_inplace(ct);
}
void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain)
{
op_st.eval->add_plain_inplace(ct, plain);
}
void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out)
{
op_st.eval->add(ct1, ct2, ct_out);
}
void add_many_ciphertext(struct evaluator_t &op_st, std::vector<Ciphertext> &cts, Ciphertext &ct_out)
{
op_st.eval->add_many(cts, ct_out);
}
void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out)
{
op_st.eval->multiply(ct1, ct2, ct_out);
}
void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2)
{
op_st.eval->multiply_inplace(ct1, ct2);
}
void multiply_ciphertexts(struct evaluator_t &op_st, std::vector<Ciphertext> &cts, Ciphertext &ct_out)
{
op_st.eval->multiply_many(cts, op_st.lk, ct_out);
}
void multiply_plain_inplace(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain)
{
op_st.eval->multiply_plain_inplace(ct, plain);
}
void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct)
{
op_st.eval->relinearize_inplace(ct, op_st.lk);
}
void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out)
{
op_st.eval->relinearize(ct, op_st.lk, ct_out);
}
void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct)
{
op_st.eval->rescale_to_next_inplace(ct);
}
void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent)
{
op_st.eval->exponentiate_inplace(ct, exponent, op_st.lk);
}
void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct)
{
op_st.eval->mod_switch_to_next_inplace(ct);
}
// // void isContain(std::string &parent_dir, std::string &result_name, std::string &result_dir)
// void isContain(std::string *dirs, int &len, std::string &result_name, std::string &result_dir)
// {
// struct evaluator_t eval;
// // init_operator(2048, 256, eval, relink_key_path);
// init_operator(8192, 4294967296, eval, relink_key_path);
// Ciphertext ct1, ct2, ct3, result;
// // std::cout << "[ERROR]" << std::endl;
// for (int index = 0; index < len; index++)
// {
// // std::cout << "[ERROR]" << dirs[index] << std::endl;
// std::string ciphertext_dir2 = dirs[index];
// // std::cout << ciphertext_dir2 << std::endl;
// int noFiles1 = findNumberOfFilesInDirectory(ciphertext_dir1);
// int noFiles2 = findNumberOfFilesInDirectory(ciphertext_dir2);
// if (noFiles1 == noFiles2)
// {
// for (int index2 = 0; index2 < noFiles1; index2++)
// {
// // std::cout << "[INFO] loading ciphertext 1" << std::endl;
// // load_ciphertext(eval, ct1, ciphertext_dir1 + "/" + ciphertext_name1 + "_" + std::to_string(index) +
// // ".ct");
// load_ciphertext(eval, ct1, ciphertext_dir1 + ciphertext_name1 + "_" + std::to_string(index2) + ".ct");
// // std::cout << "[INFO] loading ciphertext 2" << std::endl;
// // load_ciphertext(eval, ct2, ciphertext_dir2 + "/" + ciphertext_name1 + "_" + std::to_string(index) +
// // ".ct");
// load_ciphertext(eval, ct2, ciphertext_dir2 + ciphertext_name1 + "_" + std::to_string(index2) + ".ct");
// // std::cout << "[INFO] subtracting ciphertext 2 from ciphertext 1" << std::endl;
// sub_ciphertext(eval, ct1, ct2, ct1);
// if (index2 == 0)
// {
// ct3 = ct1;
// }
// else
// {
// add_ciphertext(eval, ct3, ct1, ct3);
// }
// }
// }
// else
// {
// // number of files is different in 2 directories
// }
// if (index == 0)
// {
// result = ct3;
// }
// else
// {
// multiply_ciphertext(eval, result, ct3, ct3);
// }
// }
// save_ciphertext(ct3, result_dir + "/" + result_name + ".ct");
// delete_operator(eval);
// }
// // Used for dynamic search
// void sub_vectors(std::string &ciphertext_name1, std::string &ciphertext_dir1, std::string &parent_dir, std::string &result_name, std::string &result_dir, std::string &relink_key_path)
// {
// std::vector<std::string> directories = get_directories(parent_dir);
// // for (const auto &entry : std::filesystem::directory_iterator(path))
// for (const auto &entry : directories)
// {
// // std::cout << entry << std::endl;
// std::string ciphertext_dir2 = entry + "/";
// std::string result_dir2 = result_dir + ciphertext_dir2;
// // std::cout << result_dir2 << std::endl;
// // std::cout << ciphertext_dir2 << std::endl;
// std::filesystem::create_directories(result_dir2);
// sub_vector(ciphertext_name1, ciphertext_dir2, result_name, result_dir2);
// // file reduction
// // std::cout << "[INFO] file reduction!!!" << std::endl;
// struct evaluator_t eval;
// init_operator(2048, 256, eval, relink_key_path);
// Ciphertext ct1, ct2, ct3;
// int noFiles = findNumberOfFilesInDirectory(result_dir2);
// for (int index = 1; index < noFiles; index++)
// {
// // std::cout << "[INFO] loading ciphertext 1" << std::endl;
// load_ciphertext(eval, ct1, result_dir2 + result_name + "_" + "0" + ".ct");
// // std::cout << "[INFO] loading ciphertext 2" << std::endl;
// load_ciphertext(eval, ct2, result_dir2 + result_name + "_" + std::to_string(index) + ".ct");
// // std::cout << "[INFO] addition ciphertext 1 with ciphertext 2" << std::endl;
// add_ciphertext(eval, ct1, ct2, ct1);
// // std::cout << "[INFO] saving ciphertext addition to a new ciphertext file" << std::endl;
// save_ciphertext(ct1, result_dir2 + result_name + "_" + "0" + ".ct");
// std::filesystem::remove(result_dir2 + result_name + "_" + std::to_string(index) + ".ct");
// }
// }
// }
// // Used for dynamic search
// void sub_vector(std::string &ciphertext_name1, std::string &ciphertext_dir1, std::string &ciphertext_name2, std::string &ciphertext_dir2, std::string &result_name, std::string &result_dir, std::string &relink_key_path)
// {
// struct evaluator_t eval;
// int noFiles1 = findNumberOfFilesInDirectory(ciphertext_dir1);
// int noFiles2 = findNumberOfFilesInDirectory(ciphertext_dir2);
// // init_operator(2048, 256, eval);
// init_operator(2048, 256, eval, relink_key_path);
// Ciphertext ct1, ct2, ct3;
// if (noFiles1 == noFiles2)
// {
// for (int index = 0; index < noFiles1; index++)
// {
// // std::cout << "[INFO] loading ciphertext 1" << std::endl;
// load_ciphertext(eval, ct1, ciphertext_dir1 + "/" + ciphertext_name1 + "_" + std::to_string(index) + ".ct");
// // std::cout << "[INFO] loading ciphertext 2" << std::endl;
// load_ciphertext(eval, ct2, ciphertext_dir2 + "/" + ciphertext_name2 + "_" + std::to_string(index) + ".ct");
// // std::cout << "[INFO] subtracting ciphertext 2 from ciphertext 1" << std::endl;
// sub_ciphertext(eval, ct1, ct2, ct3);
// // std::cout << "[INFO] saving ciphertext subtraction to a new ciphertext file" << std::endl;
// save_ciphertext(ct3, result_dir + "/" + result_name + "_" + std::to_string(index) + ".ct");
// }
// }
// else
// {}
// delete_operator(eval);
// }
// Input processing
bool is_number(const std::string &s)
{
std::string::const_iterator it = s.begin();
while (it != s.end() && std::isdigit(*it)) ++it;
return !s.empty() && it == s.end();
}
// C++11
// bool is_number(const std::string& s)
// {
// return !s.empty() && std::find_if(s.begin(),
// s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
// }
// std::vector<std::vector<std::string>> split_ends(const std::vector<std::string> &source, const std::vector<int> &ends)
// {
// std::vector<std::vector<std::string>> result;
// result.reserve(ends.size());
// auto anchor_front = source.begin();
// for (auto one_end: ends)
// {
// auto anchor_end = std::next(source.begin(), one_end + 1);
// result.emplace_back(anchor_front, anchor_end);
// anchor_front = anchor_end;
// }
// return result;
// }
// void printStrVector(const std::vector<std::string>& v)
// {
// for (auto x: v)
// {
// std::cout << x << ' ';
// }
// }
\ No newline at end of file
#include <iostream>
#include "seal_api.h"
#include "util.h"
// #include <algorithm>
// #include <iterator>
// #include <vector>
// #include <filesystem>
using namespace seal;
using namespace std;
void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out);
void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out);
void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out);
bool is_number(const string &s);
void printStrVector(const vector<string> &v);
vector<vector<string>> split_ends(const vector<string> &data, const vector<int> &ends);
void multiply_ciphertexts(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out);
void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct);
void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct);
void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2);
void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out);
void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2);
void negate_inplace__ciphertext(struct evaluator_t &op_st, Ciphertext &ct);
void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain);
void multiply_plain_inplace(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain);
void add_many_ciphertext(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out);
void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent);
void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain);
void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct);
int simpleCheck(
string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir);
int checkSq(
string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir);
Ciphertext check(
string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir,
struct encryptor_t &encr, struct evaluator_t &eval);
// string relink_key_path;
// string galois_key_path;
// string public_key_path;
string key_dir = "";
int main(int argc, char **argv)
{
// input processing - begin
// string result_name = argv[argc - 6];
// string result_dir = argv[argc - 5];
// int sample_size = atoi(argv[argc - 4]);
// relink_key_path = argv[argc - 3];
// galois_key_path = argv[argc - 2];
// public_key_path = argv[argc - 1];
string source = argv[1];
string result_name = argv[argc - 4];
string result_dir = argv[argc - 3];
int sample_size = atoi(argv[argc - 2]);
key_dir = argv[argc - 1];
vector<string> data;
for (int i = 2; i < argc - 4; i++)
{
data.push_back(argv[i]);
}
// if (source == "" || data.size() == 0 || result_name == "" || result_dir == "" || sample_size == 0 ||
// relink_key_path == "" || galois_key_path == "" || public_key_path == "")
if (source == "" || data.size() == 0 || result_name == "" || result_dir == "" || sample_size == 0 || key_dir == "")
{
// error handling
cout << "[ERROR] please enter a source path, data paths, output ciphertext file name or prefix, output "
"ciphertext directory, sample size, linking key path, galois key path and public key path"
<< endl;
return -1;
}
// input processing - end
// simple algo
// int result = simpleCheck(source, data, result_name, result_dir, sample_size, key_dir);
// sequence algo
int result = checkSq(source, data, result_name, result_dir, sample_size, key_dir);
// error handling
if (result == -1)
{
fprintf(stderr, "error!\n");
}
else
{
cout << "done";
}
// checkSq(source, data, result_name, result_dir, sample_size, relink_key_path, galois_key_path, public_key_path);
return result;
}
int simpleCheck(
string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir)
{
struct evaluator_t eval;
init_operator_batching(eval, key_dir);
struct encryptor_t encr;
init_operator_batching(encr, key_dir);
// cout << sample_size*data.size() << endl;
// cout << encr.bcode->slot_count() << endl;
if (sample_size*data.size() > encr.bcode->slot_count() || sample_size > encr.bcode->slot_count()/2)
{
// error handling
delete_operator_batching(encr);
delete_operator_batching(eval);
return -1;
}
else
{
Ciphertext encrypted_result_matrix;
vector<int64_t> result_matrix;
init_ciphermatrix(encr, result_matrix, encrypted_result_matrix);
vector<int64_t> dummy_matrix;
for (size_t i = 0; i < sample_size; i++)
{
dummy_matrix.push_back(1);
}
Ciphertext encrypted_dummy_matrix;
init_ciphermatrix(encr, dummy_matrix, encrypted_dummy_matrix);
// normalize input data if its size is odd
int normalized_data_size;
if (data.size() % 2 == 0)
{
normalized_data_size = data.size();
}
else
{
normalized_data_size = data.size() + 1;
}
int required_range = normalized_data_size * sample_size;
int required_no_row_elements = required_range / 2;
int required_range_row = required_range / 2;
// create padding matrix
int padding_slots = (encr.bcode->slot_count() / 2) - required_range_row;
vector<int64_t> padding_matrix(encr.bcode->slot_count(), 0ULL);
for (size_t i = 0; i < padding_slots; i++)
{
padding_matrix[required_no_row_elements + i] = 1;
padding_matrix[encr.bcode->slot_count() - i] = 1;
}
Ciphertext encrypted_padding_matrix;
init_ciphermatrix(encr, padding_matrix, encrypted_padding_matrix);
if (required_range_row <= encr.bcode->slot_count() && required_range_row > 0)
{
for (int index = 0; index < normalized_data_size / 2; index++)
{
Ciphertext ct1, ct2, ct3;
Ciphertext temp1, temp2;
// cout << "[INFO] loading ciphertext 1" << endl;
load_ciphertext(eval, ct1, source);
// cout << "[INFO] loading ciphertext 2" << endl;
load_ciphertext(eval, ct2, data.at(index));
sub_ciphertext(eval, ct1, ct2, temp1);
if ((normalized_data_size / 2) + index < data.size())
{
// cout << "[INFO] loading ciphertext 3" << endl;
load_ciphertext(eval, ct3, data.at((normalized_data_size / 2) + index));
sub_ciphertext(eval, ct1, ct3, temp2);
}
else
{
// add dummy vector for oddy data
temp2 = encrypted_dummy_matrix;
}
eval.eval->rotate_columns_inplace(temp2, eval.gk);
add_ciphertext(eval, temp1, temp2, temp1);
add_ciphertext(eval, temp1, encrypted_result_matrix, encrypted_result_matrix);
// avoid the last shift
if (index + 1 != (normalized_data_size / 2))
{
eval.eval->rotate_rows_inplace(encrypted_result_matrix, -sample_size, eval.gk);
}
}
// add renmaining padding slots
add_ciphertext(eval, encrypted_result_matrix, encrypted_padding_matrix, encrypted_result_matrix);
}
save_ciphertext(encrypted_result_matrix, result_dir + "/" + result_name + ".ct");
delete_operator_batching(encr);
delete_operator_batching(eval);
return 0;
}
}
// int checkSq(
// string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size,
// string &relink_key_path, string &galois_key_path, string &public_key_path)
int checkSq(
string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir)
{
struct evaluator_t eval;
// init_operator_batching(2048, 4294967296, eval, relink_key_path, galois_key_path);
// init_operator_batching(4096, 4294967296, eval, relink_key_path, galois_key_path);
// init_operator_batching(8192, 4294967296, eval, relink_key_path, galois_key_path);
// init_operator_batching(16384, 4294967296, eval, relink_key_path, galois_key_path);
// init_operator_batching(32768, 4294967296, eval, relink_key_path, galois_key_path);
init_operator_batching(eval, key_dir);
struct encryptor_t encr;
// init_operator_batching(4096, 4294967296, encr, public_key_path);
// init_operator_batching(8192, 4294967296, encr, public_key_path);
// init_operator_batching(16384, 4294967296, encr, public_key_path);
// init_operator_batching(32768, 4294967296, encr, public_key_path);
init_operator_batching(encr, key_dir);
// if (sample_size*data.size() > encr.bcode->slot_count() || sample_size > encr.bcode->slot_count()/2)
if (sample_size > encr.bcode->slot_count()/2)
{
// error handling
delete_operator_batching(encr);
delete_operator_batching(eval);
return -1;
}
else
{
// struct evaluator_t eval;
// // init_operator_batching(2048, 4294967296, eval, relink_key_path, galois_key_path);
// // init_operator_batching(4096, 4294967296, eval, relink_key_path, galois_key_path);
// init_operator_batching(8192, 4294967296, eval, relink_key_path, galois_key_path);
// // init_operator_batching(16384, 4294967296, eval, relink_key_path, galois_key_path);
// // init_operator_batching(32768, 4294967296, eval, relink_key_path, galois_key_path);
// struct encryptor_t encr;
// // init_operator_batching(4096, 4294967296, encr, public_key_path);
// init_operator_batching(8192, 4294967296, encr, public_key_path);
// // init_operator_batching(16384, 4294967296, encr, public_key_path);
// // init_operator_batching(32768, 4294967296, encr, public_key_path);
int capacity = (encr.bcode->slot_count()) / sample_size;
// cout << capacity << endl;
// vector<string> v_temp;
// vector<string> v_v_temp;
// Ciphertext result;
vector<Ciphertext> v_result;
int nSq = data.size() / capacity;
for (size_t i = 0; i < nSq; i++)
{
Ciphertext result;
// cout << "sq : " << i << endl;
vector<string> v_temp;
for (size_t j = 0; j < capacity; j++)
{
string str = data.back();
v_temp.push_back(str);
data.pop_back();
}
if (i == 0)
{
// cout << "sq : init" << endl;
// result = check(
// source, v_temp, result_name, result_dir, sample_size, relink_key_path, galois_key_path,
// public_key_path, encr, eval);
result = check(source, v_temp, result_name, result_dir, sample_size, key_dir, encr, eval);
v_result.push_back(result);
}
else
{
// cout << "sq : other" << endl;
// Ciphertext result2 = check(
// source, v_temp, result_name, result_dir, sample_size, relink_key_path, galois_key_path,
// public_key_path, encr, eval);
// multiply_ciphertext(eval, result2, result, result);
// relinearize_inplace(eval, result);
// result = check(
// source, v_temp, result_name, result_dir, sample_size, relink_key_path, galois_key_path,
// public_key_path, encr, eval);
result = check(source, v_temp, result_name, result_dir, sample_size, key_dir, encr, eval);
v_result.push_back(result);
}
}
if (data.size() % capacity != 0)
{
// cout << "oddy!!! " << endl;
// Ciphertext result = check(
// source, data, result_name, result_dir, sample_size, relink_key_path, galois_key_path,
// public_key_path, encr, eval);
Ciphertext result = check(source, data, result_name, result_dir, sample_size, key_dir, encr, eval);
// multiply_ciphertext(eval, result2, result, result);
// relinearize_inplace(eval, result);
v_result.push_back(result);
}
Ciphertext result;
multiply_ciphertexts(eval, v_result, result);
relinearize_inplace(eval, result);
save_ciphertext(result, result_dir + "/" + result_name + ".ct");
delete_operator_batching(encr);
delete_operator_batching(eval);
return 0;
}
}
// Ciphertext check(
// string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size,
// string &relink_key_path, string &galois_key_path, string &public_key_path, struct encryptor_t &encr,
// struct evaluator_t &eval)
Ciphertext check(
string &source, vector<string> &data, string &result_name, string &result_dir, int &sample_size, string &key_dir,
struct encryptor_t &encr, struct evaluator_t &eval)
{
// if (source == "" || data.size() == 0 || result_name == "" || result_dir == "" || sample_size == 0)
// {
// // error handling
// // return -1;
// }
// else
// {
Ciphertext encrypted_result_matrix;
vector<int64_t> result_matrix;
init_ciphermatrix(encr, result_matrix, encrypted_result_matrix);
vector<int64_t> dummy_matrix;
for (size_t i = 0; i < sample_size; i++)
{
dummy_matrix.push_back(1);
}
Ciphertext encrypted_dummy_matrix;
init_ciphermatrix(encr, dummy_matrix, encrypted_dummy_matrix);
// normalize input data if its size is odd
int normalized_data_size;
if (data.size() % 2 == 0)
{
normalized_data_size = data.size();
}
else
{
normalized_data_size = data.size() + 1;
}
int required_range = normalized_data_size * sample_size;
int required_no_row_elements = required_range / 2;
int required_range_row = required_range / 2;
// create padding matrix
int padding_slots = (encr.bcode->slot_count() / 2) - required_range_row;
vector<int64_t> padding_matrix(encr.bcode->slot_count(), 0ULL);
for (size_t i = 0; i < padding_slots; i++)
{
padding_matrix[required_no_row_elements + i] = 1;
padding_matrix[encr.bcode->slot_count() - i] = 1;
}
Ciphertext encrypted_padding_matrix;
init_ciphermatrix(encr, padding_matrix, encrypted_padding_matrix);
if (required_range_row <= encr.bcode->slot_count() && required_range_row > 0)
{
for (int index = 0; index < normalized_data_size / 2; index++)
{
Ciphertext ct1, ct2, ct3;
Ciphertext temp1, temp2;
// cout << "[INFO] loading ciphertext 1" << endl;
load_ciphertext(eval, ct1, source);
// cout << "[INFO] loading ciphertext 2" << endl;
load_ciphertext(eval, ct2, data.at(index));
sub_ciphertext(eval, ct1, ct2, temp1);
if ((normalized_data_size / 2) + index < data.size())
{
// cout << "[INFO] loading ciphertext 3" << endl;
load_ciphertext(eval, ct3, data.at((normalized_data_size / 2) + index));
sub_ciphertext(eval, ct1, ct3, temp2);
}
else
{
// add dummy vector for oddy data
temp2 = encrypted_dummy_matrix;
}
eval.eval->rotate_columns_inplace(temp2, eval.gk);
add_ciphertext(eval, temp1, temp2, temp1);
add_ciphertext(eval, temp1, encrypted_result_matrix, encrypted_result_matrix);
// avoid the last shift
if (index + 1 != (normalized_data_size / 2))
{
eval.eval->rotate_rows_inplace(encrypted_result_matrix, -sample_size, eval.gk);
}
}
// add renmaining padding slots
add_ciphertext(eval, encrypted_result_matrix, encrypted_padding_matrix, encrypted_result_matrix);
}
// // save_ciphertext(encrypted_result_matrix, result_dir + "/" + result_name + ".ct");
// delete_operator_batching(eval);
return encrypted_result_matrix;
// }
}
void sub_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out)
{
op_st.eval->sub(ct1, ct2, ct_out);
}
void sub_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2)
{
op_st.eval->sub_inplace(ct1, ct2);
}
void sub_plain_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain)
{
op_st.eval->sub_plain_inplace(ct, plain);
}
void negate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct)
{
op_st.eval->negate_inplace(ct);
}
void add_plain_inplace_ciphertext(struct evaluator_t &op_st, struct Ciphertext &ct, const Plaintext &plain)
{
op_st.eval->add_plain_inplace(ct, plain);
}
void add_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out)
{
op_st.eval->add(ct1, ct2, ct_out);
}
void add_many_ciphertext(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out)
{
op_st.eval->add_many(cts, ct_out);
}
void multiply_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2, Ciphertext &ct_out)
{
op_st.eval->multiply(ct1, ct2, ct_out);
}
void multiply_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct1, Ciphertext &ct2)
{
op_st.eval->multiply_inplace(ct1, ct2);
}
void multiply_ciphertexts(struct evaluator_t &op_st, vector<Ciphertext> &cts, Ciphertext &ct_out)
{
op_st.eval->multiply_many(cts, op_st.lk, ct_out);
}
void multiply_plain_inplace(struct evaluator_t &op_st, Ciphertext &ct, const Plaintext &plain)
{
op_st.eval->multiply_plain_inplace(ct, plain);
}
void relinearize_inplace(struct evaluator_t &op_st, Ciphertext &ct)
{
op_st.eval->relinearize_inplace(ct, op_st.lk);
}
void relinearize(struct evaluator_t &op_st, Ciphertext &ct, Ciphertext &ct_out)
{
op_st.eval->relinearize(ct, op_st.lk, ct_out);
}
void rescale_to_next_inplace(struct evaluator_t &op_st, Ciphertext &ct)
{
op_st.eval->rescale_to_next_inplace(ct);
}
void exponentiate_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct, uint64_t &exponent)
{
op_st.eval->exponentiate_inplace(ct, exponent, op_st.lk);
}
void mod_switch_to_next_inplace_ciphertext(struct evaluator_t &op_st, Ciphertext &ct)
{
op_st.eval->mod_switch_to_next_inplace(ct);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment